Docker + Nginx + Let’s EncryptでHTTPS対応のプロキシサーバーを構築する

Docker上にNginxコンテナをプロキシサーバーとして構築し、Let’s EncryptでHTTPS対応しました。構築にあたって かなり苦戦した ので、そのノウハウを記事としてまとめました。

「Nginx」とは

Apacheなどの従来のWebサーバーは、クライアントの数が多くなるとサーバーがパンクする 「C10K問題(クライアント1万台問題)」 を抱えていました。「Nginx」はこの問題を解決するために誕生した、静的コンテンツを高速配信するWebサーバーです。2017年10月現在、そのシェアは Apacheとほぼ同等 となっています。

wpid-wss-share13.png

Webサーバー シェア
Micosoft IIS 49.44%
Apache 18.78%
Nginx 18.40%

「Let’s Encrypt」とは

「Let’s Encrypt」は すべてのWebサーバへの接続を暗号化する ことを目指し、SSL/TLSサーバ証明書を 無料 で発行する認証局(CA)です。シスコ、Akamai、電子フロンティア財団、モジラ財団などの大手企業・団体がスポンサーとして支援しています。


本稿が目指すシステム構成

本稿ではAmazon EC2、Dockerコンテナを使用して以下のようなシステムを構築することを目標とします。

DockerでNgixのプロキシサーバーを構築する.png

前提条件

  • 独自ドメインを取得していること(本稿で使用するドメインはexample.comとします)
  • IPv4パブリックIP(Elastic IP)がEC2インスタンスに設定されていること
  • EC2インスタンスにDocker、docker-composeがインストールされていること

事前に準備すること

DockerでHTTPS対応のプロキシサーバーを構築するにあたり、事前に以下の設定をしておく必要があります。

  • EC2のインバウンドルールで443ポートを開放する
  • DNSのAレコードを設定する
  • プロキシ用のネットワークを構築する

EC2のインバウンドルールで443ポートを開放する

インバウンドルールを以下のように設定し、443ポートを外部へ公開します。

タイプ プロトコル ポート範囲 ソース
HTTPS TCP 443 0.0.0.0/0
HTTPS TCP 443 ::/0

DNSのAレコードを設定する

DNSの設定方法は利用しているドメイン取得サービスによって異なります。例えばバリュードメインの場合、DNSの設定方法は「DNS情報・URL転送の設定 | VALUE-DOMAIN ユーザーガイド」に記載されています。

DNSのAレコードを以下のように設定します。xx.xx.xx.xxにはEC2インスタンスに割り当てられているIPv4パブリックIPを設定します。

a @ xx.xx.xx.xx
a www xx.xx.xx.xx

上記設定は以下を意味します。

  • example.com(サブドメイン無し)をIPアドレスxx.xx.xx.xxにポイントする
  • www.example.com をIPアドレスxx.xx.xx.xxにポイントする

プロキシ用のネットワークを構築する

プロキシサーバーとWebサーバー間のネットワークは外部との通信を行う必要がありません。そこで
プロキシサーバーとWebサーバー間の 内部ネットワーク を構築するため、EC2のインスタンスにログインし、以下のコマンドを入力します。

$ docker network create --internal sample_proxy_nw

上記コマンドは以下を意味します。

  • --internal: ネットワーク外との通信が行えないネットワークを作成します。
  • sample_proxy_nw: 任意のネットワーク名です。

以下のコマンドを入力し、ネットワークの設定情報がコンソールに出力されていることを確認しましょう。

$ docker network inspect sample_proxy_nw

Dockerコンテナの定義ファイルを作成する

事前準備が完了したら、Dockerコンテナの定義ファイルを作成しましょう。本稿におけるディレクトリ構成は以下のとおりです。

/path/to/dir/

.
├── docker-compose.yml // プロキシサーバーとWebサーバーのコンテナを定義するファイル
└── proxy
    ├── default.conf // プロキシサーバー上にあるNginxのデフォルト定義ファイル
    ├── Dockerfile // プロキシサーバーのイメージを構築するためのファイル
    └── entrypoint.sh // プロキシサーバーにSSL証明書を取得するためのファイル

以下では、各ファイルの内容を解説します。

./docker-compose.yml

docker-compose.ymlでは、以下のコンテナを定義しています。

  • proxy: プロキシサーバー(Nginxベース)
  • web1: Webサーバー(httpdベース)
  • web2: Webサーバー(httpdベース)
version: '3'
services:
  proxy:
    build: ./proxy
    tty: true
    image: sample_proxy
    container_name: sample_proxy
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
    ports:
      - "443:443"
    volumes:
      - '/srv/letsencrypt:/etc/letsencrypt'
    networks:
      - default
      - sample_proxy_nw
    depends_on:
      - "web1"
      - "web2"
    command: ["wait-for-it.sh", "sample_web1:80", "--", "./wait-for-it.sh", "sample_web2:80"]
  web1:
    image: httpd
    container_name: sample_web1
    tty: true
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
    networks:
      - sample_proxy_nw
  web2:
    image: httpd
    container_name: sample_web2
    tty: true
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
    networks:
      - sample_proxy_nw
networks:
  proxy_nw:
    external: true

上記コマンドは以下を意味します。

  • サービスproxyports: 外部からのHTTPSアクセスとproxyサーバーの内部ポートを疎通させるため、443:443を定義します。
  • サービスproxyvolumes: /srv/letsencrypt:/etc/letsencryptを定義します。/etc/letsencryptLet’s Encryptで取得した証明書が生成されるディレクトリ です。
  • networks: 上述の説明で生成したsample_proxy_nwを各サービス(proxy, web1, web2)に定義します。
  • depends_on: コンテナの起動順序を制御するオプションです。 Nginxのproxy_passに設定されているWebサーバーが起動していない状態でプロキシサーバーが起動した場合にエラーとなる ため、web1, web2を設定します。

./proxy/default.conf

./proxy/default.confはNginxのデフォルト定義ファイル(/etc/nginx/conf.d/default.conf)を書き換えるためのファイルです。

server{

    server_name example.com www.example.com;

    proxy_redirect off;
    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 / {
        proxy_pass    http://sample_web1/;
    }

    location /example/ {
        proxy_pass    http://sample_web2/;
    }

}

上記設定は以下を意味します。

  • server_name: ユーザーから要求されるHTTPリクエストのヘッダに含まれるHostフィールドとserver_nameが一致した場合、該当するサーバ設定を採用します。Nginxではキャッチオールサーバーとして_を定義することもできますが、 certbot-autoがサーバー情報を正しく取得することができない ため、上記のようにドメイン名を入力します。
  • location: ルートディレクトリ(example.com/)とサブディレクトリ(example.com/example/)にアクセスした際の振り分け先URIを設定します。proxy_passには、http://[コンテナ名]/を設定します。コンテナ名はdocker-compose.ymlのcontainer_nameで設定した名前となります。
    また、http://sample_web1/のように 末尾に/を入れる ことに注意しましょう。例えばlocation /example/において、プロキシパスの末尾に/が含まれていない(http://sample_web2)場合、振り分け先は http://sample_web2/example/となってしまいます。

./proxy/Dockerfile

FROM nginx
COPY default.conf /etc/nginx/conf.d/default.conf
RUN apt-get update && apt-get install -y \
        wget && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*
ADD https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh /usr/local/bin/wait-for-it.sh
RUN chmod +x /usr/local/bin/wait-for-it.sh
ADD https://dl.eff.org/certbot-auto /usr/local/bin/certbot-auto
RUN chmod a+x /usr/local/bin/certbot-auto
RUN certbot-auto --os-packages-only -n
COPY ./entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]

上記設定は以下を意味します。

  • ADD https://dl.eff.org/certbot-auto /usr/local/bin/certbot-auto: Let’s Encryptが発行するSSL/TLSサーバ証明書を自動で取得・更新するツール「 certbot-auto 」をダウンロードします。

./proxy/entrypoint.sh

#!/bin/bash
certbot-auto --nginx -d example.com -d www.example.com -m your-account@gmail.com --agree-tos -n
certbot-auto renew
/bin/bash

上記設定は以下を意味します。

  • --nginx: プロキシサーバーにNginxを使用する場合のオプションです。default.confの設定を自動的に書き換えます。(2017年12月現在、アルファ版のプラグイン)
  • -d example.com -d www.example.com: SSL/TLSサーバ証明書の取得を申請するドメイン名を指定します。
  • -m your-account@gmail.com: アカウントの登録や回復などに使用する電子メールアドレスを指定します。
  • --agree-tos: Let’s Encryptの利用規約に同意します。
  • -n: インタラクティブ設定をオフにします。
  • ./certbot-auto renew: 3ヶ月で失効する SSL/TLSサーバ証明書を自動で更新します。

以下のコマンドを入力してentrypoint.shに 実行権限を付与する ことを忘れないようにしましょう。

$ chmod +x entrypoint.sh

Dockerコンテナを起動する

それでは以下のコマンドを入力してDockerコンテナを起動しましょう。

docker-compose up -d

しばらく時間をおいてから、以下のコマンドを入力します。

docker-compose logs

以下のように出力されていれば成功です。

-------------------------------------------------------------------------------
Congratulations! You have successfully enabled https://example,com and
https://www.example.com

You should test your configuration at:
https://www.ssllabs.com/ssltest/analyze.html?d=example.com
https://www.ssllabs.com/ssltest/analyze.html?d=www.example.com
-------------------------------------------------------------------------------

HTTPSでアクセスする

ブラウザを起動し、実際に以下のURLにアクセスしてみましょう。

Chromeブラウザの場合はデベロッパーツール > Security > View certificateからSSL/TLSサーバ証明書を確認することができます。

「発行元: Let’s Encrypt Authority X3」となっているはずです。

続きを読む

CloudFormationとecs-cliを使って「Fargate+NLB+fluentd」環境を作成する。

AWS Fargateが発表されたのでさっそくつかってみます。
今回はFargateの上でfluentdコンテナを実行します。

手順

  1. CloudFromationのテンプレートでECSクラスタやNLBなどのAWSリソースを作ります。
  2. fluentdのDockerfiledocker-compose.ymlecs-params.ymlを作ります。
  3. fluentdのDockerイメージを作成し、ECRにpushします。
  4. ecs-cliコマンドでFargateにデプロイします。
  5. ecs-cli logsコマンドで接続を受け付けていることを確認します。

CloudFormationテンプレート

  • VPCから一気に作ります。
AWSTemplateFormatVersion: '2010-09-09'

Description: ""

Parameters:
  VPCCidr:
    Description: ""
    Type: String
    Default: "10.1.0.0/16"
  EnableDnsSupport:
    Description: ""
    Type: String
    Default: true
    AllowedValues:
      - true
      - false
  EnableDnsHostnames:
    Description: ""
    Type: String
    Default: true
    AllowedValues:
      - true
      - false
  InstanceTenancy:
    Description: ""
    Type: String
    Default: default
    AllowedValues:
      - default
      - dedicated
  SubnetCidrA:
    Description: ""
    Type: String
    Default: "10.1.10.0/24"
  SubnetCidrB:
    Description: ""
    Type: String
    Default: "10.1.20.0/24"
  AvailabilityZoneA:
    Description: ""
    Type: String
    Default: us-east-1a
  AvailabilityZoneB:
    Description: ""
    Type: String
    Default: us-east-1b
  MapPublicIpOnLaunch:
    Description: ""
    Type: String
    Default: true
    AllowedValues:
      - true
      - false
  AttachInternetGateway:
    Description: ""
    Type: String
    Default: "true"
    AllowedValues:
      - true
      - false
  Schema:
    Description: ""
    Type: String
    Default: "internet-facing"
    AllowedValues:
      - "internet-facing"
      - "internal"
  ListenerPort:
    Description: ""
    Type: String
    Default: "24224"
  TargetGroupPort:
    Description: ""
    Type: String
    Default: "24224"
  TargetType:
    Description: ""
    Type: String
    Default: "ip"
    AllowedValues:
      - "ip"
      - "instance"

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: "Network Configuration"
        Parameters:
          - VPCCidr
          - EnableDnsSupport
          - EnableDnsHostnames
          - InstanceTenancy
          - SubnetCidrA
          - SubnetCidrB
          - AvailabilityZoneA
          - AvailabilityZoneB
          - MapPublicIpOnLaunch
          - AttachInternetGateway
      - Label:
          default: "NetworkLoadBalancer Configuration"
        Parameters:
          - Schema
          - ListenerPort
          - TargetGroupPort
          - TargetType

Outputs:
  Cluster:
    Value: !Ref Cluster
  TargetGroupArn:
    Value: !Ref TargetGroup
  SubnetA:
    Value: !Ref SubnetA
  SubnetB:
    Value: !Ref SubnetB
  SecurityGroup:
    Value: !GetAtt SecurityGroup.GroupId
  IAMRole:
    Value: !GetAtt IAMRole.Arn
  Repository:
    Value: !Ref Repository

Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VPCCidr
      EnableDnsSupport: !Ref EnableDnsSupport
      EnableDnsHostnames: !Ref EnableDnsHostnames
      InstanceTenancy: !Ref InstanceTenancy
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}.vpc"

  RouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}.rtable"

  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}.igw"

  AttachGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      InternetGatewayId: !Ref InternetGateway
      VpcId: !Ref VPC

  Route:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref RouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  SubnetA:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: !Ref SubnetCidrA
      AvailabilityZone: !Ref AvailabilityZoneA
      MapPublicIpOnLaunch: !Ref MapPublicIpOnLaunch
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}.subnet"

  SubnetARouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref SubnetA
      RouteTableId: !Ref RouteTable

  SubnetB:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: !Ref SubnetCidrB
      AvailabilityZone: !Ref AvailabilityZoneB
      MapPublicIpOnLaunch: !Ref MapPublicIpOnLaunch
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}.subnet"

  SubnetBRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref SubnetB
      RouteTableId: !Ref RouteTable

  SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: "SecurityGroup"
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - CidrIp: !Ref VPCCidr
          IpProtocol: "tcp"
          FromPort: "24224"
          ToPort: "24224"
        - CidrIp: 0.0.0.0/0
          IpProtocol: "tcp"
          FromPort: "24224"
          ToPort: "24224"
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}.sg"

  Cluster:
    Type: AWS::ECS::Cluster
    Properties:
      ClusterName: !Ref AWS::StackName

  LoadBalancer:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Name: !Sub "${AWS::StackName}-nlb"
      Type: "network"
      Scheme: !Ref Schema
      Subnets:
        - !Ref SubnetA
        - !Ref SubnetB
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}.nlb"

  Listener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      LoadBalancerArn: !Ref LoadBalancer
      Port: !Ref ListenerPort
      Protocol: "TCP"
      DefaultActions:
        - Type: forward
          TargetGroupArn: !Ref TargetGroup

  TargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    DependsOn: LoadBalancer
    Properties:
      Name: !Sub "${AWS::StackName}-tg"
      Port: !Ref TargetGroupPort
      Protocol: "TCP"
      VpcId: !Ref VPC
      TargetType: !Ref TargetType
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}.targetgroup"

  IAMRole:
    Type: "AWS::IAM::Role"
    Properties:
      RoleName: !Sub "${AWS::StackName}.role"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: "Allow"
            Action:
              - "sts:AssumeRole"
            Principal:
              Service:
                - "ecs-tasks.amazonaws.com"
      Policies:
        - PolicyName: !Sub "${AWS::StackName}.policy"
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: "Allow"
                Resource: "*"
                Action:
                  - "ecr:GetAuthorizationToken"
                  - "ecr:BatchCheckLayerAvailability"
                  - "ecr:GetDownloadUrlForLayer"
                  - "ecr:BatchGetImage"
                  - "logs:CreateLogStream"
                  - "logs:PutLogEvents"

  LogGroup:
    Type: "AWS::Logs::LogGroup"
    Properties:
      LogGroupName: !Sub "${AWS::StackName}/fluentd"
      RetentionInDays: 3

  Repository:
    Type: "AWS::ECR::Repository"
    Properties:
      RepositoryName: !Sub "${AWS::StackName}/fluentd"
  • ポイント

    1. NLBにはSecurityGroupはアタッチできない。
    2. コンテナにはVPC Cidrからのアクセスを許可する必要がある。これがないとヘルスチェックが失敗する。
    3. コンテナはロググループを自動生成しない。あらかじめロググループを作成しておく必要がある。

Stackの作成

  • AWSコンソールからCloudFormationを選択してStackを作成します。

cfn

  • しばらく待ちます。

creating

  • 完成です。

created

コンテナの設定

  • 以下のディレクトリ構成で設定ファイルを書きます。
├── Makefile
└── fluentd
    ├── Dockerfile
    ├── docker-compose.yml
    ├── ecs-params.yml
    ├── fluent.conf
    └── plugins //今回は空ディレクトリでok

fluent.conf

  • 標準出力に吐き出すだけです。
  • CloudWatchLogsに転送されます。
<source>
  type forward
  bind 0.0.0.0
  port 24224
</source>

<match **>
  type stdout
</match>

Dockerfile

FROM fluent/fluentd
COPY fluent.conf /fluentd/etc

docker-compose.yml

  • ${AWS::Account}はAWSアカウントID、${AWS::StackName}はCloudFormationで作成したスタックの名前を入れます。
version: '2'
services:
  fluentd:
    image: ${AWS::Account}.dkr.ecr.us-east-1.amazonaws.com/${AWS::StackName}/fluentd
    ports:
      - "24224:24224"
    logging:
      driver: "awslogs"
      options:
        awslogs-region: "us-east-1"
        awslogs-group: "${AWS::StackName}/fluentd"
        awslogs-stream-prefix: "container"

ecs-params.yml

  • ${SubnetA}, ${SubnetB}, ${SecurityGroup}はCloudFormationで作成したリソースのIDを入れます。
  • CloudFormationの「出力」タブに作成したリソースの一覧が表示されているのでコピペします。
  • 自動生成してほしい。
version: 1
task_definition:
  ecs_network_mode: awsvpc
  task_execution_role: arn:aws:iam::${AWS::Account}:role/${AWS::StackName}.role
  task_size:
    cpu_limit: 0.25
    mem_limit: 0.5GB
  services:
    fluentd:
      essential: true

run_params:
  network_configuration:
    awsvpc_configuration:
      subnets:
        - ${SubnetA}
        - ${SubnetB}
      security_groups:
        - ${SecurityGroup}
      assign_public_ip: ENABLED
  • この設定ファイルをみて分かる通り、Fargate(正確にはawsvpcモード)ではコンテナに直接サブネットやセキュリティグループをアタッチします。
  • EC2インスタンスのような感覚でコンテナを扱えます。

Makefile

  • たくさんコマンドをうつのでMakefileをつくっておきます。
push:
    docker build -f fluentd/Dockerfile -t ${AWS::Account}.dkr.ecr.us-east-1.amazonaws.com/${AWS::StackName}/fluentd fluentd
    `aws ecr get-login --no-include-email --region us-east-1`
    docker push ${AWS::Account}.dkr.ecr.us-east-1.amazonaws.com/${AWS::StackName}/fluentd:latest

up:
    cd fluentd; 
    ecs-cli compose service up 
        --cluster ${AWS::StackName} 
        --target-group-arn ${TargetGroupArn} 
        --launch-type FARGATE 
        --container-name fluentd 
        --container-port 24224 
        --region us-east-1 
        --timeout 10

rm:
    cd fluentd; 
    ecs-cli compose service rm 
    --cluster ${AWS::StackName} 
    --region us-east-1 
    --timeout 10

Deploy

  • イメージを作ってECRにpushします。
$ make push
docker build -f fluentd/Dockerfile -t ************.dkr.ecr.us-east-1.amazonaws.com/fargate/fluentd fluentd
Sending build context to Docker daemon  5.632kB
Step 1/2 : FROM fluent/fluentd
 ---> 060874232311
Step 2/2 : COPY fluent.conf /fluentd/etc
 ---> Using cache
 ---> 1ee08befeb8d
Successfully built 1ee08befeb8d
Successfully tagged ************.dkr.ecr.us-east-1.amazonaws.com/fargate/fluentd:latest
`aws ecr get-login --no-include-email --region us-east-1`
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
Login Succeeded
docker push ************.dkr.ecr.us-east-1.amazonaws.com/fargate/fluentd:latest
The push refers to a repository [************.dkr.ecr.us-east-1.amazonaws.com/fargate/fluentd]
baa346e06fe3: Pushed 
fe129fa31f70: Pushed 
dcf88bef8f3a: Pushed 
b59190601542: Pushed 
56e1e5a28df0: Pushed 
9fc62b353b50: Pushed 
26fbe6ae586e: Pushed 
16174e87921f: Pushed 
latest: digest: sha256:9f8c90b5fc10c084f93c5a93c038f4d307676b4fb641a8a36d67f4573655d52f size: 1981
  • Fargateにデプロイします。
$ make up
cd fluentd; 
    ecs-cli compose service up 
    --cluster fargate 
    --target-group-arn arn:aws:elasticloadbalancing:us-east-1:************:targetgroup/fargate-tg/**** 
    --launch-type FARGATE 
    --container-name fluentd 
    --container-port 24224 
    --region us-east-1 
    --timeout 10
WARN[0000] Skipping unsupported YAML option...           option name=networks
WARN[0000] Skipping unsupported YAML option for service...  option name=networks service name=fluentd
INFO[0001] Using ECS task definition                     TaskDefinition="fluentd:12"
INFO[0002] Created an ECS service                        service=fluentd taskDefinition="fluentd:12"
INFO[0002] Updated ECS service successfully              desiredCount=1 serviceName=fluentd
INFO[0017] (service fluentd) has started 1 tasks: (task 7228958b-0de1-4e31-a6b2-52d35b6c7b84).  timestamp=2017-12-07 02:14:52 +0000 UTC
INFO[0139] Service status                                desiredCount=1 runningCount=1 serviceName=fluentd
INFO[0139] ECS Service has reached a stable state        desiredCount=1 runningCount=1 serviceName=fluentd

確認

  • ログを取得します。
$ ecs-cli ps --cluster fargate --region us-east-1
Name                                          State                Ports                         TaskDefinition
7228958b-0de1-4e31-a6b2-52d35b6c7b84/fluentd  RUNNING              **.**.**.**:24224->24224/tcp  fluentd:12

$ ecs-cli logs --cluster fargate --region us-east-1 --task-id 7228958b-0de1-4e31-a6b2-52d35b6c7b84
2017-12-07 02:17:03 +0000 [info]: reading config file path="/fluentd/etc/fluent.conf"
2017-12-07 02:17:03 +0000 [info]: starting fluentd-0.12.40
2017-12-07 02:17:03 +0000 [info]: gem 'fluentd' version '0.12.40'
2017-12-07 02:17:03 +0000 [info]: adding match pattern="**" type="stdout"
2017-12-07 02:17:03 +0000 [info]: adding source type="forward"
2017-12-07 02:17:03 +0000 [info]: using configuration file: <ROOT>
  <source>
    type forward
    bind 0.0.0.0
    port 24224
  </source>

  <match **>
    type stdout
  </match>
</ROOT>
2017-12-07 02:17:03 +0000 [info]: listening fluent socket on 0.0.0.0:24224
  • 正常に起動しています。
  • fluent-cattelnetで接続するとログが出力されます。

削除

  • 作成したリソースを消しておかないとお金を取られます。
  • コンテナを削除してから、AWSリソースを削除します。
$ make rm
cd fluentd; 
    ecs-cli compose service rm 
    --cluster fargate 
    --region us-east-1 
    --timeout 10
WARN[0000] Skipping unsupported YAML option...           option name=networks
WARN[0000] Skipping unsupported YAML option for service...  option name=networks service name=fluentd
INFO[0001] Updated ECS service successfully              desiredCount=0 serviceName=fluentd
INFO[0001] Service status                                desiredCount=0 runningCount=1 serviceName=fluentd
INFO[0017] (service fluentd) has begun draining connections on 1 tasks.  timestamp=2017-12-07 02:44:53 +0000 UTC
INFO[0017] (service fluentd) deregistered 1 targets in (target-group arn:aws:elasticloadbalancing:us-east-1:************:targetgroup/fargate-tg/****)  timestamp=2017-12-07 02:44:53 +0000 UTC
INFO[0321] Service status                                desiredCount=0 runningCount=0 serviceName=fluentd
INFO[0321] ECS Service has reached a stable state        desiredCount=0 runningCount=0 serviceName=fluentd
INFO[0321] Deleted ECS service                           service=fluentd
INFO[0322] ECS Service has reached a stable state        desiredCount=0 runningCount=0 serviceName=fluentd
  • AWSコンソールでECRリポジトリを削除します。

    • CloudFromationで作成したリポジトリにイメージが登録されていると、CloudFormationでは削除できません。
  • AWSコンソール -> CloudFromation -> Stackの削除をします。

使ってみた感想

今まではECSクラスタを構成するEC2インスタンスの制限を受けて使いにくい部分(動的ポートマッピングとかawsvpcのeni制限とかスケールとか)がありましたが、Fargateによってそれらが一気に解決しました。AWSでコンテナ運用するならFargate一択ですね。

参考

  1. AWS Fargate: サービス概要
  2. GitHub – aws/amazon-ecs-cli

続きを読む

AWS 上に JobScheduler を構築した話

AWSには自前でジョブ実行用のサービスがあるので、こういうのはあまりやらないと思いますが、色々とハマったのでメモ。

インストール

JobScheduler インストール

  1. インストーラーをここからダウンロードします。

    スクリーンショット 2017-06-08 0.33.37.png

  2. 解凍した中にある jobscheduler_install.xml を以下の形に修正します。

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <!--
    XML configuration file for JobScheduler setup
    
    The JobScheduler is available with a dual licensing model.
    - GNU GPL 2.0 License (see http://www.gnu.org/licenses/gpl-2.0.html)
    - JobScheduler Commercial License (see licence.txt)
    
    The setup asks you for the desired license model
    (see <entry key="licenceOptions" .../> below).
    
    If you call the setup with this XML file then you accept
    at the same time the terms of the chosen license agreement.
    -->
    <AutomatedInstallation langpack="eng">
    <com.izforge.izpack.panels.UserInputPanel id="home">
        <userInput/>
    </com.izforge.izpack.panels.UserInputPanel>
    <com.izforge.izpack.panels.UserInputPanel id="licences">
        <userInput>
    
            <!-- Select the license model (GPL or Commercial) -->
            <entry key="licenceOptions" value="GPL"/>
    
            <!-- If you selected GPL as license model than the licence must be empty.
                 Otherwise please enter a license key if available.
                 It is also possible to modify the license key later. -->
            <entry key="licence" value=""/>
    
        </userInput>
    </com.izforge.izpack.panels.UserInputPanel>
    <com.izforge.izpack.panels.HTMLLicencePanel id="gpl_licence"/>
    <com.izforge.izpack.panels.HTMLLicencePanel id="commercial_licence"/>
    <com.izforge.izpack.panels.TargetPanel id="target">
    
        <!-- SELECT THE INSTALLATION PATH FOR THE BINARIES AND LIBRARIES
             The installation expands this path with the Scheduler ID as subdirectory.
             The path must be absolute!
             Default paths are
             /opt/sos-berlin.com/jobscheduler for Unix
             C:Program Filessos-berlin.comjobscheduler for Windows -->
        <installpath>/opt/sos-berlin.com/jobscheduler</installpath>
    
    </com.izforge.izpack.panels.TargetPanel>
    <com.izforge.izpack.panels.UserPathPanel id="userpath">
    
        <!-- SELECT THE DATA PATH FOR CONFIGURATION AND LOG FILES
             The installation expands this path with the Scheduler ID as subdirectory.
             The path must be absolute!
             Default paths are
             /home/[user]/sos-berlin.com/jobscheduler for Unix
             C:ProgramDatasos-berlin.comjobscheduler for Windows -->
        <UserPathPanelElement>/home/joc/jobscheduler</UserPathPanelElement>
    
    </com.izforge.izpack.panels.UserPathPanel>
    <com.izforge.izpack.panels.PacksPanel id="package">
    
        <!-- SELECT THE PACKS WHICH YOU WANT INSTALL -->
    
        <!-- Package: JobScheduler
             JobScheduler Basic Installation
             THIS PACK IS REQUIRED. IT MUST BE TRUE -->
        <pack index="0" name="Job Scheduler" selected="true"/>
    
        <!-- Package: Database Support
             Job history and log files can be stored in a database. Database support is
             available for MySQL, PostgreSQL, Oracle, SQL Server, DB2.
             THIS PACK IS REQUIRED. IT MUST BE TRUE -->
        <pack index="2" name="Database Support" selected="true"/>
    
        <!-- Package: Housekeeping Jobs
             Housekeeping Jobs are automatically launched by the Job Scheduler, e.g. to send
             buffered logs by mail, to remove temporary files or to restart the JobScheduler. -->
        <pack index="5" name="Housekeeping Jobs" selected="true"/>
    
    </com.izforge.izpack.panels.PacksPanel>
    <com.izforge.izpack.panels.UserInputPanel id="network">
        <userInput>
            <!-- Network Configuration -->
    
            <!-- Enter the name or ip address of the host on which the JobScheduler is operated -->
            <entry key="schedulerHost" value="localhost"/>
    
            <!-- Enter the port for TCP communication -->
            <entry key="schedulerPort" value="4444"/>
    
            <!-- Enter the port for HTTP communication -->
            <entry key="schedulerHTTPPort" value="40444"/>
    
            <!-- To enter a JobScheduler ID is required.
                 The IDs of multiple instances of the JobScheduler must be unique per server.
                 The JobScheduler ID expands the above installation paths as subdirectory.
                 Please omit special characters like: /  : ; * ? ! $ % & " < > ( ) | ^ -->
            <entry key="schedulerId" value="schedulerId_XXXX"/>
    
            <!-- It is recommended to enable TCP access for the host where the JobScheduler will install,
                 optionally enter additional host names or ip addresses. To enable all hosts in your
                 network to access the JobScheduler enter '0.0.0.0'. -->
            <entry key="schedulerAllowedHost" value="0.0.0.0"/>
    
            <!-- Choose (yes or no) wether the JobScheduler should be started at the end of the installation -->
            <entry key="launchScheduler" value="yes"/>
    
        </userInput>
    </com.izforge.izpack.panels.UserInputPanel>
    <com.izforge.izpack.panels.UserInputPanel id="cluster">
        <userInput>
            <!-- Cluster Configuration -->
    
            <!-- The JobScheduler can be installed independent of other possibly JobSchedulers,
                 as a primary JobScheduler in a backup system or as a backup JobScheduler.
                 Use '' for a standalone, '-exclusive' for a primary
                 or '-exclusive -backup' for a backup JobScheduler.
                 A database is required for a backup system. All JobSchedulers in a backup system
                 must have the same JobScheduler ID and the same database.
                 Further you can set '-distributed-orders' for a load balancing cluster.
                 For more information see
                 http://www.sos-berlin.com/doc/de/scheduler.doc/backupscheduler.xml
                 http://www.sos-berlin.com/doc/de/scheduler.doc/distributed_orders.xml -->
            <entry key="clusterOptions" value=""/>
    
        </userInput>
    </com.izforge.izpack.panels.UserInputPanel>
    <com.izforge.izpack.panels.UserInputPanel id="smtp">
        <userInput>
            <!-- Mail Recipients Configuration / SMTP Authentication -->
    
            <!-- Enter the ip address or host name and port (default: 25) of your SMTP server -->
            <entry key="mailServer" value=""/>
            <entry key="mailPort" value="25"/>
    
            <!-- Configure the SMTP authentication if necessary. -->
            <entry key="smtpAccount" value=""/>
            <entry key="smtpPass" value=""/>
    
            <!-- Enter the addresses of recipients to which mails with log files are automatically
                 forwarded. Separate multiple recipients by commas -->
    
            <!-- Account from which mails are sent -->
            <entry key="mailFrom" value=""/>
    
            <!-- Recipients of mails -->
            <entry key="mailTo" value=""/>
    
            <!-- Recipients of carbon copies: -->
            <entry key="mailCc" value=""/>
    
            <!-- Recipients of blind carbon copies -->
            <entry key="mailBcc" value=""/>
    
        </userInput>
    </com.izforge.izpack.panels.UserInputPanel>
    <com.izforge.izpack.panels.UserInputPanel id="email">
        <userInput>
            <!-- Mail Configuration / Event Handler -->
    
            <!-- Choose in which cases mails with log files are automatically forwarded. -->
            <entry key="mailOnError" value="no"/>
            <entry key="mailOnWarning" value="no"/>
            <entry key="mailOnSuccess" value="no"/>
    
            <!-- The Housekeeping package is required for configure JobScheduler as event handler
                 Choose this option if you intend to use JobScheduler Events and
                 - this JobScheduler instance is the only instance which processes Events
                 - this JobScheduler instance is a supervisor for other JobSchedulers which submit Events -->
            <entry key="jobEvents" value="off"/>
    
        </userInput>
    </com.izforge.izpack.panels.UserInputPanel>
    <com.izforge.izpack.panels.UserInputPanel id="database">
        <userInput>
            <!-- JobScheduler Database Configuration -->
    
            <!-- Choose the database management system. Supported values are 'mysql' for MySQL,
                 'oracle' for Oracle, 'mssql' for MS SQL Server, 'pgsql' for PostgreSQL,
                 'db2' for DB2 and 'sybase' for Sybase. -->
            <entry key="databaseDbms" value="mysql"/>
    
            <!-- You can choose between 'on' or 'off' to create the database tables.
                 If you have modified the initial data of an already existing installation,
                 then the modifications will be undone. Data added remains unchanged.
                 This entry should be only 'off', when you sure, that all tables are already created. -->
            <entry key="databaseCreate" value="on"/>
    
        </userInput>
    </com.izforge.izpack.panels.UserInputPanel>
    <com.izforge.izpack.panels.UserInputPanel id="dbconnection">
        <userInput>
            <!-- JobScheduler Database Configuration -->
    
            <!-- Enter the name or ip address of the database host -->
            <entry key="databaseHost" value="the host of RDS"/>
    
            <!-- Enter the port number for the database instance. Default ports are for MySQL 3306,
                 Oracle 1521, MS SQL Server 1433, postgreSQL 5432, DB2 50000, Sybase 5000. -->
            <entry key="databasePort" value="3306"/>
    
            <!-- Enter the schema -->
            <entry key="databaseSchema" value="jobscheduler_data"/>
    
            <!-- Enter the user name for database access -->
            <entry key="databaseUser" value="databaseUser"/>
    
            <!-- Enter the password for database access -->
            <entry key="databasePassword" value="databasePassword"/>
    
            <!-- You have to provide the MySQL, MS SQL Server, Sybase or DB2 JDBC driver respectively if you selected
                 corresponding DBMS type. For license reasons MySQL, Sybase and MS SQL Server JDBC Drivers are
                 not provided. Alternatively you can use the mariadb JDBC Driver for MySQL and
                 the jTDS JDBC Driver for MS SQL Server and Sybase which is provided. -->
    
            <!-- You can choose between 'yes' or 'no' for using the jTDS JDBC Driver
                 This entry affects only MS SQL Server or Sybase -->
            <entry key="connectorJTDS" value="yes"/>
    
            <!-- You can choose between 'yes' or 'no' for using the mariadb JDBC Driver
                 This entry affects only MySQL -->
            <entry key="connectorMaria" value="yes"/>
    
        </userInput>
    </com.izforge.izpack.panels.UserInputPanel>
    <com.izforge.izpack.panels.UserInputPanel id="jdbc">
        <userInput>
            <!-- JobScheduler Database Configuration -->
    
            <!-- Configuration for JDBC Driver
                 This entry is only necessary if you selected a DBMS type such as MySQL,
                 MS SQL Server, Sybase ot DB2 in the previous <userInput> element. -->
    
            <!-- You have to provide the MySQL, MS SQL Server, Sybase or DB2 JDBC driver respectively if you selected
                 corresponding DBMS type. For license reasons MySQL and MS SQL Server JDBC Drivers are
                 not provided. Specify the JDBC Driver source (e.g. mysql-connector-java-*.jar for MySQL,
                 sqljdbc.jar for MS SQL Server, jconn3.jar for Sybase). Alternatively you can use the mariadb
                 JDBC Driver for MySQL and the jTDS JDBC Driver for MS SQL Server and Sybase which is provided. -->
    
            <!-- Select the path to JDBC Driver -->
            <entry key="connector" value="/usr/share/java/mariadb-connector-java.jar"/>
    
            <!-- Only for DB2: Select the path to DB2 license file for JDBC Driver -->
            <entry key="connectorLicense" value=""/>
    
        </userInput>
    </com.izforge.izpack.panels.UserInputPanel>
    <com.izforge.izpack.panels.UserInputPanel id="reportingDatabase">
        <userInput>
            <!-- Reporting Database Configuration
                 NOT SUPPORTED FOR SYBASE AND DB2 -->
    
            <!-- Set 'yes' if the JobScheduler and the Reporting database are the same.
                 If 'yes' then further Reporting database variables are ignored. -->
            <entry key="sameDbConnection" value="yes"/>
    
            <!-- Choose the database management system. Supported values are 'mysql' for MySQL,
                 'oracle' for Oracle, 'mssql' for MS SQL Server, 'pgsql' for PostgreSQL. -->
            <entry key="reporting.databaseDbms" value="mysql"/>
    
        </userInput>
    </com.izforge.izpack.panels.UserInputPanel>
    <com.izforge.izpack.panels.UserInputPanel id="reportingDbconnection">
        <userInput>
            <!-- Reporting Database Configuration
                 NOT SUPPORTED FOR SYBASE AND DB2 -->
    
            <!-- Enter the name or ip address of the database host -->
            <entry key="reporting.databaseHost" value="qnet-jobscheduler.c58hqrvwigfw.ap-northeast-1.rds.amazonaws.com"/>
    
            <!-- Enter the port number for the database instance. Default ports are for MySQL 3306,
                 Oracle 1521, MS SQL Server 1433, postgreSQL 5432. -->
            <entry key="reporting.databasePort" value="3306"/>
    
            <!-- Enter the schema -->
            <entry key="reporting.databaseSchema" value="jobscheduler_data"/>
    
            <!-- Enter the user name for database access -->
            <entry key="reporting.databaseUser" value="reporting.databaseUser"/>
    
            <!-- Enter the password for database access -->
            <entry key="reporting.databasePassword" value="reporting.databasePassword"/>
    
            <!-- You have to provide the MySQL or MS SQL Server JDBC driver respectively if you selected
                 corresponding DBMS type. For license reasons MySQL and MS SQL Server JDBC Drivers
                 are not provided. Alternatively you can use the mariadb JDBC Driver for MySQL and the
                 jTDS JDBC Driver for MS SQL Server which is provided. -->
    
            <!-- You can choose between 'yes' or 'no' for using the jTDS JDBC Driver
                 This entry affects only MS SQL Server -->
            <entry key="reporting.connectorJTDS" value="yes"/>
    
            <!-- You can choose between 'yes' or 'no' for using the mariadb JDBC Driver
                 This entry affects only MySQL -->
            <entry key="reporting.connectorMaria" value="yes"/>
    
        </userInput>
    </com.izforge.izpack.panels.UserInputPanel>
    <com.izforge.izpack.panels.UserInputPanel id="reportingJdbc">
        <userInput>
            <!-- Reporting Database Configuration
                 NOT SUPPORTED FOR SYBASE AND DB2 -->
    
            <!-- Configuration for JDBC Driver
                 This entry is only necessary if the package 'Database Support' is chosen and you
                 selected a DBMS type MySQL or MS SQL Server in the previous
                 <userInput> element. -->
    
            <!-- You have to provide the MySQL or MS SQL Server JDBC driver respectively if you selected
                 corresponding DBMS type. For license reasons MySQL and MS SQL Server JDBC Drivers are
                 not provided. Specify the JDBC Driver source (e.g. mysql-connector-java-*.jar for MySQL,
                 sqljdbc.jar for MS SQL Server). Alternatively you can use the mariadb JDBC Driver for
                 MySQL and the jTDS JDBC Driver for MS SQL Server which is provided. -->
    
            <!-- Select the path to JDBC Driver -->
            <entry key="reporting.connector" value="/usr/share/java/mariadb-connector-java.jar"/>
    
        </userInput>
    </com.izforge.izpack.panels.UserInputPanel>
    <com.izforge.izpack.panels.UserInputPanel id="end">
        <userInput/>
    </com.izforge.izpack.panels.UserInputPanel>
    <com.izforge.izpack.panels.InstallPanel id="install"/>
    <com.izforge.izpack.panels.ProcessPanel id="process"/>
    <com.izforge.izpack.panels.FinishPanel id="finish"/>
    </AutomatedInstallation>
    
    
  3. setup.sh を実行します

    ./setup.sh jobscheduler_install.xml
    

JOC インストール

  1. JobScheduler と同様に JOC をダウンロードします。

    スクリーンショット 2017-06-08 0.35.42.png

  2. joc_install.xml を修正します。

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <!--
    XML configuration file for JOC
    
    If you call the installer with this XML file then
    you accept at the same time the terms of the
    licence agreement under GNU GPL 2.0 License
    (see http://www.gnu.org/licenses/gpl-2.0.html)
    -->
    <AutomatedInstallation langpack="eng">
    <com.izforge.izpack.panels.UserInputPanel id="home">
        <userInput/>
    </com.izforge.izpack.panels.UserInputPanel>
    <com.izforge.izpack.panels.HTMLLicencePanel id="gpl_licence"/>
    <com.izforge.izpack.panels.TargetPanel id="target">
    
        <!-- SELECT THE INSTALLATION PATH
             It must be absolute!
             For example:
             /opt/sos-berlin.com/joc on Linux
             C:Program Filessos-berlin.comjoc on Windows -->
        <installpath>/opt/sos-berlin.com/joc</installpath>
    
    </com.izforge.izpack.panels.TargetPanel>
    <com.izforge.izpack.panels.UserInputPanel id="jetty">
        <userInput>
    
            <!-- JOC requires a servlet container such as Jetty.
                 If a servlet container already installed then you can use it.
                 Otherwise a Jetty will be installed in addition if withJettyInstall=yes.
                 You need root permissions to install JOC with Jetty. -->
            <entry key="withJettyInstall" value="yes"/>
            <entry key="jettyPort" value="4446"/>
            <!-- Only necessary for Windows -->
            <entry key="jettyStopPort" value="40446"/>
            <!-- Only necessary for Unix (root permissions required) -->
            <entry key="withJocInstallAsDaemon" value="yes"/>
            <!-- Path to Jetty base directory
                 For example:
                 /homer/[user]/sos-berlin.com/joc on Linux
                 C:ProgramDatasos-berlin.comjoc on Windows -->
            <entry key="jettyBaseDir" value="/home/joc/jetty"/>
    
            <!-- Java options for Jetty. -->
            <!-- Initial memory pool (-Xms) in MB -->
            <entry key="jettyOptionXms" value="128"/>
            <!-- Maximum memory pool (-Xmx) in MB -->
            <entry key="jettyOptionXmx" value="512"/>
            <!-- Thread stack size (-Xss) in KB -->
            <entry key="jettyOptionXss" value="4000"/>
            <!-- Further Java options -->
            <entry key="jettyOptions" value=""/>
    
        </userInput>
    </com.izforge.izpack.panels.UserInputPanel>
    <com.izforge.izpack.panels.UserInputPanel id="reportingDatabase">
        <userInput>
            <!-- Reporting Database Configuration -->
    
            <!-- Choose the database management system. Supported values are 'mysql' for MySQL,
                 'oracle' for Oracle, 'mssql' for MS SQL Server, 'pgsql' for PostgreSQL. -->
            <entry key="reporting.databaseDbms" value="mysql"/>
    
        </userInput>
    </com.izforge.izpack.panels.UserInputPanel>
    <com.izforge.izpack.panels.UserInputPanel id="reportingDbconnection">
        <userInput>
            <!-- Reporting Database Configuration -->
    
            <!-- Enter the name or ip address of the database host -->
            <entry key="reporting.databaseHost" value="qnet-jobscheduler.c58hqrvwigfw.ap-northeast-1.rds.amazonaws.com"/>
    
            <!-- Enter the port number for the database instance. Default ports are for MySQL 3306,
                 Oracle 1521, MS SQL Server 1433, postgreSQL 5432. -->
            <entry key="reporting.databasePort" value="3306"/>
    
            <!-- Enter the schema -->
            <entry key="reporting.databaseSchema" value="jobscheduler_data"/>
    
            <!-- Enter the user name for database access -->
            <entry key="reporting.databaseUser" value="qnet_admin"/>
    
            <!-- Enter the password for database access -->
            <entry key="reporting.databasePassword" value="7sYne7aFEsFSK7xh"/>
    
            <!-- You have to provide the MySQL or MS SQL Server JDBC driver respectively if you selected
                 corresponding DBMS type. For license reasons MySQL and MS SQL Server JDBC Drivers are
                 not provided. Alternatively you can use the mariadb JDBC Driver for MySQL and
                 the jTDS JDBC Driver for MS SQL Server which is provided. -->
    
            <!-- You can choose between 'yes' or 'no' for using the jTDS JDBC Driver
                 This entry affects only MS SQL Server -->
            <entry key="reporting.connectorJTDS" value="yes"/>
    
            <!-- You can choose between 'yes' or 'no' for using the mariadb JDBC Driver
                 This entry affects only MySQL -->
            <entry key="reporting.connectorMaria" value="yes"/>
    
        </userInput>
    </com.izforge.izpack.panels.UserInputPanel>
    <com.izforge.izpack.panels.UserInputPanel id="reportingJdbc">
        <userInput>
            <!-- Reporting Database Configuration -->
    
            <!-- Configuration for JDBC Driver
                 This entry is only necessary if you selected a DBMS type such as MySQL and
                 MS SQL Server in the previous <userInput> element. -->
    
            <!-- You have to provide the MySQL or MS SQL Server JDBC driver respectively if you selected
                 corresponding DBMS type. For license reasons MySQL and MS SQL Server JDBC Drivers are
                 not provided. Specify the JDBC Driver source (e.g. mysql-connector-java-*.jar for MySQL,
                 sqljdbc.jar for MS SQL Server). Alternatively you can use the mariadb
                 JDBC Driver for MySQL and the jTDS JDBC Driver for MS SQL Server which is provided. -->
    
            <!-- Select the path to JDBC Driver -->
            <entry key="reporting.connector" value="/usr/share/java/mariadb-connector-java.jar"/>
    
        </userInput>
    </com.izforge.izpack.panels.UserInputPanel>
    <com.izforge.izpack.panels.UserInputPanel id="database">
        <userInput>
            <!-- JobScheduler Database Configuration -->
    
            <!-- Set 'yes' if the Reporting and the JobScheduler database are the same.
                 If 'yes' then further JobScheduler database variables are ignored. -->
            <entry key="sameDbConnection" value="yes"/>
    
            <!-- Choose the database management system. Supported values are 'mysql' for MySQL,
                 'oracle' for Oracle, 'mssql' for MS SQL Server, 'pgsql' for PostgreSQL,
                 'db2' for DB2 and 'sybase' for Sybase. -->
            <entry key="databaseDbms" value=""/>
    
        </userInput>
    </com.izforge.izpack.panels.UserInputPanel>
    <com.izforge.izpack.panels.UserInputPanel id="dbconnection">
        <userInput>
            <!-- JobScheduler Database Configuration -->
    
            <!-- Enter the name or ip address of the database host -->
            <entry key="databaseHost" value="qnet-jobscheduler.c58hqrvwigfw.ap-northeast-1.rds.amazonaws.com"/>
    
            <!-- Enter the port number for the database instance. Default ports are for MySQL 3306,
                 Oracle 1521, MS SQL Server 1433, postgreSQL 5432, DB2 50000, Sybase 5000. -->
            <entry key="databasePort" value="3306"/>
    
            <!-- Enter the schema -->
            <entry key="databaseSchema" value="jobscheduler_data"/>
    
            <!-- Enter the user name for database access -->
            <entry key="databaseUser" value="qnet_admin"/>
    
            <!-- Enter the password for database access -->
            <entry key="databasePassword" value="7sYne7aFEsFSK7xh"/>
    
            <!-- You have to provide the MySQL, MS SQL Server, Sybase or DB2 JDBC driver respectively if you selected
                 corresponding DBMS type. For license reasons MySQL, Sybase and MS SQL Server JDBC Drivers are
                 not provided. Alternatively you can use the mariadb JDBC Driver for MySQL and
                 the jTDS JDBC Driver for MS SQL Server and Sybase which is provided. -->
    
            <!-- You can choose between 'yes' or 'no' for using the jTDS JDBC Driver
                 This entry affects only MS SQL Server or Sybase -->
            <entry key="connectorJTDS" value="yes"/>
    
            <!-- You can choose between 'yes' or 'no' for using the mariadb JDBC Driver
                 This entry affects only MySQL -->
            <entry key="connectorMaria" value="yes"/>
    
        </userInput>
    </com.izforge.izpack.panels.UserInputPanel>
    <com.izforge.izpack.panels.UserInputPanel id="jdbc">
        <userInput>
            <!-- JobScheduler Database Configuration -->
    
            <!-- Configuration for JDBC Driver
                 This entry is only necessary if you selected a DBMS type such as MySQL,
                 MS SQL Server, Sybase ot DB2 in the previous <userInput> element. -->
    
            <!-- You have to provide the MySQL, MS SQL Server, Sybase or DB2 JDBC driver respectively if you selected
                 corresponding DBMS type. For license reasons MySQL and MS SQL Server JDBC Drivers are
                 not provided. Specify the JDBC Driver source (e.g. mysql-connector-java-*.jar for MySQL,
                 sqljdbc.jar for MS SQL Server, jconn3.jar for Sybase). Alternatively you can use the mariadb
                 JDBC Driver for MySQL and the jTDS JDBC Driver for MS SQL Server and Sybase which is provided. -->
    
            <!-- Select the path to JDBC Driver -->
            <entry key="connector" value="/usr/share/java/mariadb-connector-java.jar"/>
    
            <!-- Only for DB2: Select the path to DB2 license file for JDBC Driver -->
            <entry key="connectorLicense" value=""/>
    
        </userInput>
    </com.izforge.izpack.panels.UserInputPanel>
    <com.izforge.izpack.panels.UserInputPanel id="end">
        <userInput/>
    </com.izforge.izpack.panels.UserInputPanel>
    <com.izforge.izpack.panels.InstallPanel id="install"/>
    <com.izforge.izpack.panels.ProcessPanel id="process"/>
    <com.izforge.izpack.panels.FinishPanel id="finish"/>
    </AutomatedInstallation>
    
  3. setup.sh を実行します

    ./setup.sh joc_install.xml
    

続きを読む

AWS Network Load Balancer(NLB)のソースIPとターゲットのセキュリティグループ留意点まとめ …

ども、大瀧です。 AWSの新しいL4ロードバランサとしてNetwork Load Balancer(以下NLB)が登場して3ヶ月、いくつかのアップデートを経てNLBの機能はだいぶ様変わりしてきました。というわけで、ここらでNLBのソースIPに関する挙動とターゲットのセキュリティグループについてまとめておきたいと思います。 おことわり : 本 … 続きを読む

カテゴリー 未分類 | タグ

re:Invent 2017 TUESDAY NIGHT LIVEまとめ

Fusic Advent Calendar 2017 の3日目の記事です。

re:Invent 2017では下記の3つの基調講演で様々なサービスや新機能が発表されました。
・TUESDAY NIGHT LIVE
・KEYNOTE DAY1
・KEYNOTE DAY2

本日はTUESDAY NIGHT LIVEについてまとめました。

TUESDAY NIGHT LIVE

大きく下記の3テーマが語られます。
・COMPUTING AT SCALE
・LOAD BALANCING AT SCALE
・SECURIRY AT SCALE

「SCALE」という言葉が強調されてますね。

ANATOMY OF AN AWS REGION

https://www.youtube.com/watch?time_continue=124&v=dfEcd3zqPOA#t=7m23s

・AWSは最初の5年で4リージョン、次の5年で7リージョンを開設してきました。(10年で11リージョン)
・そして、2016年、2017年、2018年でさらに11リージョンを開設します。
・これらのリージョン間のネットワークを強化してグローバルなよりネットワークにしていく

COMPUTING AT SCALE

https://www.youtube.com/watch?time_continue=124&v=dfEcd3zqPOA#t=14m01s

・ここ数年でGPU & FPGAの利用が急成長している
・P3インスタンスの利用方法についての説明
 -> 機械学習
  -> 自動運転に関する企業の紹介

 1. ハードウェアの進化
 2. 機械学習フレームワーク
 3. 急成長するコミュニティ(GLUON)

AMAZON EC2 INSTANCES

https://www.youtube.com/watch?time_continue=124&v=dfEcd3zqPOA#t=27m33s

・Amazon EC2の基本的なアーキテクチャの説明
・EC2の進化
 1. EC2 Hosts
 2. EC2 Managment Services
 3. Amazon EBS
 4. Nitro System(AWS独自開発のクラウド基盤)

・EC2の目標
1. セキュリティ
 AWSの最も大事な品質はセキュリティとも語っている
2. パフォーマンス
 EC2インスタンスパフォーマンスは、他のパフォーマンス全てに関わる重要事項
3. 親しみやすさ

・Nitro System
1. C3インスタンス
 -> ネットワークパケットのプロセスをNitro Systemに移行
 -> レイテンシーの50%向上
2. C4インスタンス
 -> ストレージのプロセスをNitro Systemに移行
 -> EBS最適化がデフォルト化
 -> 12.5%計算力向上
3. C5インスタンス
 -> Custom Nitro ASICを選択
 -> Annapurna labsが開発
 -> Custom Nitro ASICを導入したのがC5インスタンス(Nitro Hypervisor)
  -> コアの技術はKVM
4. Bare Metal Instances

例) AUTODESK

https://www.youtube.com/watch?time_continue=124&v=dfEcd3zqPOA#t=48m44s
・機械学習による設計
・GENERATIVE DESIGN
・GENERATIVE DESIGNによって飛行機のドアなどを設計

https://www.autodesk.co.jp/solutions/3d-design-software?referrer=%2Fsolutions%2F3d-design-software

LOAD BALANCING AT SCALE

https://www.youtube.com/watch?time_continue=124&v=dfEcd3zqPOA#t=1h04m32s
・AWS最初のLOAD BALANCING紹介(32MB)

THE GOLDEN AGE PF HARDWARE LOAD BALANCIERS

・GOOD
・信頼性、スケーラビリティ、俊敏性を実現する簡単な方法
・プロバイダの増加、パフォーマンスの向上、機能の向上、コストの削減

・BAD
・ロードバランサーのコストの割合が増加している
・運用上の課題

ロードバランサーの問題点① BLACK BOX

・ハードウェアがブラックボックス化しており、問題を課題を解決できない
・他のユーザの真ん中ぐらいで利用して最初に問題に直面しないようにしていた

ロードバランサーの問題点② Virtual IPの数

・設定が煩雑
・10年前のVIP数 6,000
・現在のVIP数 600,000

Hyperplane

HARDWARE LOAD BALANCIERS
・2Nアーキテクチャでは最大で50%の利用率になる

S3 LOAD BALANCIERS
・Hyperplane(S3 分散型 ロードバランサー)

下記のサービスで利用されている
1. Amazon Elastic File System(EFS)
2. AWS Managed NAT
3. AWS Network Load Balancer(NLB)
4. AWS PrivateLink

PrivateLink (個人的に大注目)

・インターネットを介さずにサービスにアクセス可能
・複数アクセス間のVPCに対してサービス提供が可能
・APNはもっと簡単にサービス提供が可能

SECURIRY AT SCALE

https://www.youtube.com/watch?time_continue=124&v=dfEcd3zqPOA#t=1h22m50s
・自動化とツール化
・機械学習
・ベストプラクティス
・パートナー

・開発者もセキュリティエンジニアでもある
・AWSはセキュリティ対策を自動化している

AMAZON MACIE

・データアクセスアクティビティのモニタリング

AMAZON GuardDuty

・AWSアカウント全体の監視

※ セキュリティのポイント:人をデータから引き離す
※ AWSの文化はセキュリティを非常に大切にする

参考サイト
https://aws.amazon.com/jp/about-aws/events/reinvent2017-1128/
https://dev.classmethod.jp/cloud/aws/aws-reinvent-tuesdaynightlive-engineers-eye/
https://dev.classmethod.jp/cloud/aws/aws-reinvent-2017-keynote-day-1/
https://dev.classmethod.jp/cloud/aws/aws-reinvent-2017-keynote-day-2/
https://www.youtube.com/playlist?list=PLhr1KZpdzukfZxFGkA796dKaUufAgnU4c

続きを読む

AWS Fargateを使用してNginxを起動した(ENI使用)

AWS Fargateとは

AWS re:Invent2017でAWSが発表したコンテナホスト(インスタンス)を意識せずにコンテナを管理できるオーケストレーションサービスです。
現時点ではバージニア(us-east-1)リージョンのみでGAとなっています。
ちなみに、re:Inventに参加したので、現地でキーノートを聞いていましたが、同時にEKSも発表され待望のサービスが来た!という感じで私も会場もめちゃくちゃ興奮してました。

やってみる

クラスタの作成

リージョンはバージニアを選択し、Elastic Container Serviceの画面を開きます。
クラスターの作成ボタンを押してクラスタの作成を始めます。
(私の環境は元々別のクラスタが作成してあったので初めての場合表示が違うかもしれません)
console_aws_amazon_com_ecs_home_region_us-east-1.png

クラスタテンプレートの選択

以下の3つのクラスタテンプレートが選択できます。

  • Network only
  • EC2 Linux + Networking
  • EC2 Windows + Networking

Network onlyがFargateのようなので、こちらを選択して次のステップへ進みます。
console_aws_amazon_com_ecs_home_region_us-east-1__1_.png

クラスタの設定

ここではクラスタ名とネットワークの設定をします。
クラスタ名はFargateTestにしてみました。
また、このクラスタ用にVPCも合わせて作ってくれるオプションがあったので選択しました。
値はデフォルトのままで作成
console_aws_amazon_com_ecs_home_region_us-east-1__2_.png

起動ステータスの確認

作成が始まるとCloudFormationスタックが走ります。
しばらくするとイイ感じにクラスタができあがります。
console_aws_amazon_com_ecs_home_region_us-east-1__3_.png

クラスタの状態を確認

当然ですが実行中のタスクもサービスもありません。
console_aws_amazon_com_ecs_home_region_us-east-1__4_.png

タスク定義作成

新しくNginxを起動するタスクを定義します。
(私の環境は元々別のタスクが登録してあったので初めての場合表示が違うかもしれません)
console_aws_amazon_com_ecs_home_region_us-east-1__5_.png

ローンチタイプの選択

FARGATEEC2が選択できるので、当然FARGATEを選んで次のステップに進みます。
console_aws_amazon_com_ecs_home_region_us-east-1__6_.png

タスク定義の設定

適当にタスク定義に名前をつけます。ここではTestNginxとしました。
タスクのサイズ指定でメモリとvCPUを選択できます。
メモリは0.5GBと1GB~30GBまで1GB刻みで調整できるようです。
CPUは0.25、0.5、1、2、4から選択します。
ここではどちらも最小値の0.5GB、0.25vCPUを選択しました。
続いてコンテナの追加を行います。
console_aws_amazon_com_ecs_home_region_us-east-1__7_.png

コンテナの追加

コンテナ名を適当に定義します。ここではTestNginxにしました。
また、使用するコンテナイメージを指定します。DockerHubで公開されているNginxイメージをそのまま指定しました。
Nginxコンテナはポート80でListenするのでポートマッピングの設定は80となります。
その他は特に変更せずに追加し、そのまま作成します。
console_aws_amazon_com_ecs_home_region_us-east-1__8_.png

ローンチステータスの確認

ECSタスクと必要なIAM Roleが定義されたようです。
console_aws_amazon_com_ecs_home_region_us-east-1__9_.png

サービスの作成

クラスタの一覧から今回作成したFargateTestを選択します。
console_aws_amazon_com_ecs_home_region_us-east-1__11_.png

サービスの作成

サービスタブ内から作成します。
console_aws_amazon_com_ecs_home_region_us-east-1__12_.png

サービスの設定

Launch Typeは当然FARGATEを選択します。
また、タスク定義は先程作成したTestNginxを指定します。
サービス名には適当な名前をつけます。ここではTestNginxとしました。
console_aws_amazon_com_ecs_home_region_us-east-1__13_.png

ネットワーク構成の設定

参加するVPCを指定します。たぶん最初に作ったVPC IDが指定されていると思います。
コンテナが起動するサブネットを追加します。AZごとに別れていると思います。
また、セキュリティグループを編集することで既存のセキュリティグループを指定したり新規作成の内容を微調整できるようです。デフォルトのままだとポート80をAnyで公開します。
今回はELBを使用せずに直接コンテナに接続してみたいのでELBタイプはなしを選択しました。
このまま次のステップに進みます。
console_aws_amazon_com_ecs_home_region_us-east-1__14_.png

オートスケールの設定

オートスケールの設定ができますが、今回は実施しないのでそのまま次のステップに進みます。
console_aws_amazon_com_ecs_home_region_us-east-1__15_.png

サービスの確認

内容を確認してサービスの作成をします。
console_aws_amazon_com_ecs_home_region_us-east-1__16_.png

作成ステータスの確認

セキュリティグループの設定やサービスの設定が進みます。
console_aws_amazon_com_ecs_home_region_us-east-1__17_.png

動作確認

タスクのステータス確認

クラスタ内のタスクタブでステータスがRUNNINGになっていることを確認します。少し時間がかかる場合があります。
起動中のタスクIDを選択して詳細を確認します。
console_aws_amazon_com_ecs_home_region_us-east-1__18_.png

タスクの詳細確認

Networkの部分を見ると、ENI idがアタッチされていることが確認できます。
コンテナは外部に対してこのENIで通信します。
ENI IDを選択するとENIの画面に遷移します。
console_aws_amazon_com_ecs_home_region_us-east-1__19_.png

ENIの確認

ENIの画面に遷移したら、IPv4パブリックIPの部分を参照します。
ここに表示されているIPアドレスでコンテナと通信できます。
us-east-1_console_aws_amazon_com_ec2_v2_home_region_us-east-1.png

Nginxにアクセス

ブラウザで先程確認したIPアドレスにアクセスしてみます。
スクリーンショット 2017-12-05 17.28.17.png
無事Nginxが起動していました。

後片付け

作成したクラスタを削除します。
…と言いたいところですが、単純に削除したところ途中でエラーが出ました。
サービスを作成した際にできたセキュリティグループが残ってしまうので、CloudFormationStackが削除できないことが原因でした。
おそらく正しい手順はサービスの削除 -> セキュリティグループの削除 -> クラスタの削除となります。
まさか最後にアンチパターンにぶつかるとは。。。
console_aws_amazon_com_ecs_home_region_us-east-1__20_.png

最後に

インスタンスを意識する必要がないので保守範囲が減り、期待通りかなり魅力あるサービスだと感じました。
運用面では監視に課題が出てきそうなのかなーと思いました。
なんにせよ、Terraformへの組み込みと、東京リージョンでのサービス開始が待ち遠しいです。

続きを読む

クラウドベンダーの比較

はじめに

3大クラウドと呼ばれているAWS、GCP,Azureのリソースを比べてみました。
2017年11月時点の比較となります。

インフラ・サービスレベル

比較項目 AWS GCP Azure 備考
データセンター 各地で借りている すべて自前 各地で借りている(一部自前)
仮想化技術 Xen KVM Hyper-V
リージョン(国内) 1個所 1個所 2個所
リージョン(全国) 15個所 12個所 36個所
SLA 99.95 99.95 99.95 仮想サーバ

サービス面

比較項目 AWS GCP Azure 備考
仮想サーバ Amazon EC2 Google Compute Engine Azure Virtual Machines
仮想サーバ対応OS Amazon Linux,CentOS,RedHat,Windows Server,等 CentOS,RedHat,SLES,Windows Server,等 CentOS,RedHat,Windows Server,等
仮想サーバディスク SSD,HDD SSD,HDD SSD,HDD
仮想サーバスナップショット
仮想サーバオートスケール
コンテナ Amazon ECS Container Engine Container Service
RDB RDS Cloud SQL SQL Database
RDB冗長化
RDBリードレプリカ
RDB DB種別 Aurora,MySQL,MariaDB,Oracle,SQL Server,PostgreSQL MySQL,PostgreSQL SQL Server
NoSQL DynamoDB Cloud Datastore Cosmos DB
ビックデータ Redshift BigQuery App Service
メール Amazon SES
モニタリングツール CloudWatch Stackdriver Azure Monitor
ロードバランサー(L4) CLB Network load balancing Azure Load Barancer
ロードバランサー(L7) ALB HTTP load balancing Application Gateway
CDN Amazon CloudFront Google Cloud CDN Azure CDN
VPN Amazon VPC Google Cloud VPN VPN Gateway
DNS Route53 Google Cloud DNS Azure DNS
専用線 Direct connect Dedicated Interconnect Express Route

サポート面

比較項目 AWS GCP Azure 備考
ランク低 開発者 ($29/月 or 利用料の 3%/月) シルバー ($150/月) Standard($300/月)
ランク中 ビジネス($100/月 or 利用料 の10%/月) ゴールド($400/月) Professional Direct($1,000/月)
ランク高 エンタープライズ($15,000/月 or 利用料の10%) プラチナ(問合せ) Premier(問合せ)

費用面(リージョン日本)

比較項目 AWS GCP Azure 備考
課金単位
ディスカウント リザーブドインスタンス(前払い) 継続利用割引、利用確約の割引(前払い) エンタープライズ契約(前払い)
仮想サーバ(Type) t2.medium(2vCPU,4GB) n1-standard-2(2コア,7.5GB) A2 V2(2コア,4GB)
仮想サーバ(時) $0.0464(5.336円)※1 $0.0950(10.925円)※1 $0.15(17.25円)※1
仮想サーバ(月) $33.408(3841.92円)※1 $48.17(5539.55円)※1,※2 $108(12,420円)※1
インターネットへの転送量 $0.140/GB(10TBまで) $0.12/GB(1TBまで) $0.138/GB(5GB-10TB、5GBまでは無料)
ストレージ利用料 $0.025/GB (最初の50TB/月まで) ※S3 $0.016/GB 月 ※Regional Storage $0.2/GB(最初の50TB/月まで) ※BLOG Storage

※1 $1=115円換算
※2 継続利用割引含む

総括

 AWS、GCP,Azureでのサービス面では同じようなサービスを展開していることが判明。
 インフラ・サービスレベルでは、Azureがリージョン36個とTOPに。
世界的に見て幅を利かせているように思えた。
ただ、GCPはすべて自前のセンターでクラウドサービスを展開していることから、
新しいことをやるにも制約が低いように思えた。
私のイメージ的に一番シェアが高いAWSは、インフラ面ではGCP,Azureに劣っている結果となった。
 費用面では、Azureは割高。AWSが思ったよりも頑張っているように思えた。
 イメージ的にGCPは費用は安いと思っていたが、仮想サーバ比較だと、継続利用割引を使用してもAWSのほうが安い結果となった。
 ただ、費用に関しては、日々値下げ合戦が繰り広げられているので、今後のベンダーさんの努力に期待です。

最後に、費用面での算出に使用した見積もりツールです。
【AWS】http://calculator.s3.amazonaws.com/index.html
【GCP】https://cloud.google.com/products/calculator/?hl=ja
【Azure】https://azure.microsoft.com/ja-jp/pricing/calculator

続きを読む

AWSをさわってみたのでつまずいた点などをメモ

本記事はサムザップ Advent Calendar 2017の5日目の記事です。
昨日は@tomoriakiさんのゲームエンジニアが紙ヒコーキワークショップをやってみたでした

前提

・ インフラ歴半年
・ 業務では主にGCPを使用
・ GCPでできることをAWSで再現
・ 基本的にはterraformで構築
・ 大体検証期間は2週間くらい

目指したこと

既存のプロジェクト(GCP)と同等の開発環境構築

手順

※ 下記に記載する順番どおりに行ったわけではなく、記載上の問題で番号を振っています。

1. VPC構築

まずは何はともあれVPCとサブネット、サブネット配下にインスタンスを1台作成しました。

つまずき1
インスタンスにsshアクセスできない!
※ FWの設定(awsではセキュリティーグループ(sg)っていうのかな)はingress port:22許可したのに

原因と解決
インターネットゲートウェイ(igw)ってものをサブネットにアタッチしないとprivateなサブネットになってしまい、アクセス出来ないとのこと。


2. VPCにpriveteとpublicのサブネット構築

1.でigwを置いたけどそもそも接続出来ない領域分けたいよね、ということでサブネットを2つ作ってigwをアタッチするpublicサブネットとアタッチしないpriveteサブネットを作成
それぞれにインスタンスを1台ずつ置きpriveteインスタンスにはpublicインスタンスからinternal接続する

つまずき2
privateサブネットに置いたインスタンスでyum updateできない

原因と解決
privateサブネットだと外へのアクセスもできないらしい
NATゲートウェイ(ngw)というものをpublicサブネットに配置して、それ経由でpriveteサブネットのインスタンスは外へのアクセスをできるようにした。

※ 最初は名前的にEgress Only インターネットゲートウェイだと思ったけど、こちらはipv6らしい

TIPS
S3への接続はなにもしないと外部経由になってしまうらしい
エンドポイント(ep)というものをVPCに配置するとinternalで接続できるのでVPCを作ったらとりあえず、epも配置しよう!!


3. プロジェクトと開発環境の構成

1,2でVPCはだいたい出来たけど、
・ プロジェクトが違う場合
・ 環境(development, staging, productionなど)が違う場合
どのようにネットワークを分けて構築すればいいかを考えた。

参考
下記サイトでアカウントを分ける場合とVPCを分ける場合を分かりやすくまとめている
こちらを参考に本番と開発を分け(パターン4)、開発はVPCで分ける(パターン2-1)ように考慮した
https://dev.classmethod.jp/cloud/aws/account-and-vpc-dividing-pattern/


4. LBの作成

TCP, HTTP, HTTPSロードバランサの作成

つまずき3
terraformのmoduleロードバランサ関連多くてどれ使えばいいか分からん

原因と解決

terraform module名 awsでの呼び方 備考
elb classic ロードバランサ
alb application ロードバランサ 非推奨
(今後のバージョンアップで削除予定)
lb application ロードバランサ
network ロードバランサ
基本的にはこちらを使用する

TIPS
application LBはマルチAZ構成を強制されているのでゾーンの違うpublicなサブネットを2つ用意する必要がある。


5. インスタンスのホスト名解決

gcpではinternalな通信にホスト名を使用できる。

つまずき4
awsだとホスト名がipでつけられそもそも分かりづらいので、ホスト名を設定しつつ名前解決をしたい。

原因と解決
インスタンス登録時にtags:Nameにインスタンス名を設定し、そのインスタンス名とprivateIPをroute53でレコード登録する

サーバ自体はterraformのprovisionerで下記を実行

sudo sed -i -e "s/localhost.localdomain/[ホスト名]/g" /etc/sysconfig/network
sudo hostname [ホスト名]

まとめ

・ awsはgcpに比べてやれることが多い分、使う側がネットワークの知識とか結構求められるな!という印象を受けました。terraformのコード量もgcpの2倍くらいになった気がする。

・ マルチAZ構成を考える際は結構パフォーマンスに注意する必要がありそう。別ゾーンへのアクセスはパフォーマンスが落ちるという検証結果が結構あるので、問題ないように構成を考えないといけない

・ あとはざっくりgcpはブラックリスト、awsはホワイトリストなセキュリティーな印象

terraformのコード

https://github.com/bayguh/terraform_aws


明日は@Gaku_Ishiiさんの記事です。

続きを読む

AWS Fargateのタスクでsshd、コンテナにシェルで入ってみる

とりあえずやってみたくなるやつ。

今回使用したDockerイメージのソース、タスク用のJSONなどはこちら。

一回ログインしたらセッション切断時にタスクも終了する(sshdが-dで起動している)ようにしています。

ログインしてみる

ssh root@52.90.198.xxx で。環境変数ROOT_PWをrun-taskで指定していなければパスワードroooootで。

一応amazonlinuxをベースにしており、ログインしたときの環境変数はこんな感じ。 (※ 元の環境変数からAWS_*のみ自動でexportするように指定済。)

$ ssh root@34.236.216.xxx
root@34.236.216.xxx's password: 
There was 1 failed login attempt since the last successful login.
debug1: PAM: reinitializing credentials
debug1: permanently_set_uid: 0/0

Environment:
  USER=root
  LOGNAME=root
  HOME=/root
  PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/aws/bin
  MAIL=/var/mail/root
  SHELL=/bin/bash
  SSH_CLIENT=xxxxxxxxx 57401 22
  SSH_CONNECTION=xxxxxxxxx 57401 10.0.1.188 22
  SSH_TTY=/dev/pts/0
  TERM=xterm-256color
  AWS_CONTAINER_CREDENTIALS_RELATIVE_URI=/v2/credentials/2bf9b4ff-70a8-4d84-9733-xxxxxxx
  AWS_DEFAULT_REGION=us-east-1
  AWS_REGION=us-east-1

-bash-4.2# 

普通のメタデータは取れません。

# ec2-metadata 
[ERROR] Command not valid outside EC2 instance. Please run this command within a running EC2 instance.

Task Roleの取得はOK

-bash-4.2# curl 169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI | jq .
{
  "RoleArn": "arn:aws:iam::xxxxxxxx:role/ecsTaskExecutionRole",
  "AccessKeyId": "ASIAXXXXXXXXX",
  "SecretAccessKey": "XXXXXXXXXX",
  "Token": "xxx==",
  "Expiration": "2017-12-04T11:37:56Z"
}

という程度の軽い動作チェック程度には使えるというのと、一応このまま何かを頑張って構築しても稼働はするはず。。※コンテナポートはtask-definitionに追加で。
ホストのファイルシステムをマウントとかできないのであまり探るところもないけれど、気になるところは各自でチェックという感じで。

ふろく: AWS-CLIでrun-task

CLIの実行例にTask Roleはつけていないので、必要ならregister-task-definitionか、run-taskのoverrideで付与します。

task-definitionを作成する。

$ EXEC_ROLE_ARN=<ロールのARN> # AmazonECSTaskExecutionRolePolicyが付いたなにかしらのRole
$ aws ecs register-task-definition 
  --execution-role-arn $EXEC_ROLE_ARN 
  --family ssh-login 
  --network-mode awsvpc 
  --requires-compatibilities FARGATE 
  --cpu 256 
  --memory 512 
  --container-definitions "`cat example/task-def-sshlogin.json`"

> {
>    "taskDefinition": {
>        "taskDefinitionArn": "arn:aws:ecs:us-east-1:xxxxxxxx:task-definition/ssh-login:2",
>        "containerDefinitions": [
...

taskを実行する。

$ CLUSTER_NAME=<クラスタの名前>
$ SUBNET_ID=<コンテナを実行するサブネット>
$ SG_ID=<TCP/22が開いているSG>
$ aws ecs run-task 
  --cluster $CLUSTER_NAME 
  --launch-type FARGATE 
  --task-definition ssh-login:1 
  --network-configurationawsvpcConfiguration="{subnets=[$SUBNET_ID],securityGroups=[$SG_ID],assignPublicIp=ENABLED}"

#=> タスクのIDが返ってくるで変数に入れておくと良い

ENIのPublicIPはrun-taskの時点ではすぐにわからないので、ENIのIDがわかるまで適当にdescribe。

$ TASK_ARN=arn:aws:ecs:us-east-1:xxxxxxxxxxx:task/677c0132-9086-4087-bd18-xxxxxxxxxxx
$ aws ecs --region us-east-1 describe-tasks 
  --cluster $CLUSTER_NAME 
  --tasks arn:aws:ecs:us-east-1:xxxxxxxxxxx:task/677c0132-9086-4087-bd18-xxxxxxxxxxx

# =>
...

                {
                    "id": "xxxxxxxxxxx",
                    "type": "ElasticNetworkInterface",
                    "status": "ATTACHED",
                    "details": [
                        {
                            "name": "subnetId",
                            "value": "subnet-xxxxxxx"
                        },
                        {
                            "name": "networkInterfaceId",
                            "value": "eni-xxxxxxxx"
                        },
...

ENIのIDが分かったらPublicIPをとります。

$ aws ec2 --region us-east-1 describe-network-interfaces --network-interface-ids eni-xxxxxx | jq .NetworkInterfaces[].Association.PublicIp
"52.90.198.xxx"

ENIあたりはManagementConsole見ながらのほうが楽ですけどね。

続きを読む

Amazon RDS Read ReplicaをNLBでロードバランシングする

この記事は Relux AdventCalendar 4日目の記事です。

RDS Read Replicaのロードバランシング

複数のRead Replicaをロードバランシングする方法はいくつか考えられます。

  • Reader Endpointを使用する
  • HAProxyやNginxなどのソフトウェアを使用する
  • NLBを使用する

Reader Endpoint

Reader EndpointはAWS RDSの機能として用意されたもので、特別な設定をすることなく利用できます。
クラスタ内のRead Replica全てに均一に分散するもので、特定のRead Replicaを対象から外すといったことはできません。
短い時間(1秒ごと)でCNAMEを切り替えてラウンドロビンするような実装となっており、実際はロードバランサではありません。

HAProxyやNginx

AWSで行うとしたら、専用のEC2インスタンスを用意し、自分でインストール・設定・管理をする必要があります。

NLBを使用する

2017年9月ごろに、ELBの一種としてリリースされた Network Load Balancerは、EC2インスタンスだけでなく、任意のIPアドレスをターゲットとしてTCPロードバランサを構築できます。
これを使用することで、特定のRead Replicaのみをターゲットとした負荷分散環境を簡単に実装することができます。

NLB で Read Replica のロードバランシングを行う

NLBの構築

Screen Shot 0029-12-04 at 7.21.32.png
EC2 Load Balancersの設定画面から「Create Load Balancer」をクリック

Screen Shot 0029-12-04 at 7.21.58.png
Network Load Balancer を選択

NLBの基本設定

Screen Shot 0029-12-04 at 7.23.48.png
Nameには任意の名前を設定。
Schemeは、VPC内でのみ使用するのであれば internalを選択。

Listenerは、Aurora(MySQL)を対象とするので 3306/TCP

Availability Zoneでは使用するVPCを選択し、エンドポイントを置くサブネットを選択する。

ルーティングの設定

Screen Shot 0029-12-04 at 7.24.28.png

ALBと同じようにターゲットグループを作成する。
AuroraのReplicaをターゲットとする場合には、3306/TCP、Target typeは ip とする。

ターゲットの登録

Screen Shot 0029-12-04 at 7.25.26.png

ターゲットとして、ロードバランシングの対象としたいReplicaインスタンスのIPアドレスを登録する。
IPアドレスはReplicaインスタンスのDNS名をnslookupやdigで引いて調べる。

Security Groupの設定

Screen Shot 0029-12-04 at 7.35.59.png

NLBにはSecurity Groupを設定できない。
なので、NLBのAvailability Zoneに設定したサブネットのネットワークアドレスを許可するよう、RDSのSecurity Groupに設定をする。

疎通確認

Screen Shot 0029-12-04 at 8.07.04.png

アプリケーションサーバから接続可能なことを確認する。

最後に

今のところ、弊社では開発環境にのみ導入をし、試験運用を行なっております。
特に動作にが問題なく有用そうであれば、本番環境への導入を進めていきたいと思っています。

続きを読む