ALB Ingress Controller を使う

この記事では、 ALB Ingress Controller について書きます。

zalando-incubator/kube-ingress-aws-controller については、 Kubernetes2 Advent Calendar 2017 7日目 @mumoshu 先生の記事で、 書かれていますので、そちらを参照して下さい :bow:

WHY

Kubernetes on AWS で運用している場合、 Kubernetes の Service を作成すると、 AWS の Classic Load Balancer が作成されます。 Classic Load Balancer 以外に Application Load Balancer を利用したい場合が以下のような時にあります。

  • http2 を利用したい
  • /blog などリソース毎に向き先を区切る

Kubernetes on AWS を利用する方は既に AWS を使いだおしている方が大半だと思います。既存のアプリケーションを Kubernetes へ移行しようとした際に、 既に ALB(Application Load Balancer) を利用していたのが、 Kubernetes へ移行したら ELB (Classic Load Balancer) になって http2 無くなりましたというのはパフォーマンスにも影響を与えます。

そこで ALB Ingress Controller を利用することで、 ALB が使えます。

ALB Ingress Controller

The ALB Ingress Controller satisfies Kubernetes ingress resources by provisioning Application Load Balancers.

ALB Ingress Controller は、 Kubernetes の ingress を作成したタイミングで、 Application Load Balancer を作成します。

Design

image.png

The following diagram details the AWS components this controller creates. It also demonstrates the route ingress traffic takes from the ALB to the Kubernetes cluster.

Design に ALB が作られるまでの流れと、トラフィックの流れが書かれています。

Ingress Creation

Kubernetes 上に ingress を一つ作った時の流れ

[1]: The controller watches for ingress events from the API server. When it finds ingress resources that satisfy its requirements, it begins the creation of AWS resources.

[1] ALB Ingress Controller は、 Kubernetes の API Server からの Event を監視し、該当の Event を検知したら AWS のリソースを作成し始める。

[2]: An ALB (ELBv2) is created in AWS for the new ingress resource. This ALB can be internet-facing or internal. You can also specify the subnets its created in using annotations.

[2] ALB を作成する。 annotation を指定することで、サブネットやインターネット向けか内部向けかも決めることができる。

[3]: Target Groups are created in AWS for each unique Kubernetes service described in the ingress resource.

[3] ALB の向き先となるターゲットグループは、 ingress に記述された Service ごとに AWS で作成。

[4]: Listeners are created for every port detailed in your ingress resource annotations. When no port is specified, sensible defaults (80 or 443) are used. Certificates may also be attached via annotations.

[4] リスナは、 ingress の annotation で指定したポート用に作成されます。ポートが指定されていない場合、80または443を使用。 ACM も使用することもできる。

[5]: Rules are created for each path specified in your ingress resource. This ensures traffic to a specific path is routed to the correct Kubernetes Service.

[5] 入力リソースで指定された各パスに対してルールが作成され、特定のパスへのトラフィックが正しい Kubernetes の Service にルーティングされる。

Ingress Traffic

This section details how traffic reaches the cluster.

As seen above, the ingress traffic for controller-managed resources starts at the ALB and reaches the Kubernetes nodes through each service’s NodePort. This means that services referenced from ingress resource must be exposed on a node port in order to be reached by the ALB.

ALB から始まり、各サービスの NodePort を通じて Kubernetes ノードに到達するようになっている。 ALB を使ったサービスを公開するためには、 ingress と NodePort を使った Service の二つが必要になる。

How it Works

  • alb-ingress-controller 用の IAM を作成
  • ALB 作る際に、 sg と subnet を自動でアサインされるように、 subnet にタグの設定
  • AWS の IAM 情報と CLUSTER_NAME を secrets に入れる
  • default サーバーという一旦 target group アサインできるテンポラリのサービスを建てる
  • alb-ingress-controller を deploy する

alb-ingress-controller 用の IAM を作成

Role Permissions

AWS を操作するため、専用の IAM が必要になります。必要になるリソースは例と以下に記載されています。

IAM Policy

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "acm:DescribeCertificate",
                "acm:ListCertificates"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:AuthorizeSecurityGroupIngress",
                "ec2:CreateSecurityGroup",
                "ec2:CreateTags",
                "ec2:DeleteSecurityGroup",
                "ec2:DescribeInstances",
                "ec2:DescribeSecurityGroups",
                "ec2:DescribeSubnets",
                "ec2:DescribeTags",
                "ec2:ModifyInstanceAttribute",
                "ec2:RevokeSecurityGroupIngress"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "elasticloadbalancing:AddTags",
                "elasticloadbalancing:CreateListener",
                "elasticloadbalancing:CreateLoadBalancer",
                "elasticloadbalancing:CreateRule",
                "elasticloadbalancing:CreateTargetGroup",
                "elasticloadbalancing:DeleteListener",
                "elasticloadbalancing:DeleteLoadBalancer",
                "elasticloadbalancing:DeleteRule",
                "elasticloadbalancing:DeleteTargetGroup",
                "elasticloadbalancing:DescribeListeners",
                "elasticloadbalancing:DescribeLoadBalancers",
                "elasticloadbalancing:DescribeRules",
                "elasticloadbalancing:DescribeTags",
                "elasticloadbalancing:DescribeTargetGroups",
                "elasticloadbalancing:DescribeTargetHealth",
                "elasticloadbalancing:ModifyListener",
                "elasticloadbalancing:ModifyLoadBalancerAttributes",
                "elasticloadbalancing:ModifyRule",
                "elasticloadbalancing:ModifyTargetGroup",
                "elasticloadbalancing:RegisterTargets",
                "elasticloadbalancing:RemoveTags",
                "elasticloadbalancing:SetSecurityGroups",
                "elasticloadbalancing:SetSubnets"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "iam:GetServerCertificate",
                "iam:ListServerCertificates"
            ],
            "Resource": "*"
        }
    ]
}

ALB 作る際に、 sg と subnet を自動でアサインされるように、 subnet にタグの設定

Subnet Selection

ingress の annotation か auto-detection で、 各ALBを作成するサブネットを決定。

  • annotation: alb.ingress.kubernetes.io/subnets に、 subnet ID または NAME タグを使用して指定
  • auto-detection: annotation の指定はなく、自動検出で ALB を作成

auto-detection を有効にするためには、以下の tag を追加します。 ALB を作る際に subnet が二つ必要なため、二つ tag をつける。

  • kubernetes.io/role/alb-ingress=
  • kubernetes.io/cluster/$CLUSTER_NAME=shared

    • $CLUSTER_NAMEalb-ingress-controller.yamlCLUSTER_NAME 環境変数と一致させる必要がある

設定例

image

AWS の IAM 情報と CLUSTER_NAME を Secrets に入れる

namespace name key description
kube-system alb-ingress-controller AWS_ACCESS_KEY_ID credentials of IAM user for alb-ingress-controller
kube-system alb-ingress-controller AWS_SECRET_ACCESS_KEY credentials of IAM user for alb-ingress-controller
kube-system alb-ingress-controller CLUSTER_NAME cluster name
  • 登録方法

k8sec を使って Sercrets に登録します。

$ k8sec set alb-ingress-controller KEY=VALUE -n kube-system
  • 確認
$ k8sec list alb-ingress-controller -n kube-system
NAME            TYPE    KEY         VALUE
alb-ingress-controller  Opaque  AWS_ACCESS_KEY_ID   "hoge"
alb-ingress-controller  Opaque  AWS_SECRET_ACCESS_KEY   "fuga"
alb-ingress-controller  Opaque  CLUSTER_NAME        "Ooops"

ingress に必要になる Default backend サービスを建てる

kubectl Deployments

alb-ingress-controller を使うために必要になる Default backend サービスを建てる。 alb-ingress-controller を利用する ingress は、全て Default backend を指す。

$ kubectl create -f https://raw.githubusercontent.com/coreos/alb-ingress-controller/master/examples/default-backend.yaml

alb-ingress-controller を deploy する

  • alb-ingress-controller manifest ファイルをダウンロードする
$ wget https://raw.githubusercontent.com/coreos/alb-ingress-controller/master/examples/alb-ingress-controller.yaml
  • Secrets に追加したものを manifest file に反映する
        envFrom:
        - secretRef:
            name: alb-ingress-controller
  • AWS_REGION を設定する
- name: AWS_REGION
  value: ap-northeast-1
  • Deploy alb-ingress-controller
$ kubectl apply -f alb-ingress-controller.yaml  
  • log で起動できているか確認できる。
$ kubectl logs -n kube-system 
    $(kubectl get po -n kube-system | 
    egrep -o alb-ingress[a-zA-Z0-9-]+) | 
    egrep -o '[ALB-INGRESS.*$'
[ALB-INGRESS] [controller] [INFO]: Log level read as "", defaulting to INFO. To change, set LOG_LEVEL environment variable to WARN, ERROR, or DEBUG.
[ALB-INGRESS] [controller] [INFO]: Ingress class set to alb
[ALB-INGRESS] [ingresses] [INFO]: Build up list of existing ingresses
[ALB-INGRESS] [ingresses] [INFO]: Assembled 0 ingresses from existing AWS resources

上手く動かない場合ははここを true にすると良い。 AWS の制限で止められている可能性もありえる。

        - name: AWS_DEBUG
          value: "false"

これで ALB Ingress Controller の準備は完了

実際に ALB 作成してみる

alb-ingress-controller にある echo server を元にやってみる。基本的に以下、二点を抑えるだけで ALB
を利用できる。

  • ingress と NodePort を使った Service
  • ingress の annotation の設定

echoservice

alb-ingress-controller にある sample を元に echoserver を建ててみる。

$ kubectl apply -f https://raw.githubusercontent.com/coreos/alb-ingress-controller/master/examples/echoservice/echoserver-namespace.yaml &&
kubectl apply -f https://raw.githubusercontent.com/coreos/alb-ingress-controller/master/examples/echoservice/echoserver-service.yaml &&
kubectl apply -f https://raw.githubusercontent.com/coreos/alb-ingress-controller/master/examples/echoservice/echoserver-deployment.yaml

Namespace を切って、 NodePort で開放する Service と Deployment が作られる。

$ kubectl get all -n echoserver
NAME                             READY     STATUS    RESTARTS   AGE
po/echoserver-2241665424-xm1rt   1/1       Running   0          10m

NAME             TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
svc/echoserver   NodePort   100.65.13.23   <none>        80:31509/TCP   10m

NAME                DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deploy/echoserver   1         1         1            1           10m

NAME                       DESIRED   CURRENT   READY     AGE
rs/echoserver-2241665424   1         1         1         10m
  • ingress file を取得する
wget https://raw.githubusercontent.com/coreos/alb-ingress-controller/master/examples/echoservice/echoserver-ingress.yaml
  • annotation の設定(オプション)

Annotations に全部使える ALB の option が書いてある。

alb.ingress.kubernetes.io/scheme: internet-facing # or 'internal'
alb.ingress.kubernetes.io/connection-idle-timeout: # Defauflt 60
alb.ingress.kubernetes.io/subnets: # subnet ID か Name 
alb.ingress.kubernetes.io/security-groups: # sg ID か Name Default 0.0.0.0/0 
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP":80,"HTTPS": 443}]' # Default 80
alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:ap-northeast-1:hoge:certificate/UUID # ACM 利用する場合
alb.ingress.kubernetes.io/healthcheck-path: # Default "/"
alb.ingress.kubernetes.io/healthcheck-port: # Default Traffic port
alb.ingress.kubernetes.io/healthcheck-interval-seconds: # Default 15
alb.ingress.kubernetes.io/healthcheck-protocol: # Default HTTP
alb.ingress.kubernetes.io/healthcheck-timeout-seconds: # Default 5
alb.ingress.kubernetes.io/healthy-threshold-count: # Default 2
alb.ingress.kubernetes.io/unhealthy-threshold-count: # Default 2
alb.ingress.kubernetes.io/successCodes: # Default 200
alb.ingress.kubernetes.io/tags:  # Tag を入れる
  • ingress を建てる
$ kubectl apply -f echoserver-ingress.yaml

とりあえず default のままでいい場合は下記のコマンド

$ kubectl apply -f https://raw.githubusercontent.com/coreos/alb-ingress-controller/master/examples/echoservice/echoserver-ingress.yaml
  • ALB が作成された log を確認して見る
$ kubectl logs -n kube-system 
  $(kubectl get po -n kube-system | 
  egrep -o alb-ingress[a-zA-Z0-9-]+) | 
  egrep -o '[ALB-INGRESS.*$' | 
  grep 'echoserver/echoserver'
[ALB-INGRESS] [echoserver/echoserver] [INFO]: Start ELBV2 (ALB) creation.
[ALB-INGRESS] [echoserver/echoserver] [INFO]: Completed ELBV2 (ALB) creation. Name: hogefuga-echoserver-ech-2ad7 | ARN: arn:aws:elasticloadbalancing:ap-northeast-1:0000:loadbalancer/app/hogefuga-echoserver-ech-2ad7/17fd1481cb40fcc2
[ALB-INGRESS] [echoserver/echoserver] [INFO]: Start TargetGroup creation.
[ALB-INGRESS] [echoserver/echoserver] [INFO]: Succeeded TargetGroup creation. ARN: arn:aws:elasticloadbalancing:ap-northeast-1:0000:targetgroup/hogefuga-31509-HTTP-c3a0606/9914a217042c4006 | Name: hogefuga-31509-HTTP-c3a0606.
[ALB-INGRESS] [echoserver/echoserver] [INFO]: Start Listener creation.
[ALB-INGRESS] [echoserver/echoserver] [INFO]: Completed Listener creation. ARN: arn:aws:elasticloadbalancing:ap-northeast-1:0000:listener/app/hogefuga-echoserver-ech-2ad7/17fd1481cb40fcc2/0fe42e9436e45013 | Port: 80 | Proto: HTTP.
[ALB-INGRESS] [echoserver/echoserver] [INFO]: Start Rule creation.
[ALB-INGRESS] [echoserver/echoserver] [INFO]: Completed Rule creation. Rule Priority: "1" | Condition: [{    Field: "host-header",    Values: ["echoserver.example.com"]  },{    Field: "path-pattern",    Values: ["/"]  }]
[ALB-INGRESS] [echoserver/echoserver] [INFO]: Fetching Targets for Target Group arn:aws:elasticloadbalancing:ap-northeast-1:0000:targetgroup/hogefuga-31509-HTTP-c3a0606/9914a217042c4006
[ALB-INGRESS] [echoserver/echoserver] [INFO]: Fetching Rules for Listener arn:aws:elasticloadbalancing:ap-northeast-1:0000:listener/app/hogefuga-echoserver-ech-2ad7/17fd1481cb40fcc2/0fe42e9436e45013
[ALB-INGRESS] [echoserver/echoserver] [INFO]: Ingress rebuilt from existing ALB in AWS
  • URL を確認
$ kubectl describe ing -n echoserver echoserver
Name:             echoserver
Namespace:        echoserver
Address:          hogefuga-echoserver-ech-2ad7-126540505.ap-northeast-1.elb.amazonaws.com
Default backend:  default-http-backend:80 (100.96.27.7:8080)
Rules:
  Host                    Path  Backends
  ----                    ----  --------
  echoserver.example.com  
                          /   echoserver:80 (<none>)
Annotations:
Events:
  Type    Reason  Age   From                Message
  ----    ------  ----  ----                -------
  Normal  CREATE  2m    ingress-controller  Ingress echoserver/echoserver
  Normal  CREATE  2m    ingress-controller  hogefuga-echoserver-ech-2ad7 created
  Normal  CREATE  2m    ingress-controller  hogefuga-31509-HTTP-c3a0606 target group created
  Normal  CREATE  2m    ingress-controller  80 listener created
  Normal  CREATE  2m    ingress-controller  1 rule created
  Normal  UPDATE  2m    ingress-controller  Ingress echoserver/echoserver

ここからさらに踏み込んで external DNS の設定がありますが今回は、ALB までで閉じます。
最後に cURL で確認して終了です。

$ curl hogefuga-echoserver-ech-2ad7-126540505.ap-northeast-1.elb.amazonaws.com
CLIENT VALUES:
client_address=10.1.93.88
command=GET
real path=/
query=nil
request_version=1.1
request_uri=http://hogefuga-echoserver-ech-2ad7-126540505.ap-northeast-1.elb.amazonaws.com:8080/

SERVER VALUES:
server_version=nginx: 1.10.0 - lua: 10001

HEADERS RECEIVED:
accept=*/*
host=hogefuga-echoserver-ech-2ad7-126540505.ap-northeast-1.elb.amazonaws.com
user-agent=curl/7.43.0
x-amzn-trace-id=Root=1-5a2d4e2f-5545b75b74003cd80e5134bb
x-forwarded-for=192.168.100.10
x-forwarded-port=80
x-forwarded-proto=http
BODY:
-no body in request-
  • 最後は、削除
$ kubectl delete ns echoserver
namespace "echoserver" deleted

ALB も削除される。

$ curl hogefuga-echoserver-ech-2ad7-126540505.ap-northeast-1.elb.amazonaws.com
curl: (6) Could not resolve host: hogefuga-echoserver-ech-2ad7-126540505.ap-northeast-1.elb.amazonaws.com

続きを読む

[CloudWatch] 断続的なしきい値超過を捉えるアラームが設定しやすくなりました | Developers.IO

AWSのマネジメントコンソール「CloudWatch」の画面より「アラームの作成」を利用しました。 アラームの対象となるメトリックは、Application Load Balancer(ALB)のリクエストカウント(RequestCount) の「合計数」を利用しました。 続きを読む

AWS CloudFormationを使ってAWS Fargateの環境を作成してみる

本記事は個人の意見であり、所属する組織の見解とは関係ありません。

こちらはAWS Fargate Advent Calendar 2017の6日目の記事です。
AWS Fargateが発表されて、一週間ぐらい経ちました。新しいサービス、機能を色々試してみるのは楽しいですよね!

今日は、Fargateを触ってみて、もう少し本格的に取り組んでみたいと感じた方向けにAWS CloudFormationを使ってAWS Fargateの環境を作成する流れについて確認してみたいと思います。

AWS CloudFormationとは

Cloudformationでは、AWSリソースの環境構築を設定テンプレートを元に自動化する事ができます。ECSで利用する場合、TaskdefinisionやServiceの設定なども記述する事ができます。Containerのデプロイをより簡単に行える様になり各種自動化を行いやすくなるメリットもあります。

今回はFargateのAdvent Calendarへの投稿ですので、詳細については、次のWebinerの資料を確認してみてください。

CloudFormationテンプレート作成

作成方針

Cloudformationのテンプレートは記載の自由度が高く、色々な記述の仕方ができるのですが、今回は分かりやすさを重視して次の様な構成で分割したテンプレートを作成してみました。

  • VPC作成用テンプレート

    • Fargate用のVPCを作成し、VPCの設定を行うテンプレート
    • PublicSubnetやPrivateSubnet、ルートテーブルなどを作成していきます。
  • SecurityGroup作成用テンプレート

    • TaskやALBで利用するSecurityGroupを作成します。
  • ECSクラスターを作成するテンプレート

  • ELBを設定するテンプレート

  • TaskDefinitionテンプレート

    • ECS上で起動するContainerに関する設定を行います。
  • Serviceテンプレート

分割の仕方も様々ですので、各自のユースケースにあわせて、色々と試してみてください。個人的には、ライフサイクルが異なるリソースは別テンプレートにするが好きです。逆に、開発環境やデモ環境を素早く立ち上げたい場合は1つのテンプレートの中に全て記載してしまうのもいいですよね。

VPC作成用テンプレート

テンプレートの一部は次の様な形になります。(折りたたんでいます)

Resources:
    VPC:
        Type: AWS::EC2::VPC
        Properties:
            CidrBlock: !Ref VpcCIDR
            Tags:
                - Key: Name
                  Value: !Ref EnvironmentName

    InternetGateway:
        Type: AWS::EC2::InternetGateway
        Properties:
            Tags:
                - Key: Name
                  Value: !Ref EnvironmentName


  <省略>


Outputs:

    VPC:
        Description: A reference to the created VPC
        Value: !Ref VPC
        Export:
          Name: !Sub ${EnvironmentName}-VPC

ポイントは、作成したリソースに関する情報を別リソースからもアクセスできる様に
OutpusセクションでExport属性をつけている事です。Export属性で定義しているNameを利用して、
別テンプレートからも対象リソースに対する参照を行う事ができます。

SecurityGroup作成用テンプレート

ALB用、Container用のSecurityGroupを作成し、必要なPortを許可しています。

こちらも長いので、折りたたんでいます。

Description: >
    This template deploys a security-groups.

Parameters:
  EnvironmentName:
    Description: An environment name that will be prefixed to resource names
    Type: String
    Default: advent-calendar-2017

Resources:
  LoadBalancerSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      VpcId: !ImportValue advent-calendar-2017-VPC
      GroupDescription: SecurityGroup for ALB
      SecurityGroupIngress:
        - CidrIp: 0.0.0.0/0
          IpProtocol: tcp
          FromPort: 80
          ToPort: 80
      Tags:
        - Key: Name
          Value: !Sub ${EnvironmentName}-LoadBalancers


  ContainerSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      VpcId: !ImportValue advent-calendar-2017-VPC
      GroupDescription: Security Group for Task
      SecurityGroupIngress:
        -
          SourceSecurityGroupId: !Ref LoadBalancerSecurityGroup
          IpProtocol: -1
        -
          CidrIp: 0.0.0.0/0
          IpProtocol: tcp
          FromPort: 80
          ToPort: 80

      Tags:
        - Key: Name
          Value: !Sub ${EnvironmentName}-ContainerSecurityGroup

Outputs:
  LoadBalancerSecurityGroup:
    Description: A reference to the security group for load balancers
    Value: !Ref LoadBalancerSecurityGroup
    Export:
      Name: !Sub ${EnvironmentName}-LoadBalancerSecurityGroup

  ContainerSecurityGroup:
    Description: A reference to the security group for EC2 hosts
    Value: !Ref ContainerSecurityGroup
    Export:
      Name: !Sub ${EnvironmentName}-ContainerSecurityGroup

ECSクラスタ-を作成するテンプレート

非常にシンプルです。ただ、クラスタを定義して名前をつけるだけ。

Description: >
    This sample template deploys a ECS Cluster

Parameters:
  EnvironmentName:
    Description: An environment name that will be prefixed to resource names
    Type: String
    Default: advent-calendar-2017

Resources:
  ECSCluster:
    Type: AWS::ECS::Cluster
    Properties:
      ClusterName: !Sub ${EnvironmentName}-cluster

Outputs:
  ECSCluster:
    Description: A referenc
    Value: !Ref ECSCluster
    Export:
      Name: !Sub ${EnvironmentName}-Cluster

ELBを設定するテンプレート

ALB、Listener、Targetgroupを作成しています。

Description: >
    This template deploys an Application Load Balancer.


Parameters:
  EnvironmentName:
    Description: An environment name that will be prefixed to resource names
    Type: String
    Default: advent-calendar-2017


Resources:
  LoadBalancer:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Name: !Ref EnvironmentName
      Subnets:
        - !ImportValue advent-calendar-2017-PublicSubnet1
        - !ImportValue advent-calendar-2017-PublicSubnet2
      SecurityGroups:
        - !ImportValue advent-calendar-2017-LoadBalancerSecurityGroup
      Tags:
        - Key: Name
          Value: !Ref EnvironmentName
      Scheme: internet-facing

  LoadBalancerListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      LoadBalancerArn: !Ref LoadBalancer
      Port: 80
      Protocol: HTTP
      DefaultActions:
        - Type: forward
          TargetGroupArn: !Ref DefaultTargetGroup

  DefaultTargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      Name: !Sub ${EnvironmentName}-targetgroup
      VpcId: !ImportValue advent-calendar-2017-VPC
      Port: 80
      Protocol: HTTP
      TargetType: ip

Outputs:

  LoadBalancer:
    Description: A reference to the Application Load Balancer
    Value: !Ref LoadBalancer
    Export:
      Name: !Sub ${EnvironmentName}-Loadbalancer

  LoadBalancerUrl:
    Description: The URL of the ALB
    Value: !GetAtt LoadBalancer.DNSName

  Listener:
    Description: A reference to a port 80 listener
    Value: !Ref LoadBalancerListener
    Export:
      Name: !Sub ${EnvironmentName}-Listener

  DefaultTargetGroup:
    Value: !Ref DefaultTargetGroup
    Export:
      Name: !Sub ${EnvironmentName}-DefaultTargetGroup

TaskDefinition設定

ようやくFargateに関連する設定が出てきました。ここでは、RequiresCompatibilities属性にFARGATEを指定し、
NetworkMode属性にawsvpcを指定しています。また、CPU、メモリの設定はContainerDefinitionsの外側で設定します。
Container Definitionsにおけるmemory/cpuの指定はオプションです。加えて、各Taskがログを出力するためのCloudwatch Logsの設定もここで行なっています。

Description: >
    This sample deploys a task

Parameters:
  EnvironmentName:
    Description: An environment name that will be prefixed to resource names
    Type: String
    Default: advent-calendar-2017

Resources:
  LogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub '/ecs/logs/${EnvironmentName}-groups'

  ECSTask:
    Type: AWS::ECS::TaskDefinition
    Properties:
      Cpu: 256
      ExecutionRoleArn: arn:aws:iam::XXXXXXXXXXXX:role/ecsTaskExecutionRole
      Family: !Sub ${EnvironmentName}-task
      Memory: 512
      NetworkMode: awsvpc
      RequiresCompatibilities:
        - FARGATE
      ContainerDefinitions:
        -
          Name: nginx
          Image: nginx:latest
          LogConfiguration:
            LogDriver: awslogs
            Options:
              awslogs-group: !Ref LogGroup
              awslogs-region: us-east-1
              awslogs-stream-prefix: ecs
          MemoryReservation: 512
          PortMappings:
            -
              HostPort: 80
              Protocol: tcp
              ContainerPort: 80

Outputs:
  LogGroup:
      Description: A reference to LogGroup
      Value: !Ref LogGroup

  ECSTask:
    Description: A reference to Task
    Value: !Ref ECSTask

Service設定

ここではFargate上でTaskを起動させるために、LaunchType属性にFARGATEを指定しています。ここでTaskNameに指定しているXXの数字はTaskのRevisionに該当します。Taskの更新とともにここの数字を変える必要があるという点がポイントです。

Description: >
    This sample deploys a service

Parameters:
  EnvironmentName:
    Description: An environment name that will be prefixed to resource names
    Type: String
    Default: advent-calendar-2017

  TaskName:
    Description: A task name
    Type: String
    Default: advent-calendar-2017-task:XX

Resources:
  Service:
    Type: AWS::ECS::Service
    Properties:
      Cluster: !ImportValue advent-calendar-2017-Cluster
      DesiredCount: 2
      LaunchType: FARGATE
      LoadBalancers:
        -
          TargetGroupArn: !ImportValue advent-calendar-2017-DefaultTargetGroup
          ContainerPort: 80
          ContainerName: nginx
      NetworkConfiguration:
        AwsvpcConfiguration:
          SecurityGroups:
            -
              !ImportValue advent-calendar-2017-ContainerSecurityGroup
          Subnets:
            -
              !ImportValue advent-calendar-2017-PrivateSubnet1
            -
              !ImportValue advent-calendar-2017-PrivateSubnet2
      ServiceName: !Sub ${EnvironmentName}-service
      TaskDefinition: !Ref TaskName
Outputs:
  Service:
      Description: A reference to the service
      Value: !Ref Service

Cloudformation Stackを作成する

これで、Fargate環境の作成準備が整いました。ここからは順番にStackを作成していきます。

$ aws cloudformation create-stack --stack-name advent-calendar-2017-vpc 
--template-body file://Fargate-vpc.yml 
--region us-east-1

$ aws cloudformation create-stack --stack-name advent-calendar-2017-security-group 
--template-body file://Fargate-security-groups.yaml 
--region us-east-1

$ aws cloudformation create-stack --stack-name advent-calendar-2017-load-balancer 
--template-body file://Fargate-load-balancers.yaml 
--region us-east-1

$ aws cloudformation create-stack --stack-name advent-calendar-2017-cluster 
--template-body file://Fargate-cluster.yml 
--region us-east-1


$ aws cloudformation create-stack --stack-name advent-calendar-2017-task 
--template-body file://Fargate-taskdefinition.yml 
--region us-east-1

$ aws cloudformation create-stack --stack-name advent-calendar-2017-service 
--template-body file://Fargate-service.yml 
--region us-east-1

作成した環境を確認する

Cloudformationでの環境構築が終わりました。正しく構築できているか、ALB経由でアクセスして確認してみてください。
作成したALBのFQDNは、マネージメントコンソール上のEC2の画面>ロードバランサにアクセスして確認できます。
それ以外にも今回の例では、CLIでの次の様なコマンドで確認する事ができます。(少し無理やりですが。。。)

$ aws cloudformation describe-stacks --stack-name advent-calendar-2017-load-balancer  
--region us-east-1 | jq '.Stacks[].Outputs[] | select(.OutputKey == "LoadBalancerUrl")'

{
  "Description": "The URL of the ALB",
  "OutputKey": "LoadBalancerUrl",
  "OutputValue": "advent-calendar-2017-844241308.us-east-1.elb.amazonaws.com"
}


####awscli単独でやるなら、次の様にも書く事ができます。

aws cloudformation describe-stacks --stack-name advent-calendar-2017-load-balancer  
--region us-east-1 
--query 'Stacks[].Outputs[?OutputKey == `LoadBalancerUrl`].OutputValue'

ECSクラスター

次のコマンドで存在が確認できます。

$ aws ecs list-clusters --region us-east-1
{
    "clusterArns": [
        "arn:aws:ecs:us-east-1:925496135215:cluster/advent-calendar-2017-cluster"
    ]
}

サービスの状態

作成したサービスの状態は次の様なコマンドで確認できます。

aws ecs describe-services --services <service name> 
--cluster <cluster name> --region us-east-1

例えば、デプロイしているサービスの状況を確認する際には以下の様なコマンドで状態を取得可能です。
次のコマンド結果には、runningCountが2であり、desiredCountの設定通りにTaskが起動している事が確認できます。


$ aws ecs describe-services --services advent-calendar-2017-service 
--cluster advent-calendar-2017-cluster 
--region us-east-1 | jq .[][].deployments
[
  {
    "status": "PRIMARY",
    "networkConfiguration": {
      "awsvpcConfiguration": {
        "subnets": [
          "subnet-2541e678",
          "subnet-9297e0f6"
        ],
        "securityGroups": [
          "sg-326f1047"
        ]
      }
    },
    "pendingCount": 0,
    "createdAt": 1512499161.953,
    "desiredCount": 2,
    "taskDefinition": "arn:aws:ecs:us-east-1:XXXXXXXXXXXX:task-definition/advent-calendar-2017-task:3",
    "updatedAt": 1512500281.269,
    "id": "ecs-svc/9223370524355613851",
    "runningCount": 2
  }
]

デプロイしたServiceを更新する

Cloudformationを利用して作成していますので、更新もCloudformation経由で行います。

テンプレートを更新する。

今回はDesiredCountを修正してみました。

$ diff Fargate-service-update.yml Fargate-service.yml
20c20
<       DesiredCount: 4
---
>       DesiredCount: 2

Stackを更新する

次の様なコマンドでStackの更新が可能です。

$ aws cloudformation update-stack --stack-name advent-calendar-2017-service 
--template-body file://Fargate-service-update.yml 
--region us-east-1

しばらく待った後に再びServiceの状態を確認するとDsierdCount通りにTaskの数が増えている事が確認できます。

$ aws ecs describe-services --services advent-calendar-2017-service 
--cluster advent-calendar-2017-cluster 
--region us-east-1 | jq .[][].deployments
[
  {
    "status": "PRIMARY",
    "networkConfiguration": {
      "awsvpcConfiguration": {
        "subnets": [
          "subnet-2541e678",
          "subnet-9297e0f6"
        ],
        "securityGroups": [
          "sg-326f1047"
        ]
      }
    },
    "pendingCount": 0,
    "createdAt": 1512499161.953,
    "desiredCount": 4,
    "taskDefinition": "arn:aws:ecs:us-east-1:925496135215:task-definition/advent-calendar-2017-task:3",
    "updatedAt": 1512538215.582,
    "id": "ecs-svc/9223370524355613851",
    "runningCount": 4
  }
]

Taskをアップデートする。

テンプレートを更新する。

Taskが利用するメモリの容量を修正してみました。

$ diff Fargate-taskdefinition-update.yml Fargate-taskdefinition.yml 
25c25
<       Memory: 1024
---
>       Memory: 512

Stackを更新する

次の様なコマンドでTask用のStackの更新をします。

$ aws cloudformation update-stack --stack-name advent-calendar-2017-task 
--template-body file://Fargate-taskdefinition-update.yml 
--region us-east-1

TaskのRevisionが変化していますので、Serviceでも新しいRevisionを利用する様に、テンプレートを修正して、Service用のStackを更新します。

$ aws cloudformation update-stack --stack-name advent-calendar-2017-service 
--template-body file://Fargate-service.yml 
--region us-east-1

再度、サービスの状態を確認して、起動しているTaskが更新されている事を確認してみてください。

まとめ

Cloudformationを利用したECS,Fargateの操作はいかがだったでしょうか。今回の記事を書く為に、新規でCloudformationテンプレートを作成したのですが、これまでのECSで利用していたテンプレートとの違いは僅かでした。FargateをきっかけにECSに興味を持って頂けた方の参考になればうれしいです。

続きを読む

AWS ELB を使って冗長構成を組むまでの気にするポイント

今回ELBを使って、EC2の冗長構成を作りました。
その中で、何個かはまりごとにも出くわしたので、メモがわりに投稿します。

前提条件の構成

(BEFORE)

インターネット -> EC2 -> RDS

(とりあえずのAFTER)

インターネット -> ELB -> EC2 -> RDS

(さらにAFTER)

インターネット -> ELB -> EC2その1 / EC2その2 -> RDS

大まかな流れ

  1. ロードバランサーの作成
  2. ターゲットグループの作成
  3. ヘルスチェック用ファイルの設置
  4. DNSのAレコード登録
  5. EC2インスタンスを新規作成
  6. DNSのAレコード登録(直アクセス確認用)
  7. ターゲットグループに新規EC2インスタンスを登録
  8. 動作確認

手順とハマりポイント

1. ロードバランサーの作成

  • 入口が見つけづらいので数分ハマるので気をつけてくださいw

EC2_Management_Console.jpg

  • ロードバランサーの種類を選びます。今回は「Application Load Balancer」を選択。

EC2_Management_Console.jpg

  • AWSコンソールの手順に従い、設定を行います。
1. ロードバランサーの設定
2. セキュリティ設定の構成
3. セキュリティグループの設定
4. ルーティングの設定
5. ターゲットの登録
6. 確認

2. ターゲットグループの作成

  • ターゲットグループには、複数のAZを指定し冗長構成を図りました。
  • ターゲットは後からでも登録できるので、後回し。
  • 基本的には、ここでどんな設定をしても、DNSのAレコードを設定しない限り影響ないので、気軽に

3. ヘルスチェック用ファイルの設置

  • 確認をしている中でヘルスチェックが「Unhealthy」と出ていたので、Document Root配下にチェック用ファイルを置き、ヘルスチェックを再設定

4. DNSのAレコード登録

  • ロードバランサーの「説明」タブにある情報を参照し、DNSのAレコードを追加

EC2_Management_Console.jpg

  • この状態で、ブラウザからアクセスすると (とりあえずのAFTER) の構成になっている

5. EC2インスタンスを新規作成

  • 既存のサーバのAMIを作って、いつも通りにコピー作成
  • その時に、AZを既存のEC2と違うところで作るのを忘れずに。あとで必要になります。

6. DNSのAレコード登録(直アクセス確認用)

  • 既存のサーバ+新規作成サーバのパブリックIPを参照し、DNSのAレコードに追加
  • ロードバランサーを経由せず、インターネットから直接EC2にもアクセス可能な構成とするため

7. ターゲットグループに新規EC2インスタンスを登録

  • 既存のサーバ+新規作成サーバのパブリックIPを参照し、DNSのAレコードに追加
  • ターゲットグループのターゲットの種類を「ip」で選択した場合は プライベートIP を指定する必要があります。ここで パブリックIP を指定しようとし、しばらくハマりました。

8. 動作確認

  • 晴れて、ロードバランサーの設定は完了です。
  • それぞれのサーバにアクセスがきていること、ログが出ていること、ラウンドロビンできていることを確認し、ひと段落。

ここには書いてないけど、一緒にやったこと

  • ログファイルバックアップの設定

    • ログファイルをS3にバックアップしているのですが、単純に稼働サーバを増やすだけだとログファイル名が被っちゃうことが想定されたので、ログファイル名にホスト名を含めるなどの手入れをしました。
  • ログに出てくるIPアドレス取得に X_HTTP_FORWARDED_FORに切り替え

感想

サブネットグループやインスタンスの新規作成など、結構直感で運用していた面も改めてレビューすることができました。
かといって、大きなハマりポイントはなく、設定完了まで行けたのでAWSさすが!!という感じです。

続きを読む

AWS FargateでNginxを動かしてみる

本記事は個人の意見であり、所属する組織の見解とは関係ありません。

こちらはAWS Fargate Advent Calendar 2017の12/2分の記事です。

AWS Fargateを使うことで、コンテナを使ったアプリケーションにだけ集中して開発することができます。今日は、Amazon ECSのコンソールのFirst runチュートリアルを通して、簡単にNginxを立ち上げてみて、変更を加えてデプロイしてみましょう。

First runは以下のリンクから始められます。

1セット作成してみる

Step 1を見ると、Nginxのコンテナ定義はチュートリアルにあるのでそれを選ぶだけで簡単に作成できます。

Screen Shot 2017-12-03 at 12.40.39 AM.png

Step 2では、サービスにApplication Load Balancerを紐付けるチェックボックスを選択します。

Screen Shot 2017-12-03 at 12.41.07 AM.png

Step 3では、Cluster nameを適当につけます。ここではadvent-calendar-2017とします。

Screen Shot 2017-12-03 at 12.41.39 AM.png

Step 4で確認したら作成します。これだけです。実際は選択した情報を元にAWS CloudFormationスタックが作成され、以下のリソースが自動的に生成されます。もちろん、Fargateを使うのでこの中にAmazon EC2インスタンスは含まれていません!

Screen Shot 2017-12-03 at 12.48.05 AM.png

作成が完了したら、Load balancerのリンクを開き、DNS nameをブラウザで開くとNginxのindex.htmlが表示されます。503が返って来る場合は、タスクの起動待ちですのでしばらく待てば大丈夫です。

Screen Shot 2017-12-03 at 12.49.10 AM.png

View Service => Tasksタブから、起動しているタスクの詳細を開くとLogというタブがあるので、そこを見るとNginxのアクセスログが表示されると思います。ALBからのヘルスチェックと自身のブラウザでアクセスしたログが記録されています。なお、実体はAmazon CloudWatch Logsに収集されています。

Screen Shot 2017-12-03 at 12.50.49 AM.png

以上です。とても簡単ですね!、、、だけだと面白くないので、作成したECSサービスをすこしだけいじってみましょう。

スケールしてみる

タスクはFargateで起動されているので、数を変更してスケールさせたい時はサービスのタスク数を変更して更新するだけです。先程作成した時には1タスクになっているので、これを2にしてみましょう。サービスの画面でUpdateをクリックします。

Screen Shot 2017-12-03 at 12.53.44 AM.png

Number of tasksを2に変更して、あとはNext stepを押し続け、最後にサービスを更新します。

Screen Shot 2017-12-03 at 12.54.00 AM.png

しばらくすると以下のようにタスクの数が増えています。ALBへの登録もサービスが自動で行ってくれますので、すぐにALBからのリクエストがバランスされます。

Screen Shot 2017-12-03 at 12.56.50 AM.png

こちらのリンクからCloudWatch Logsの画面に行くと、2つのタスクのログをまとめて見ることができます。

Screen Shot 2017-12-03 at 12.58.24 AM.png

デプロイしてみる

いわゆるデプロイをするために、タスク定義を新たに作成してサービスを更新してみましょう。サービスの詳細画面からTask definitionのリンクをクリックし現在のタスク定義の画面に飛びます(リビジョンの数字は人によって違います)。そして、Create new revisionをクリックします。

Screen Shot 2017-12-03 at 1.01.55 AM.png

下の方にスクロールして、Container Definitionsの中にあるnginxをクリックします。すると、コンテナ定義の変更画面が出てくるので、Imageをより軽量なAlpine Linuxベースに変更するため、nginx:alpineにします。

Screen Shot 2017-12-03 at 1.03.09 AM.png

そのままコンテナ定義の画面を下にスクロールして、Advanced container configurationの中のEntry pointとCommandを以下の様に変更します。

  • Entry point

    • sh,-c (コンマを忘れずに)
  • Command
    • ifconfig eth1 | grep "inet addr" | cut -d ':' -f 2 | cut -d ' ' -f 1 > /usr/share/nginx/html/index.html && exec nginx -g "daemon off;"
    • コンテナ起動時に、Private IPアドレスをindex.htmlに書き込んでいます。

Screen Shot 2017-12-03 at 1.04.08 AM.png

コンテナ定義のUpdateをクリックして閉じ、一番下のCreateをクリックしてタスク定義を作成します。最後に、今作成したタスク定義でサービスを更新します。ActionsからUpdate Serviceを選択します。

Screen Shot 2017-12-03 at 1.11.49 AM.png

変更画面が開くと、Task Definitionが新しくなっているので、ClusterとService nameが間違っていないことを確認したらNext stepを押し続け、最後にUpdateをクリックします。

Screen Shot 2017-12-03 at 1.13.03 AM.png

これによって、新旧タスクがいわゆるBlue/Greenデプロイの形で入れ替わります。デフォルトの設定では、デプロイ中も最低限100%(2タスク)を確保しつつ、最大で200%(4タスク)が同時実行されることを許容する設定にしているので、おおまかには以下の様な流れでデプロイが実行されます:

  1. 新タスク定義のタスクが2つ起動する
  2. 新タスク定義のタスクがALBに登録され、Healthyになる
    • この時点で、トラフィックは新旧混在状態になる
  3. 旧タスク定義のタスク2つがALBから解除される
    • この時点で、トラフィックは新タスクのみになる
    • ALBのTarget GroupのDeregistration Delayがデフォルトだと300秒になっているので、ここから5分かかるが、0秒に変更すれば即座に解除される。
  4. 旧タスク定義のタスク2つが削除され、サービス更新完了

ALBのDNS nameに何度かアクセスしてみると、表示されるIPアドレスが入れ替わることが分かると思います。

作成した環境を削除する

最後に、今作成した環境を削除しておきます。といっても簡単で、ECSのクラスタを削除すれば、関連するリソースを全て自動的に削除してくれます。具体的には、CloudFormationスタックが削除されます。

Screen Shot 2017-12-03 at 1.26.16 AM.png

進捗も表示されるので安心です。

Screen Shot 2017-12-03 at 1.26.36 AM.png

まとめ

First runチュートリアルで数クリックでNginxをFargateで立ち上げた後に、スケールしたりデプロイしてみたりしました。タスクのこととサービスのことだけに集中して作業できることがお分かり頂けたかと思います。

続きを読む

HTTP/2対応のElastic Beanstalk環境を構築する

はじめに

サービスの紹介

2017/10/16 にリリースした Snapmap(スナップマップ) は、
「いつ」「なにを」「どこで」「どうやって」撮影したのかが分かるというコンセプトのサービスです。

そんな Snapmap ですが、画像共有サービスなのでサイト全体は HTTP/2 で表示するようになっています。
その効果1もあり、サイトのパフォーマンスを計測するとこんな感じで結構速いです。

Elastic Beanstalkとは

Snapmap は Elastic Beanstalk を使ってアプリケーションサーバーの環境を構築しています。
Elastic Beanstalk は AWS のサービスの一つで、デプロイ・サーバー監視・スケーリングの全てをまるっとやってくれます。

新規サービスで考慮しておくべきことの多くをショートカットできるのはとても魅力的で、インフラにコストを掛けたくなかった今回の案件にぴったりでした。

HTTP/2にする、その前に

Elastic Beanstalk で構築したアプリケーションサーバーを HTTP/2 に対応させるには、ロードバランサーを Application Load Balancer にする必要があります2
ただ、普通に Web の画面からポチポチ作成すると Classic Load Balancerで環境を構築されてしまいます(2017/12/1 現在)。
さらに、悲しいことに環境構築後にロードバランサーの種類は変更できません

なので、一番初めから EB CLI を使って作成する必要があります。
すでに構築してしまっている場合は諦めて別環境を再作成しましょう。

というわけで、自分の備忘録として今回は一から手順を書いていきたいと思います。

手順

AWS CLI / EB CLIのインストール

EB CLI のインストールがまだであれば以下のコマンドでインストールできます。(AWS CLI も後で必要なのでついでにインストールします)

$ pip install --upgrade pip
$ pip install awscli --user
$ pip install awsebcli --user

AWSの設定

aws configure を利用して、AWSへのアクセス情報を設定します。

$ aws configure
AWS Access Key ID [None]: AKIA*********EXAMPLE # アクセスキーを指定
AWS Secret Access Key [None]: wJa***************************EXAMPLEKEY # シークレットアクセスキーを指定
Default region name [None]: ap-northeast-1
Default output format [None]: json

アクセスキーをまだ発行していなければこちらを参考に。

Elastic Beanstalkの環境作成

準備ができたので Elastic Beanstalk の環境を作っていきます。

まず初期設定を行います。
デプロイ用ディレクトリを作成して eb init を実行し、リージョンとアプリケーションを選択します。

$ mkdir hogehoge
$ cd hogehoge
$ eb init

Select a default region
1) us-east-1 : US East (N. Virginia)
2) us-west-1 : US West (N. California)
3) us-west-2 : US West (Oregon)
4) eu-west-1 : EU (Ireland)
5) eu-central-1 : EU (Frankfurt)
6) ap-south-1 : Asia Pacific (Mumbai)
7) ap-southeast-1 : Asia Pacific (Singapore)
8) ap-southeast-2 : Asia Pacific (Sydney)
9) ap-northeast-1 : Asia Pacific (Tokyo)
10) ap-northeast-2 : Asia Pacific (Seoul)
11) sa-east-1 : South America (Sao Paulo)
12) cn-north-1 : China (Beijing)
13) us-east-2 : US East (Ohio)
14) ca-central-1 : Canada (Central)
15) eu-west-2 : EU (London)
(default is 3): 9 # 東京リージョンを選ぶ

Select an application to use
1) [ Create new Application ]
(default is 1): 1 # 新規アプリを選ぶ

Enter Application Name
(default is "hogehoge"): hogehoge # ディレクトリ名がデフォルトになっているのでアプリ名を入力する
Application shibuya_test has been created.

Select a platform.
1) Node.js
2) PHP
3) Python
4) Ruby
5) Tomcat
6) IIS
7) Docker
8) Multi-container Docker
9) GlassFish
10) Go
11) Java
12) Packer
(default is 1): 4 # プラットフォームを選ぶ

Select a platform version.
1) Ruby 2.4 (Puma)
2) Ruby 2.3 (Puma)
3) Ruby 2.2 (Puma)
4) Ruby 2.1 (Puma)
5) Ruby 2.0 (Puma)
6) Ruby 2.4 (Passenger Standalone)
7) Ruby 2.3 (Passenger Standalone)
8) Ruby 2.2 (Passenger Standalone)
9) Ruby 2.1 (Passenger Standalone)
10) Ruby 2.0 (Passenger Standalone)
11) Ruby 1.9.3
(default is 1): 1 # バージョンを選ぶ
Cannot setup CodeCommit because there is no Source Control setup, continuing with initialization
Do you want to set up SSH for your instances?
(Y/n): Y # 対象サーバーにSSHアクセスしたいならYes

Select a keypair.
1) snapmap_bastion
13) [ Create new KeyPair ]
(default is 1): 1 # キーペアを選ぶ

次に環境の作成ですが、ここで注意したいのが、1 つの VPC とアベイラビリティーゾーンが異なる 2 つのサブネットが必要という点です。
可用性確保のためにそういう仕様になっているっぽいです。

つまり先に VPC とサブネットは作成しておく必要があります。
作成ができたら eb create を実行し、環境を作成します。

eb create xxxxxxxx 
    --elb-type application 
    --vpc.id vpc-xxxxxxxx  # 作成したVPC
    --vpc.elbsubnets subnet-xxxxxxxx,subnet-xxxxxxxx  # 作成したサブネット
    --vpc.ec2subnets subnet-xxxxxxxx,subnet-xxxxxxxx  # 作成したサブネット
    --vpc.elbpublic 
    --vpc.publicip

これでサンプルアプリのサイトが構築されます。こんな感じ。

うまく起動したら、環境作成はいったん完了です。

ebextensionsを設置

次にソースコードを HTTP/2 対応させます。

こちらを参考に、ソースコードのプロジェクト直下にHTTPをHTTPSにリダイレクトさせるための .ebextensions ファイルを作ります。

.ebextensions/01_aws.config
option_settings:
  aws:elbv2:listener:443:
    DefaultProcess: default
    ListenerEnabled: true
    Protocol: HTTPS
    SSLCertificateArns: rn:aws:acm:ap-northeast-1:*************************** # 先ほど発行した証明書のARN
  aws:elbv2:listener:80:
    DefaultProcess: http
    ListenerEnabled: true
    Protocol: HTTP
  aws:elasticbeanstalk:environment:process:default:
    Port: 80
    Protocol: HTTP
    StickinessEnabled: true
    StickinessLBCookieDuration: 43200
    HealthCheckPath: /
    HealthCheckTimeout: 30
    HealthCheckInterval: 60
    MatcherHTTPCode: 200
  aws:elasticbeanstalk:environment:process:http:
    Port: 81
    Protocol: HTTP
    HealthCheckPath: /
    HealthCheckTimeout: 30
    HealthCheckInterval: 60
    MatcherHTTPCode: 301
.ebextensions/02_nginx.config
files:
  /etc/nginx/conf.d/redirect.conf:
    mode: "000644"
    owner: root
    group: root
    content: |
      server {
        listen 81;
        rewrite ^ https://$host$request_uri permanent;
      }

Elastic Beanstalk の関連ファイルを無視するよう .gitignore に以下を追加します。

.gitignore
# Elastic Beanstalk Files
.elasticbeanstalk/*
!.elasticbeanstalk/*.cfg.yml
!.elasticbeanstalk/*.global.yml

ソースコードの変更は以上です。

ソースコードの取得

作成したデプロイ用ディレクトリにソースコードを配置します。

$ cd hogehoge # デプロイ用ディレクトリに移動する
$ git init
$ git remote add origin git@github.com:CoachUnited/hogehoge.git
$ rm .gitignore # 自動で作成されてしまうので消す
$ git pull origin master

次に環境変数を設定し、再度デプロイします。

$ eb setenv RAILS_ENV=production HOGE=fuga 〜 # 必要な環境変数をつらつらと
$ eb deploy # ソースコードをデプロイ

これでサイトが正しく表示されれば OK です。
次は SSL 対応をしていきます。

証明書の取得

こちらを参考に AWS Certificate Manager を利用して、サイトドメインで利用する証明書を取得します。

ちなみに、テスト環境もSSL化したい場合はワイルドカード証明書(*.snapmap.jp)を作成すればOKですが、ワイルドカード証明書はルートドメイン(snapmap.jp)には使えないので注意してください。

(なんと、11月の時点でSESでメールを受け取る必要がなくなったそうです :tada:

Route53を設定

あとは Route53 でサイトドメインの Hosted Zone から A レコードを作成して、ElasitcBeanstalk で作成された環境のドメインを割り当ててください。

これですべて完了です。
ブラウザでアクセスして HTTP/2 になっていれば成功です。お疲れ様でした。

まとめ

手順自体はそこそこ長いですが、実際に作業してみるととても簡単に、そして一度作成してしまえば後は AWS におまかせできます。
スモールスタートのプロジェクトには ElasticBeanstalk 超超オススメです!


  1. Vue.js や materializecss の利用も速度向上に大きく寄与しています。 

  2. 画像は CloudFront で配信されているため、Supported HTTP Versions を「HTTP/2, HTTP/1.1, HTTP/1.0」にするだけで HTTP/2 化できます。 

続きを読む

Istio Ingress on Kubernetes on AWS

自己紹介


Istio?

  • “An open platform to connect, manage, and secure microservices. https://istio.io
  • Kubernetesで動くService Meshの一つ

Istio Ingress?

  • istio-ingress-controller
  • KubernetesのIngress Controllerの一種
  • Ingress … L7ロードバランシング(の設定)
  • Ingress Controller … Ingressリソースの内容に応じてL7ロードバランサをプロビジョニングする

アーキテクチャ

image.png

ref: @kelseyhightower-san, https://github.com/kelseyhightower/istio-ingress-tutorial#architecture

  • Nginx Ingresesとかと同じ構成
  • Istio Ingress Node Pool
    • 例: インターネットに公開する場合

      • インターネットに公開したL4、L7ロードバランサ経由(Classic Load Balancer, Application Load Balancer)で、プライベートサブネット内ノードのIstio Ingress Controllerへ
      • AWS Network Load Balancer経由でパブリックサブネット内ノードのIstio Ingress Controllerへ

Istio Ingressでできないこと

以下はIstio Ingressの責任範囲外

  • AWS Security Groupの設定

    • 手動、Terraform, CloudFormation、kube-awsなどのクラスタプロビジョニングツールを使う
  • AWS ELB, ALBのプロビジョニング
    • 手動、Terraform, CloudFormationなどで管理
    • Istio Ingressと他のIngress Controllerを併用する(kube-ingress-aws-controller)
  • AWS Route53 Record Setの作成

典型的なistioのインストール手順

前提として、RBACは有効に、istio専用のネームスペースをつくり、デフォルトのzipkin以外で分散トレースするとして・・・

helm installと、立て続けにhelm upgradeを実行する必要があるところがわかりづらい。


まずhelm installでCRD(Customer Resource Definition)をつくり、

$ helm install incubator/istio --set rbac.install=true --namespace istio-system --devel

helm upgradeでCRD以外をつくる。

helm upgrade eponymous-billygoat incubator/istio --reuse-values --set istio.install=true --devel

kubectlを打つのが面倒なので、kubensでistio-systemを選択。

alias k=kubectl
alias kn=kubens

kn istio-system

istio configmapにistioが接続するzipkinのホスト名が書いてあるので、それを変更。

k edit configmap istio

デフォルトでは以下のようになっている。

# Zipkin trace collector
zipkinAddress: zipkin:9411

Stackdriverにトレースを流す場合

zipkinAddress: stackdriver-zipkin.kube-system:9411

dd-zipkin-proxy+Datadog APMにトレースを流す場合、
iptablesで$MAGIC_IP:9411->$HOST_IP:9411にredirectさせてから、

zipkinAddress: 169.254.169.256:9411

Istio Ingressを試す


Ingressのプロキシ先バックエンドサービスをデプロイする

いつものKubernetesへのDeployment + istioctl kube-inject

httpbinをデプロイする。

$ git clone git@github.com:istio/istio.git
$ cd istio/samples/httpbin
$ kn istio-ingress-test
$ k apply -f <(istioctl kube-inject -f samples/httpbin/httpbin.yaml)

k apply -f httpbin.yaml のかわりに k apply -f <(istioctl kube-inject -f httpbin.yaml)としてIstio Sidecarの定義を付け加えている。


Kubernetes Ingressリソースの作成

cat <<EOF | kubectl create -f -
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: simple-ingress
  annotations:
    kubernetes.io/ingress.class: istio
spec:
  rules:
  - http:
      paths:
      - path: /.*
        backend:
          serviceName: httpbin
          servicePort: 8000
EOF

kind: IngressとあるとおりKubenetesの一般的なIngressリソースをつくるだけ。

Istio Ingress ControllerがこのIngressを検知して、よしなにEnvoyの設定変更をしてくれる。Nginx Ingress Controllerの場合よしなに設定変更されるのがNginxという違い。


Istio Ingressからバックエンドへのルーティング

あとは、Istioで一般に使うRouteRuleを設定することで、リクエストをルーティングする。Istio “Ingress”に特別なことはない。


istioのRouteRuleとは?

RouteRuleはistio管理下のService A・B間でどういうルーティングをするかという設定を表す。

Service A —istio w/ RouteRule—> Service B


Istio Ingress + RouteRule

Istio Ingressに対してRouteRuleを設定する場合、基本的にsourceがistio-ingressになる(kubectl –namespace istio get svcするとistio-ingressというServiceがいるが、それ)。

Istio Ingress —istio w/ RouteRule—> Backend Service A


Istio Ingress + RouteRuleの例

例えば、バックエンド障害時のIstio Ingressの挙動を確認したい場合。以下のようなRouteRuleで、istio ingressから全バックエンドへのリクエストを遮断する・・・というのもルーティングの範疇。

cat <<EOF | istioctl create -f -
## Deny all access from istio-ingress
apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
  name: deny-route
spec:
  destination:
    name: httpbin
  match:
    # Limit this rule to istio ingress pods only
    source:
      name: istio-ingress
      labels:
        istio: ingress
  precedence: 1
  route:
  - weight: 100
  httpFault:
    abort:
      percent: 100
      httpStatus: 403 #Forbidden for all URLs
EOF

Istio Ingressでできること

クラスタ内部向けのRouteRule同様、specに色々かいて活用すると以下のようなことができる。

  • Cookieが特定のパターンにマッチしたらサービスv2、そうでなければサービスv1にルーティング

    • ユーザがアクセスするWebサービス、Web APIのA/Bテスト
    • β版Web UIの先行公開
  • バックエンドの重み付け(route[].weight)
    • ミドルウェアやライブラリの更新を一部リクエストで試したい
  • レートリミット
    • 重いWeb APIに全体で100 req/sec以上のリクエストが送られないように
  • リトライ(httpReqRetries)
    • 不安定なサービスへのリクエストが失敗したら、Istio Ingressレイヤーでリトライ。クライアント側でリトライしなくて済む
  • タイムアウト(httpReqTimeout)

あわせて読みたい: Istio / Rules Configuration


まとめ

  • 同じL7のALBなど単体ではできないL7ロードバランシングが実現できます
  • User-Facingなサービスへのデプロイを柔軟にできて、アプリやミドルウェアの更新起因の大きな障害の予防になる

AWSの場合は使わなさそうな機能

使わなくていいものをうっかり使ってしまわないように。


Secure Ingress

https://istio.io/docs/tasks/traffic-management/ingress.html#configuring-secure-ingress-https

Istio IngressがTLS終端してくれる機能。SNIに対応してない(Envoyレベルで)とか、証明書の管理が面倒(AWS ACMよりも)などの点から、使うことはなさそう。


あわせて読みたい

続きを読む

Classic Load BalancerからALBにOne-stepでMigrationできるようになったのでやってみた

Classic Load BalancerからALBにOne-stepで移動できるようになったのでやってみた

目的

Classic Load BalancerからApplication Load Balancer(以下、ALB)にポチで作成できるようになったので
リリース分を早速試してみた:sunglasses:

リリース内容
New One-step Migration Wizard to Migrate a Classic Load Balancer

Classic Load Balancerの元設定

ほぼデフォルトのまま
nginxを2台ぶら下げているだけ

  • elb名確認
# aws --profile PROFILE名 elb describe-load-balancers --load-balancer-name=test-elb01 --query 'LoadBalancerDescriptions[].LoadBalancerName' --output table

-----------------------
|DescribeLoadBalancers|
+---------------------+
|  test-elb01         |
+---------------------+
  • instance id確認
# aws --profile PROFILE名 elb describe-load-balancers --load-balancer-name=test-elb01 --query 'LoadBalancerDescriptions[].Instances' --output table
-------------------------
| DescribeLoadBalancers |
+-----------------------+
|      InstanceId       |
+-----------------------+
|  i-aaaaaaaaaaaaaaaaa  |
|  i-bbbbbbbbbbbbbbbbb  |
+-----------------------+

  • Listeners確認
# aws --profile PROFILE名 elb describe-load-balancers --load-balancer-name=test-elb01 --query 'LoadBalancerDescriptions[].ListenerDescriptions' --output table
------------------------------------------------------------------------
|                         DescribeLoadBalancers                        |
||                              Listener                              ||
|+--------------+--------------------+--------------------+-----------+|
|| InstancePort | InstanceProtocol   | LoadBalancerPort   | Protocol  ||
|+--------------+--------------------+--------------------+-----------+|
||  80          |  HTTP              |  80                |  HTTP     ||
|+--------------+--------------------+--------------------+-----------+|
  • マネジメントコンソール上

01.PNG

ALBにMigrationしてみる

  • 手順

※マネジメントツコンソール上から操作

  1. 対象のClassic Load Balancerを選択
  2. 下のタブの「移行」を選択
  3. 「ALB移行ウィザードを起動」をクリック
  4. 確認画面が表示
  5. 変更するものは変更して
  6. 作成をクリック
  7. チェック・起動が走って
  8. 作成完了画面が出る
  • 手順1~3

02.PNG

  • 手順4~6

03.PNG

  • 手順7,8

04.PNG

うーん簡単!:smiley:

作成されたALBを確認

  • alb名
# aws --profile PROFILE名 elbv2 describe-load-balancers  --names=test-elb01 --query 'LoadBalancers[].LoadBalancerName' --output table

-----------------------
|DescribeLoadBalancers|
+---------------------+
|  test-elb01         |
+---------------------+
  • targetgroup名
# aws --profile PROFILE名 elbv2 describe-target-groups --names=test-elb01 --query 'TargetGroups[].TargetGroupName' --output table
----------------------
|DescribeTargetGroups|
+--------------------+
|  test-elb01        |
+--------------------+
  • Instane ID・healthcheck
# aws --profile PROFILE名 elbv2  describe-target-health --target-group-arn=TARGETGROUPのARN --query 'TargetHealthDescriptions[].[Target.Id,TargetHealth.State,Target.Port]' --output table
------------------------------------------
|          DescribeTargetHealth          |
+----------------------+-----------+-----+
|  i-aaaaaaaaaaaaaaaaa |  healthy  |  80 |
|  i-bbbbbbbbbbbbbbbbb |  healthy  |  80 |
+----------------------+-----------+-----+
  • マネージドコンソール上

05.PNG

ALBが同じ名前で作成されてますね!!:wink:

結果

ELBを元にALBをワンクリックで作成することが出来ました!!:beers:

Classic Load BalancerからALBに入れ替えるには

まだサービスにはアサインされていないので
以下の手順が必要

  1. ALBへのアクセスの動作確認
  2. Route53などのDNSで、サービスのDNSレコードをClassic ELBからALBへ変更する

※注意点
ELB配下のサーバたちがそのままALBに入れ替わるってことではないので
気をつけてください :tiger:

続きを読む

AWSサービスの概要を一覧化するスクレイピング

背景

AWSにはサービスが多種多様にあり、なかなか全体感が一覧できません。
初学者には「全体的にどんなサービスがあるの?」というのが俯瞰的に見ることができないのか「サービスのカテゴリとサービス名と、その概要を一覧化してくれ」なんてことがあろうかと思います。
対してうるせぇググれよさっと各サービスの概要説明を一覧にして差し上げるのがクラウド時代のエンジニアの所作と思われます。知らんけど。

やってみる

cheerio-httpcliでクローリング&スクレイピングしてみました。
最初はHeadless Chromeで始めたのですが、どうやらSPAはなさそうでcheerio-httpcliでよいだろうと書き直しました。

コードは以下に配置しています。
https://github.com/morimop/aws-services-list

  • 重複あっても気にしない
  • 一応言語切り替えができるかもしれない雰囲気は出してみる

うまくいかなかったところ

サービスごとにレイアウトが統一されていないので、ここを取ってくればいい、という単純な判定はできませんでした。

index.js
            const pElements = [].filter.call(
              $('main').find('p'),
              (pn)=>{
                if($(pn).find('a').length == 0){
                  return true;
                };
                return ($(pn).find('a').text() != $(pn).text());
              });

この箇所はEMRのページのせいです。このページだけHadoopやらSparkやらのリンクが冒頭に付いているので、これを除外しています。

index.js
          return $('p').parent().text().trim();

mainが見つからなかったページはとりあえず何か取ってくる、という雑仕様です。
AWS Marketplaceのページが相当おかしな感じになります。

結果

出力は./tmp/以下にJSONで出力していますので、JSON to CSVしたりするとEXCELで見られると思われます。
sample-services.PNG
圧巻。

詳細を以下に貼り付けます。長いので前半のちょっとだけを転載します。

“category” “services__name” “services__href” “services__abstruct”
“コンピューティング” “Amazon EC2” https://aws.amazon.com/jp/ec2/?nc2=h_m1 “Amazon Elastic Compute Cloud (Amazon EC2) は、安全でサイズ変更可能なコンピューティング性能をクラウド内で提供するウェブサービスです。ウェブスケールのクラウドコンピューティングを開発者が簡単に利用できるよう設計されています。 Amazon EC2 のシンプルなウェブサービスインターフェイスによって、手間をかけず、必要な機能を取得および設定できます。お客様のコンピュートリソースに対して、高機能なコントロールが提供され、Amazon の実績あるインフラストラクチャ上で実行できます。Amazon EC2 では、わずか数分間で新規サーバーインスタンスを取得して起動できるようになります。これにより、コンピューティング要件の変化に合わせて、すばやく容量をスケールアップおよびスケールダウンできます。実際に使用した分のみ料金が発生するため、Amazon EC2 はコンピューティングの経済性も変革します。Amazon EC2 を利用すれば、耐障害性に優れたアプリケーションの構築が可能になり、よくある障害のシナリオとは無縁になります。”
“” “Amazon EC2 Container Registry” https://aws.amazon.com/jp/ecr/?nc2=h_m1 “Amazon EC2 Container Registry (ECR) は、完全マネージド型の Docker コンテナレジストリです。このレジストリを使うと、開発者は Docker コンテナイメージを簡単に保存、管理、デプロイできます。Amazon ECR は Amazon EC2 Container Service (ECS) に統合されているため、開発から本番までのワークフローを簡略化できます。Amazon ECR を使用すると、自前のコンテナリポジトリの運用や、基盤となるインフラストラクチャのスケーリングの検討は不要になります。Amazon ECR は非常に可用性が高くスケーラブルなアーキテクチャでイメージをホストするため、コンテナをアプリケーションに確実にデプロイすることが可能です。AWS Identity and Access Management (IAM) に統合すると、各リポジトリをリソースレベルで制御できます。Amazon ECR に前払い料金などの義務はありません。リポジトリに保存したデータ量とインターネットに送信されたデータ量に対してのみ料金が発生します。 AWS 無料利用枠の一環として、Amazon EC2 Container Registry を無料でお試しいただけます。Amazon ECR では、新しいお客様に、月 500 MB 分のストレージを 1 年間にわたって提供いたします。”
“” “Amazon EC2 Container Service” https://aws.amazon.com/jp/ecs/?nc2=h_m1 “Amazon EC2 Container Service (ECS) は、非常にスケーラブルかつ高性能なコンテナ管理サービスで、Docker コンテナに対応しており、Amazon EC2 インスタンスのマネージド型クラスターでアプリケーションを簡単に実行できます。Amazon ECS を使用すると、自社でクラスター管理インフラストラクチャのインストール、運用、スケールを行う必要がなくなります。簡単な API 呼び出しを使用して、Docker 対応アプリケーションの起動と終了、クラスターの完了状態のクエリ、多くの使い慣れた機能 (セキュリティグループ、Elastic Load Balancing、EBS ボリューム、IAM ロールなど) へのアクセスを実行できます。Amazon ECS を使用することで、リソースニーズと可用性要件に基づいて、クラスター全体のコンテナの配置をスケジューリングできます。ビジネスまたはアプリケーション固有の要件を満たすために、独自のスケジューラーまたはサードパーティ製のスケジューラーを統合することもできます。 Amazon EC2 Container Service に追加料金は発生しません。アプリケーションを保存および実行するために作成した AWS リソース(EC2 インスタンス、EBS ボリュームなど)に対してのみ料金が発生します。”
“” “Amazon Lightsail” https://amazonlightsail.com “Everything you need to jumpstart your project on AWS—compute, storage, and networking—for a low, predictable price. Launch a virtual private server with just a few clicks.”
“” “Amazon VPC” https://aws.amazon.com/jp/vpc/?nc2=h_m1 “Amazon Virtual Private Cloud (Amazon VPC) により、アマゾン ウェブ サービス (AWS) クラウドの論理的に分離したセクションをプロビジョニングできます。これにより、AWS リソースをユーザー定義の仮想ネットワークで起動できます。ユーザーの IP アドレス範囲の選択、サブネットの作成、ルートテーブルとネットワークゲートウェイの構成など、仮想ネットワーク環境を完全にコントロールできます。VPC では、リソースやアプリケーションに安全かつ簡単にアクセスできるよう、IPv4 と IPv6 を両方とも使用できます。 Amazon Virtual Private Cloud のネットワーク設定は容易にカスタマイズすることができます。例えば、インターネットとのアクセスが可能なウェブサーバーのパブリック サブネットを作成し、データベースやアプリケーションサーバーなどのバックエンドシステムをインターネットとのアクセスを許可していないプライベート サブネットに配置できます。セキュリティグループやネットワークアクセスコントロールリストなどの複数のセキュリティレイヤーを活用し、各サブネットの Amazon EC2 インスタンスへのアクセスをコントロールすることができます。”
“” “AWS Batch” https://aws.amazon.com/jp/batch/?nc2=h_m1 “AWS Batch を使用することにより、開発者、科学者、およびエンジニアは、数十万件のバッチコンピューティングジョブを AWS で簡単かつ効率的に実行できます。AWS Batch では、送信されたバッチジョブのボリュームと特別なリソース要件に応じて、コンピューティングリソース (CPU やメモリ最適化インスタンス) の最適な数量とタイプを動的にプロビジョニングできます。AWS Batch を使うと、ジョブを実行するためのバッチコンピューティングソフトウェアやサーバークラスターをインストールしたり、管理したりする必要がなくなります。これにより、結果の分析と問題解決に集中できます。AWS Batch では、Amazon EC2 やスポットインスタンスなどの AWS コンピューティングサービスと機能を最大限に活用して、バッチコンピューティングワークロードを計画、スケジュール作成、実行します。 AWS Batch に対する追加料金はありません。バッチジョブを保存したり実行したりするために作成した AWS リソース (EC2 インスタンスなど) に対してのみ料金が発生します。”
“” “AWS Elastic Beanstalk” https://aws.amazon.com/jp/elasticbeanstalk/?nc2=h_m1 “簡単に開始でき、不足を感じることなく利用 AWS Elastic Beanstalk は、Java、.NET、PHP、Node.js、Python、Ruby、Go および Docker を使用して開発されたウェブアプリケーションやサービスを、Apache、Nginx、Passenger、IIS などの使い慣れたサーバーでデプロイおよびスケーリングするための、使いやすいサービスです。”
“” “AWS Lambda” https://aws.amazon.com/jp/lambda/?nc2=h_m1 “AWS Lambda を使用すれば、サーバーのプロビジョニングや管理なしでコードを実行できます。課金は実際に使用したコンピューティング時間に対してのみ発生し、コードが実行されていないときには料金も発生しません。Lambda を使用すれば、実質どのようなタイプのアプリケーションやバックエンドサービスでも管理を必要とせずに実行できます。コードさえアップロードすれば、高可用性を実現しながらコードを実行およびスケーリングするために必要なことは、すべて Lambda により行われます。コードは、他の AWS サービスから自動的にトリガーするよう設定することも、ウェブやモバイルアプリケーションから直接呼び出すよう設定することもできます。 AWS Lambda とは(日本語字幕)”
“” “Auto Scaling” https://aws.amazon.com/jp/autoscaling/?nc2=h_m1 “Auto Scaling により、アプリケーションの可用性を維持できると同時に、お客様が定義する条件に応じて Amazon EC2 のキャパシティーを動的および自動的に縮小あるいは拡張できます。Auto Scaling を EC2 インスタンスのフリート管理に使用することによって、フリートの状態と可用性を維持し、必要な数の Amazon EC2 インスタンスを確実に実行できます。また、Auto Scaling を EC2 インスタンスの動的スケーリングに使用することによって、需要が急激に上昇したときには Amazon EC2 インスタンスの数を自動的に増やしてパフォーマンスを維持し、需要が落ち着いた状態にあるときには能力を縮小してコストを削減できます。Auto Scaling は需要のパターンが一定のアプリケーションにも、使用量が時間、日、週で変動するアプリケーションにも適しています。Auto Scaling を Amazon EC2 で使用する以外に、Application Auto Scaling を使用して、Amazon ECS、Amazon EC2 スポットフリート、Amazon EMR クラスター、AppStream 2.0 フリート、Amazon DynamoDB といった AWS のその他のサービスのリソースを自動的にスケールできます。 12 か月間の AWS 無料利用枠と、24 時間年中無休のカスタマーサービスやサポートフォーラムなどの AWS の基本的なサポート機能を利用できます。”
“” “Elastic Load Balancing” https://aws.amazon.com/jp/elasticloadbalancing/?nc2=h_m1 “Elastic Load Balancing は、アプリケーションへのトラフィックを複数のターゲット (Amazon EC2 インスタンス、コンテナ、IP アドレスなど) に自動的に分散します。Elastic Load Balancing は、変動するアプリケーショントラフィックの負荷を、1 つのアベイラビリティーゾーンまたは複数のアベイラビリティーゾーンで処理できます。Elastic Load Balancing では、3 種類のロードバランサーが用意されています。これらはすべて、アプリケーションの耐障害性を高めるのに必要な高い可用性、自動スケーリング、堅牢なセキュリティを特徴としています。 Application Load Balancer”
“ストレージ” “Amazon Simple Storage Service (S3)” https://aws.amazon.com/jp/s3/?nc2=h_m1 “今日の企業に求められるのは、大規模なデータを簡単かつ安全に収集、保存、分析する能力です。Amazon S3 は、ウェブサイトやモバイルアプリケーション、社内アプリケーション、IoT センサーやデバイスからのデータなど、どこからの、どのような量のデータでも保存と取得が可能なオブジェクトストレージです。これは 99.999999999% の耐久性を提供し、すべての業界のマーケットリーダーによって使用される何百万ものアプリケーションのデータを保管できるように設計されています。S3 では最も厳格なセキュリティ要件を満たす包括的なセキュリティおよびコンプライアンス機能が提供されます。お客様は柔軟にデータを管理して、コスト最適化、アクセス制御、コンプライアンスに対応できるようになります。S3 は、インプレースクエリ機能を備えた唯一のクラウドストレージソリューションであり、S3 の保管データに強力な分析を直接実行できます。また、Amazon S3 は、ISV ソリューションやシステムインテグレータのパートナーによる最大のエコシステムを備えた、最も強力なサポートが提供されているストレージプラットフォームです。 “

続きを読む

【超入門】負荷分散をAWSのロードバランサーを使ってやってみよう

AWSのロードバランサーを使って負荷分散をする(初級編)

この記事は、AWSのELBを使ったことがないけど、ロードバランサー?負荷分散!?という方向けの記事です。

ロードバランサーの役割

大きく分けて二つの機能があります。
1、複数台webサーバーを複数台用意し、負荷を分散させることができます。
2、メンテナンスや障害時には切り離しを行うことができます。

image.png

AWSのロードバランサーの種類

  • ELB (Classic Load Balancer)

    • ALBより前からあった設定が基本的にしやすいロードバランサー
  • ALB (Application Load Balancer)
    • パスベースルーティング機能など豊富になったようなもの
  • NLB (Network Load Balancer)
    • 長時間接続やリージョン内とリージョンを跨いだフェイルオーバーが可能になり、さらに進化したみたいな感じ

早速利用してみる

  • 今回は概念としてわかりやすく、設定しやすいELBを使って見ましょう!

EC2インスタンスを複数用意する

  • 同じアプリケーションサーバーを複数用意します。この時おすすめなのは、現段階で動いているインスタンスのイメージ(AMI)
    を作成し、そのAMIから新しいインスタンスを起動するとほぼ同じアプリケーションサーバーを立てることができます。
  • このへんの記事がわかりやすいかと思います

ロードバランサーを作成する

インスタンスを複数起動しましたら、さっそくELBを作成しましょう

  • ec2の画面からロードバランサーを選びます

スクリーンショット 2017-10-30 21.20.36.png

  • ロードバランサーの作成を押して、ELBを選びます

スクリーンショット 2017-10-30 21.28.20.png

  • ロードバランサーの名前とプロトコルを選択して次へ進みます。
    スクリーンショット 2017-10-30 21.44.35.png

  • セキュリティグループの設定を行って次へ進みます。

スクリーンショット 2017-10-30 21.44.59.png

ヘルスチェックの設定をする

  • ヘルスチェックというのは、サーバーが生きているか確認してくれる機能のことで、生きているか確認できるパスを指定します。
  • 静的サイトであれば/index.htmlでもいいと思いますが、動的サイトなどはDBに負荷がかかるかもしれないので、チェック用のパスを設定するのが良いと思います。

  • 高度な設定では、間隔や何回成功・失敗で正常とするか非正常とするかの設定ができます。

スクリーンショット 2017-10-30 21.45.17.png

ハマりポイント!!

突然サーバーが見えなくなったしエラーも返さない!!
っとなる場合がありますが、おおよそはアプリケーションエラーでヘルスチェックに失敗して自動的に非正常ステータスとなりELBがルーティングを切っている状態になります。
突然サーバーが見えなくなったしエラーも返さない場合は、再起動するのではなくELBを疑って見ましょう!!

その他設定

  • instanceの設定

    • ここで先ほど複数作成したEC2インスタンスを登録します。
  • tagの設定をする

    • nameに対して適当なLBの名前を入れておきましょう。いつか役に立つ時がきます。
      スクリーンショット 2017-10-30 21.45.47.png
  • 確認して作成しましょう!!

  • ロードバランサーが1つ追加されているとおもいます!!

動作確認する

  • 作成後しばらくは、unhealthy(非正常)の状態になっていますが、ヘルスチェックが通りactive(正常)になるとELBのAレコードでサイトが閲覧できるようになります。

ロードバランシングされているか確認する

  • この作業は大事です、できていると思いきやできてない場合がありますので確認は行いましょう
  1. それぞれ全てのEC2インスタンスにSSHする、nginxのaccess.logなどをtailfするなどして待機します。
  2. 先ほどのELBのAレコードでアクセスし、アクセスからバランシングされているかを確認する

この確認作業を行ったら、EC2インスタンスは80番ポートは開ける必要がないですので、EC2のセキュリティグループで閉じておきます。また、ELBからのアクセスを許可するようにするため、ELBにつけているセキュリティグループのIDを設定すると良いでしょう。

おまけ

1台であってもEC2インスタンスの前には ELB を置きましょう

EC2 インスタンスのパブリック IP に CNAME を向けて公開するのはあまりよくないです。
ElasticIPを設定していなければ、システムリブートのメンテナンスの時に、IPが変わってしまうのでDNSも変更しないといけなくなります。
ELB を置いておけば無停止でサーバを入れ替えることができるので、ロードバランサ機能が不要でも使うことがおすすめです。

参考記事

続きを読む