CloudWatch Logsを使いたい

### CloudWatch Logsの主な機能
– インスタンスやサービスログの蓄積
– ログのモニタリング
– ログのフィルタリング
– ログデータのアーカイブ
– ログデータの分析
– ログのアラート化

### IAMロールの作成
AWS Service -> EC2 -> Add Permissionで “CloudWatchLogsFullAccess” をつける -> role nameはそのまま”CloudWatchLogsFullAccess” にする

### roleをattach
Modify IAM roleで作成した”CloudWatchLogsFullAccess”をroleにつける

sshログインしてapache2を入れる
$ sudo yum install httpd
$ sudo systemctl start httpd
$ sudo systemctl status httpd
$ sudo systemctl enable httpd
$ sudo systemctl is-enabled httpd
$ httpd -v

public ipを叩き、ipが入っていることを確認

cloudwatch logsエージェントインストール
$ sudo yum install -y awslogs

/etc/awslogs/awscli.confがconfファイル。us-east-1になっているので、ap-northeast-1に変更する
$ sudo cat /etc/awslogs/awscli.conf

[plugins]
cwlogs = cwlogs
[default]
region = us-east-1
[plugins]
cwlogs = cwlogs
[default]
region = ap-northeast-1

$ sudo cat /etc/awslogs/awslogs.conf

[/var/log/messages]
datetime_format = %b %d %H:%M:%S
file = /var/log/messages
buffer_duration = 5000
log_stream_name = {instance_id}
initial_position = start_of_file
log_group_name = /var/log/messages

fileで対象となるログファイルを指定する
buffer_duration: ログイベントのバッチ期間

apacheエラーログを追加

[Apache_AccessLog]
log_group_name = TestSV_Apache
log_stream_name = {instance_id}_accesslog
file = /etc/httpd/logs/access_log
datetime_format = %a %b %d %H:%M:%S %Y
initial_position = start_of_file
buffer_duration = 5000

[Apache_ErrorLog]
log_group_name = TestSV_Apache
log_stream_name = {instance_id}_errorlog
file = /etc/httpd/logs/error_log
datetime_format = %a %b %d %H:%M:%S %Y
initial_position = start_of_file
buffer_duration = 5000

amazon linux2 amiの場合
$ sudo systemctl start awslogsd

CloudWatch Logsで確認するとログが出力されている

なるほど、これをS3に転送するのね
なんか凄いことになってるな

CloudWatch基本項目

CloudWatch基本事項
– Namespace
– Metrics
– Time stamps
– Dimensions
– Statics
– Alarms

### Namespace
複数のメトリクスをまとめてコンテナ(箱)で管理する概念
異なる名前空間のメトリクスは相互に切り離されている

### Metrics
ある時間ごとのデータポイントのセット
作成されたリージョンのみ存在
メトリクスの保持期間がある

### Time stamps
メトリクスデータポイントの必須情報

### dimension
メトリクスを一意に識別する名前/値のペア

### Statistics
指定した期間のメトリクスデータの集計

### Alarms
指定した期間の単一のメトリクスを監視

### アラームの作成
CloudWatchの画面でアラーム作成

Metrics Name, Image ID, Statistic, Periodを選択

うむ、中々素晴らしいですね。

CloudWatch入門

CloudWatchとは?
-> AWSのリソースやアプリケーション、オンプレミスのサーバをモニタリングするためのマネージドサービス
-> 監視そのももの機能以外にアラーム通知、イベント検知、可視化などの機能がある

### CloudWatchメトリクス
メトリクスとは、システムのパフォーマンスに関するデータ
監視対象のリソースからメトリクスを収集することで監視を行う
CloudWatchメトリクスでは、まず名前空間という単位でグループ化される
その中でディメンション(=名前と値)の組み合わせごとにグループ化される
※統計、期間、ディメンション、標準メトリクス

### CloudWatch Logs
ログファイルの監視と保存を担う機能
AWSサービスやオンプレミスサーバからエージェント経由でログメッセージをCloudWatchエンドポイントに転送することでログデータの保存が出来る。ログデータは保存期間として1日~永久保存を選択できる
ロググループというログのグループ単位があり、その中にログストリームというグループの単位があり、その中にログイベントが保存
Kinesis Data Streams, Kinesis Data Firehose, Lambdaに配信できる
S3に保存するとコストを抑えられる

### CloudWatch Event
AWSリソースの状態が変化した場合にアクションを実行できる

アラームの設定
– 対象のメトリックス
– 統計方法: 平均、最大、合計などの中から適切な統計方法を選択
– 期間: 何分単位に1回メトリクスを評価するのか設定

### CloudWatch Dashboard
複数のログやメトリクスを一つの画面で確認することができる

実際に、CloudWatchメトリクス、CloudWatch Logs, CloudWatch Alarms、CloudWatch Eventを一つずつ使ってみないとわからんな…

pgAdminとは?

pgAdminとは?
-> PostgreSQLの管理ツールの一つで、ネットワークを通じて遠隔のデータベースサーバをGUIで管理することができる

### Ubuntu20.04にpgadminのインストール
0. 既にpsql v14が入っている状態
$ psql -V
psql (PostgreSQL) 14.2 (Ubuntu 14.2-1.pgdg20.04+1)

1. リポジトリの設定
$ sudo curl https://www.pgadmin.org/static/packages_pgadmin_org.pub | sudo apt-key add
$ sudo sh -c ‘echo “deb https://ftp.postgresql.org/pub/pgadmin/pgadmin4/apt/$(lsb_release -cs) pgadmin4 main” > /etc/apt/sources.list.d/pgadmin4.list && apt update’

2. pgAdminインストール
$ sudo apt install pgadmin4

3. メールアドレスとパスワードの登録
$ sudo /usr/pgadmin4/bin/setup-web.sh

4. プラウザから起動
http://192.168.56.10/pgadmin4

なるほどー、少し理解した。

標準出力とは?

標準出力とは、コンピュータ上で実行されているプログラムが、特に何も指定されていない場合に標準的に利用するデータ出力先。コンピュータの出力装置やOSが提供するデータ出力機能・経路などを指し、多くのシステムではディスプレイ装置による利用者への文字表示が標準出力に設定されている。
標準エラー出力もある。

$ cp -v test.txt test_cp.txt
‘test.txt’ -> ‘test_cp.txt’
上記は入力元・出力先を指定している。

標準出力とは、コマンド/アプリ側で入力元・出力先を明示することなく使用できる入力・出力のこと

### 3種類の標準
– 入力…標準入力の1系統
– 出力…標準出力、標準エラーの2系統

標準入力…加工対象のデータの入力元や、ユーザからのパラメータ入力受付用(cpでの上書き確認のy/n)
標準出力…加工済みデータの出力先や、ログ、メッセージ等情報出力用
標準エラー…確認メッセージや警告、エラーといった情報の出力用

### アプリ使用者の立場として
– シェルでコマンド実行
– デフォルト
– リダイレクト・パイプライン

なんか分かったような分かってないような

CodeDeployでECSにデプロイしようとした時にDeployment group’s ECS service must be configured for a CODE_DEPLOY deployment controller

CodeDeployでECSにデプロイしようとして、CodeDeployのdeploymentgroup作成時に”Deployment group’s ECS service must be configured for a CODE_DEPLOY deployment controller”と表示された時

### ECSでCodeDeployを使う前準備
1. IAMでECSのCodeDeploy IAM roleを作成する
Use casesで”CodeDeploy”を選択し、”CodeDeploy – ECS”を選ぶ
2. Permission: AWSCodeDeployRoleForECS
3. Role Name: ecsCodeDeployRole

これでCodeDeployでDeployment groupを作成しようとすると…

「Deployment group’s ECS service must be configured for a CODE_DEPLOY deployment controller.」と表示される

どうやら、cloudformationでfargateを作成しようとしたときに、Blue/Greenではなく、rolling updateになっていた模様
ecs-fargate-01.yml

# ------------------------------------------------------------#
#  ECS Service
# ------------------------------------------------------------#
  ECSService:
    Type: AWS::ECS::Service
    DependsOn: ALBListener
    Properties:
      Cluster: !Ref ECSCluster
      DesiredCount: !Ref ECSTaskDesiredCount
      LaunchType: FARGATE
      LoadBalancers:
        -
          TargetGroupArn: !Ref TargetGroup
          ContainerPort: 80
          ContainerName: !Sub "${PJPrefix}-${ECSContainerName}"
      NetworkConfiguration:
       AwsvpcConfiguration:
           AssignPublicIp: ENABLED
           SecurityGroups:
             - !Ref ECSSecurityGroup
           Subnets:
             - { "Fn::ImportValue": !Sub "${PJPrefix}-public-subnet-a" }
             - { "Fn::ImportValue": !Sub "${PJPrefix}-public-subnet-c" }
      ServiceName: !Sub "${PJPrefix}-${ECSServiceName}"
      TaskDefinition: !Ref ECSTaskDefinition

DeploymentControllerを修正して再度、cloudformationで作成する

  ECSService:
    Type: AWS::ECS::Service
    DependsOn: ALBListener
    Properties:
      Cluster: !Ref ECSCluster
      DesiredCount: !Ref ECSTaskDesiredCount
      DeploymentController:
        Type: CODE_DEPLOY

これでOK
でも、CloudFormation上のエラーログを見るのと、アプリ開発でエラーログ見るのだと、勝手がずいぶん違うな…

GitLab CI/CD 入門

### Gitlab CI/CDとは
– Gitlabリポジトリ内で.gitlab-ci.ymlで定義するCI/CDの仕組み
– 一つのまとまった処理の単位をpipelineとし、pipelineはjobの集合
– jobはstageによってカテゴライズ・順序付けができ、シーケンシャルにもパラレルに実行できる
– Gitlab CI/CDの実行主体はrunnerという
– RunnerにはDocker, Kubernetes, Virtualbox, Parallels executor, SSH, Shell executorなどがある
– GitlabServerをローカルに建て、リモートレポジトリとして扱うこともできる

.gitlab-ci.yml

stages:
  - prepare
  - echo

prepare-job:
  stage: prepare
  script:
    - echo "Prepare before echo-job..."

echo-job:
  stage: echo
  script:
    - echo "Ahoy! This is Gitlab CI/CD!"

$ tree
.
└── test.html
└── .gitlab-ci.yml

stage:では、pipelineにおけるjobの実行順序を制御
prepare-job, echo-jobはjobの定義

### Gitlab runnerについて
jobはrunner上で実行される
– shared runner
  – Gitlab.comのリソースを共有する形でjobを実行するRunner
– specific runner
— GitlabRunnerを導入した環境でtokenを用いてregisterすることでgitlabと連携し、ci/cdが実行される

### 実際の運用上での.gitlab-ci.yml

# ------------------------------------------------------------#
#  ECS Service
# ------------------------------------------------------------#
  ECSService:
    Type: AWS::ECS::Service
    DependsOn: ALBListener
    Properties:
      Cluster: !Ref ECSCluster
      DesiredCount: !Ref ECSTaskDesiredCount
      LaunchType: FARGATE
      LoadBalancers:
        -
          TargetGroupArn: !Ref TargetGroup
          ContainerPort: 80
          ContainerName: !Sub "${PJPrefix}-${ECSContainerName}"
      NetworkConfiguration:
       AwsvpcConfiguration:
           AssignPublicIp: ENABLED
           SecurityGroups:
             - !Ref ECSSecurityGroup
           Subnets:
             - { "Fn::ImportValue": !Sub "${PJPrefix}-public-subnet-a" }
             - { "Fn::ImportValue": !Sub "${PJPrefix}-public-subnet-c" }
      ServiceName: !Sub "${PJPrefix}-${ECSServiceName}"
      TaskDefinition: !Ref ECSTaskDefinition

ここに、DeploymentController:Type: CODE_DEPLOYを追記しないといけなさそう
一旦、cloudformationを削除して、stackを以下に変更します。

  ECSService:
    Type: AWS::ECS::Service
    DependsOn: ALBListener
    Properties:
      Cluster: !Ref ECSCluster
      DesiredCount: !Ref ECSTaskDesiredCount
      DeploymentController:
        Type: CODE_DEPLOY

なんか上手くいったけど、今度はtarget-groupが2つ必要とエラーが出るな…

お名前.comのドメインをRoute53に移管したい

ドメイン移行の手順
– ドメイン移管できるようにアンロック
– ドメインのプライバシー保護を無効化
– ドメインの登録Emailアドレスが更新されていることを確認
– authorization codeを取得

### ドメインをアンロック
ドメイン移管ロックを押下する

ステータスがOFFになっていれば特段操作する必要なし

### ドメインのプライバシー保護を無効化
移管対象のドメインに対して、現在のドメインレジストラでプライバシー保護を解除しておく必要がある。
お名前.comではドメイン一覧で「Whois情報公開代行」で解除する必要がある

「Whois情報公開代行設定」の設定を変更する
ページ下部の設定情報の変更ボタンを押す

すると、Whois公開代行が「未設定」のステータスになる。

### ドメインの登録Emailアドレスが更新されていることを確認
連絡先メールアドレスを確認する

### authorization codeを取得
移管に必要なのがauthorization code
認証コードは現在のドメインレジストらが発行
移管先のレジストラから現在のレジストラに認証コードを含む移管リクエストを送信し、現在のレジストラが移管を承認する
ドメイン一覧のドメイン詳細で確認できる

### Route53へのdomain移管の開始
Registered domainsで、Transferを選択
対象ドメインを選択して add cartとする

Authorization Codeとname serverの値を入力
Name server optionsでRoute53の「Import name servers from a Route 53 hosted zone that has the same name as the domain」を選択する

どのタイミングで移管されるかドメインレジストリにより管理できないので、ちょっと考えないといけないですね。

[AWS] Route53でドメインを取得したい

domain searchの画面で、取得したいドメイン名を入力すると結果が表示される

購入すると、”Domain registration in progress” と表示される。
なるほどー
夜中に登録して、朝起きたら登録完了していました。

ちなみに、Privacy Protectionでenableとして設定すると、Protectionでadmin, test, techなどの名前、住所、連絡先が非表示設定となります。
$ whois hoge.com で確認できます。

Whether you want to conceal your contact information from WHOIS queries. If you select Enable, your contact information will be masked. If you select Disable, your contact information will be publicly available.
When the contact type is Person:

Privacy protection hides some contact details for .link domains.
Enable

[AWS CloudFormation] ECS + Fargate

AWSTemplateFormatVersion: "2010-09-09"
Description:
  Fargate for ECS Create

Metadata:
  "AWS::CloudFormation::Interface":
    ParameterGroups:
      - Label:
          default: "Project Name Prefix"
        Parameters:
          - PJPrefix
      - Label:
          default: "InternetALB Configuration"
        Parameters:
          - InternetALBName
          - TargetGroupName
      - Label:
          default: "Fargate for ECS Configuration"
        Parameters:
          - ECSClusterName
          - ECSTaskName
          - ECSTaskCPUUnit
          - ECSTaskMemory
          - ECSContainerName
          - ECSImageName
          - ECSServiceName
          - ECSTaskDesiredCount

    ParameterLabels:
      IneternetALBName:
        default: "InternetALBName"
      TargetGroupName:
        default: "TargetGroupName"
      ECSClusterName:
        default: "ECSClusterName"
      ECSTaskName:
        default: "ECSTaskName"
      ECSTaskCPUUnit:
        default: "ECSTaskCPUUnit"
      ECSTaskMemory:
        default: "ECSTaskMemory"
      ECSContainerName:
        default: "ECSContainerName"
      ECSImageName:
        default: "ECSImageName"
      ECSServiceName:
        default: "ECSServiceName"
      ECSTaskDesiredCount:
        default: "ECSTaskDesiredCount"

# ------------------------------------------------------------#
# Input Parameters
# ------------------------------------------------------------# 
Parameters:
  PJPrefix:
    Type: String

#InternetALB
  InternetALBName:
    Type: String
    Default: "alb"

#TargetGroupName
  TargetGroupName:
    Type: String
    Default: "tg"

#ECSClusterName
  ECSClusterName:
    Type: String
    Default: "cluster"

#ECSTaskName
  ECSTaskName:
    Type: String
    Default: "task"

#ECSTaskCPUUnit
  ECSTaskCPUUnit:
    AllowedValues: [256, 512, 1024, 2048, 4096]
    Type: String
    Default: "256"

#ECSTaskMemory
  ECSTaskMemory:
    AllowedValues: [ 256, 512, 1024, 2048, 4096 ]
    Type: String
    Default: "512"

#ECSContainerName
  ECSContainerName:
    Type: String
    Default: "container"

#ECSImageName
  ECSImageName:
    Type: String
    Default: ""

#ECSServiceName
  ECSServiceName:
    Type: String
    Default: "service"

#ECSTaskDesiredCount
  ECSTaskDesiredCount:
    Type: Number
    Default: 1

Resources:
# ------------------------------------------------------------#
#  SecurityGroup for ALB
# ------------------------------------------------------------#
  ALBSecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      VpcId: { "Fn::ImportValue": !Sub "${PJPrefix}-vpc" }
      GroupName: !Sub "${PJPrefix}-alb-sg"
      GroupDescription: "-"
      Tags:
        - Key: "Name"
          Value: !Sub "${PJPrefix}-alb-sg"

# Rule
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: "0.0.0.0/0"

        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: "0.0.0.0/0"

# ------------------------------------------------------------#
#  SecurityGroup for ECS Service
# ------------------------------------------------------------#
  ECSSecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      VpcId: { "Fn::ImportValue": !Sub "${PJPrefix}-vpc" }
      GroupName: !Sub "${PJPrefix}-ecs-sg"
      GroupDescription: "-"
      Tags:
        - Key: "Name"
          Value: !Sub "${PJPrefix}-ecs-sg"

# Rule
  ECSSecurityGroupIngress:
    Type: "AWS::EC2::SecurityGroupIngress"
    Properties:
      IpProtocol: tcp
      FromPort: 80
      ToPort: 80
      SourceSecurityGroupId: !GetAtt [ ALBSecurityGroup, GroupId ]
      GroupId: !GetAtt [ ECSSecurityGroup, GroupId ]

# ------------------------------------------------------------#
#  Target Group
# ------------------------------------------------------------#
  TargetGroup:
    Type: "AWS::ElasticLoadBalancingV2::TargetGroup"
    Properties:
      VpcId: { "Fn::ImportValue": !Sub "${PJPrefix}-vpc"}
      Name: !Sub "${PJPrefix}-${TargetGroupName}"
      Protocol: HTTP
      Port: 80
      TargetType: ip


# ------------------------------------------------------------#
#  Internet ALB
# ------------------------------------------------------------#
  InternetALB:
    Type: "AWS::ElasticLoadBalancingV2::LoadBalancer"
    Properties:
      Name: !Sub "${PJPrefix}-${InternetALBName}"
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-${InternetALBName}"
      Scheme: "internet-facing"
      LoadBalancerAttributes:
        - Key: "deletion_protection.enabled"
          Value: false
        - Key: "idle_timeout.timeout_seconds"
          Value: 60
      SecurityGroups:
        - !Ref ALBSecurityGroup
      Subnets:
        - { "Fn::ImportValue": !Sub "${PJPrefix}-public-subnet-a" }
        - { "Fn::ImportValue": !Sub "${PJPrefix}-public-subnet-c" }

  ALBListener:
    Type: "AWS::ElasticLoadBalancingV2::Listener"
    Properties:
      DefaultActions:
        - TargetGroupArn: !Ref TargetGroup
          Type: forward
      LoadBalancerArn: !Ref InternetALB
      Port: 80
      Protocol: HTTP

# ------------------------------------------------------------#
# ECS Cluster
# ------------------------------------------------------------# 
  ECSCluster:
    Type: "AWS::ECS::Cluster"
    Properties:
      ClusterName: !Sub "${PJPrefix}-${ECSClusterName}"

# ------------------------------------------------------------#
#  ECS LogGroup
# ------------------------------------------------------------#
  ECSLogGroup:
    Type: "AWS::Logs::LogGroup"
    Properties:
      LogGroupName: !Sub "/ecs/logs/${PJPrefix}-ecs-group"

# ------------------------------------------------------------#
#  ECS TaskDefinition
# ------------------------------------------------------------#
  ECSTaskDefinition:
    Type: "AWS::ECS::TaskDefinition"
    Properties:
      Cpu: !Ref ECSTaskCPUUnit
      ExecutionRoleArn: !Sub "arn:aws:iam::${AWS::AccountId}:role/ecsTaskExecutionRole"
      Family: !Sub "${PJPrefix}-${ECSTaskName}"
      Memory: !Ref ECSTaskMemory
      NetworkMode: awsvpc
      RequiresCompatibilities:
        - FARGATE

#ContainerDefinitions
      ContainerDefinitions:
        - Name: !Sub "${PJPrefix}-${ECSContainerName}"
          Image: !Ref ECSImageName
          LogConfiguration:
            LogDriver: awslogs
            Options:
              awslogs-group: !Ref ECSLogGroup
              awslogs-region: !Ref "AWS::Region"
              awslogs-stream-prefix: !Ref PJPrefix
          MemoryReservation: 128
          PortMappings:
            - HostPort: 80
              Protocol: tcp
              ContainerPort: 80

# ------------------------------------------------------------#
#  ECS Service
# ------------------------------------------------------------#
  ECSService:
    Type: AWS::ECS::Service
    DependsOn: ALBListener
    Properties:
      Cluster: !Ref ECSCluster
      DesiredCount: !Ref ECSTaskDesiredCount
      LaunchType: FARGATE
      LoadBalancers:
        -
          TargetGroupArn: !Ref TargetGroup
          ContainerPort: 80
          ContainerName: !Sub "${PJPrefix}-${ECSContainerName}"
      NetworkConfiguration:
       AwsvpcConfiguration:
           AssignPublicIp: ENABLED
           SecurityGroups:
             - !Ref ECSSecurityGroup
           Subnets:
             - { "Fn::ImportValue": !Sub "${PJPrefix}-public-subnet-a" }
             - { "Fn::ImportValue": !Sub "${PJPrefix}-public-subnet-c" }
      ServiceName: !Sub "${PJPrefix}-${ECSServiceName}"
      TaskDefinition: !Ref ECSTaskDefinition

# ------------------------------------------------------------#
# Output Parameters
# ------------------------------------------------------------#
Outputs:
#InternetALB
  ALBDNSName:
    Value: !GetAtt InternetALB.DNSName
    Export:
      Name: !Sub "${PJPrefix}-${InternetALBName}-dnsname"

#ECSClusterName
  ECSClusterName:
    Value: !Sub "${PJPrefix}-${ECSClusterName}"
    Export:
      Name: !Sub "${PJPrefix}-${ECSClusterName}-name"

#ECSClusterARN
  ECSClusterARN:
    Value: !GetAtt ECSCluster.Arn
    Export:
      Name: !Sub "${PJPrefix}-${ECSClusterName}-arn"

#ECSLogGroup
  ECSLogGroupName:
    Value: !Sub "/ecs/logs/${PJPrefix}-ecs-group"
    Export:
      Name: !Sub "${PJPrefix}-ecs-group-name"

うおおおおおおおおおお
なんかcloudformation理解してきたああああああああああああああ