ansible-playbookでvagrantからEC2にデプロイする方法

[EC2側]
まず、EC2を起動し、ターミナルからssh接続
$ ssh ec2-user@**** -i ~/.ssh/***.pem
$ cd /home/release
$ ls
LICENSE appspec.yml index.html scripts

[vagrant側]
.ssh/、inventory/hostsを作成済み
/hosts

[targets]
**.***.**.**

今回デプロイするtest.htmlを作成する

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>
	ansible deploy test
</body>
</html>

$ ls
LICENSE appspec.yml index.html inventory playbook.yml scripts test.html

playbook.yml

- hosts: targets
  sudo: yes
  tasks:
    - name: put test.html
      copy: src=test.html dest=/home/release/ owner=root group=root mode=640

### デプロイ実行
$ ansible-playbook -i inventory/hosts –private-key=.ssh/***.pem playbook.yml -u ec2-user
PLAY [targets] *****************************************************************

TASK [Gathering Facts] *********************************************************
ok: [**.***.**.**]

TASK [put test.html] ***********************************************************
changed: [**.***.**.**]

PLAY RECAP *********************************************************************
**.***.**.** : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

### EC2側で確認
$ ls
LICENSE appspec.yml index.html scripts test.html
$ sudo cat test.html

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>
	ansible deploy test
</body>
</html>

playbook.ymlは、デプロイする場合は、copy: src=${source file} dest=${dest directory} owner=root group=root mode=640 でOK
test.htmlを修正して、再度ansible-playbookを叩いた場合でも、EC2側で反映されていることが確認できます。

ansibleでvagrantからEC2にSSH接続するテスト

Githubではなく、ローカルからEC2にデプロイしたい時もあるでしょう。
という事で、AnsibleからEC2にSSH接続する方法を確認していきます。

### 前提
– vagrantにansibleインストール済

$ ansible –version
ansible 2.8.5

### .gitignore
git pushする際に、秘密鍵がレポジトリにpushされないよう、gitignoreを設定します。
.gitignore

/.ssh

.ssh フォルダにテストファイルを作成して.gitignoreが動くかテスト
$ git add .
$ git commit -m “gitignore added”
$ git push -u origin master

レポジトリにて、.sshがpushされていない事を確認

## -m pingテスト
### .ssh
ec2の秘密鍵を.sshに配置
$ chmod 700 .ssh/

### EC2
instanceからEC2をstart

### host
inventory/hosts
-> instanceのpublic ip(テスト用)を入れる

[targets]
**.***.**.**

### ansible command
$ ansible all -i inventory/hosts -m ping

**.***.**.** | UNREACHABLE! => {
    "changed": false, 
    "msg": "Failed to connect to the host via ssh: Warning: Permanently added '**.***.**.**' (ECDSA) to the list of known hosts.\r\nPermission denied (publickey,gssapi-keyex,gssapi-with-mic).", 
    "unreachable": true
}

鍵認証が上手くいっていない。

$ ansible all -i inventory/hosts –private-key=.ssh/***.pem -m ping -u ec2-user

**.***.**.** | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}

appspec.ymlにhttpd stop, start処理を入れる

– CodeDeployで、service httpd stop, service httpd startの処理を入れる

### shellの作成
@local

scripts/stop_server

#!/bin/bash
isExistApp = `pgrep httpd`
if [[ -n $isExistApp ]]; then
	service httpd stop
fi

scripts/setpermission.sh

#!/bin/bash
chmod -R 777 /home/release/storage

scripts/start_server

#!/bin/bash
service httpd start

appspec.yml

version: 0.0
os: linux
files:
  - source: /
    destination: /home/release
hooks:
  ApplicationStop:
    - location: scripts/stop_server
      timout: 300
      runas: root
  AfterInstall:
    - location: scripts/setpermission.sh
      timeout: 300
      runas: root
  ApplicationStart:
    - location: scripts/start_server
      timout: 300
      runas: root

$ git add .
$ git commit -m “appspec.yml update”
$ git push -u origin master

# ec2 -> instance -> start
$ ssh ec2-user@${public_ip} -i ~/.ssh/***.pem
$ cd /home/release
$ ls
LICENSE appspec.yml index.html
// httpd serverをインストール
$ sudo yum update
$ sudo yum install httpd
$ sudo systemctl start httpd
$ sudo systemctl status httpd
$ sudo systemctl enable httpd
$ sudo systemctl is-enabled httpd

# CodeDeploy -> Applications -> create deployment -> commit idを入力
$ ls
LICENSE appspec.yml index.html scripts

なるほど、appspec.ymlの公式を確認します。
hooksのフローはこちらに掲載されています。
https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/reference-appspec-file-structure-hooks.html

BeforeInstall – 置き換えタスクセットが作成される前にタスクを実行
AfterInstall – 置き換えタスクセットが作成され、ターゲットグループの 1 つがそれに関連付けられた後、タスクを実行

AMI作成とAMIからインスタンスを起動の流れ

### AMIの作成
Instances -> Actions -> Image -> Create Image

### インスタンスの作成
-MyAMIsから作成したAMIを選択する
-後は、インスタンス作成時と同じ
-AMIからインスタンスを作成する場合も、Configure Instance Detailsを再度設定する

InstanceのIAM roleで「AmazonS3ReadOnlyAccess」などをつけたい場合は、再度インスタンスをゼロから作り直すより、AMIから作成した方が圧倒的にスピードが早く、ミスも軽減すると思う。

Git pushでEC2にCodeDeploy

Git pushするとCodeDeployでEC2にDeployされる方法

## IAMユーザの作成
Add user: GitHub
Access type: Programmatic access
Policty: AWSCodeDeployFullAccess
Permission: CreatePolicy

Policy Name: CodeDeploy-Access

Json

{
    "Version": "2020-03-07",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "codedeploy:GetDeploymentConfig",
            "Resource": "arn:aws:codedeploy:ap-northeast-1:${account id}:deploymentconfig:*"
        },
        {
            "Effect": "Allow",
            "Action": "codedeploy:RegisterApplicationRevision",
            "Resource": "arn:aws:codedeploy:ap-northeast-1:${account id}:application:${application name}"
        },
        {
            "Effect": "Allow",
            "Action": "codedeploy:GetApplicationRevision",
            "Resource": "arn:aws:codedeploy:ap-northeast-1:${account id}:application:${application name}"
        },
        {
            "Effect": "Allow",
            "Action": "codedeploy:CreateDeployment",
            "Resource": "arn:aws:codedeploy:ap-northeast-1:${account id}:deploymentgroup:${application name}/${deploy_group}"
        },
        ]
}

### GithubでCodeDeploy用のサービスを追加
– Deploy対象のレポジトリに移動
-> Settings->Integration & Services

Note: GitHub Services have been deprecated. Please contact your integrator for more information on how to migrate or replace a service with webhooks or GitHub Apps.

Servicesは終了しているので、現在はできないようです。

GitHubからEC2へのCodeDeployの手順

## 準備
### 1. IAMロール作成
– CodeDeploy
— Name: CodeDeploy
— Policy: CodeDeployRole
– ec2
— Name: s3readonly
— Policy: AmazonS3ReadOnlyAccess

### 2.VPC作成
– VPC, public subnet, InternetGateway, RouteTable作成
– SecurityGroup作成

## EC2
### 3.インスタンス作成
– Configure Instance DetailsのIAM roleで上記で作成したs3readonlyのroleを選択する
– VPC, public subnet, InternetGateway, RouteTable, SecurityGroupも作成したもの選択する
– SSHログイン

$ ssh ec2-user@****** -i  ~/.ssh/***.pem

### 4.EC2にCodeDeployAgentのインストール
$ sudo yum update
$ sudo yum install ruby
$ sudo yum install aws-cli
$ cd /home/ec2-user
$ aws s3 cp s3://aws-codedeploy-ap-northeast-1/latest/install . –region ap-northeast-1
$ chmod +x ./install
$ sudo ./install auto
$ sudo service codedeploy-agent status
The AWS CodeDeploy agent is running as PID 12399

## 5.Github repository
${repo_name}/appspec.yml

version: 0.0
os: linux
files:
  - source: /
    destination: /home/release

### 6.CodeDeployのapplication作成
– ServicesのCodeDeployからCreate Application
— test

### 7. Deployment group
– Create deployment group押下
Deployment group name: testDeploy
Service role: codeDeploy
Deployment type: In place
Environment configuration: Amazon EC2 instances
->key:test
Deployment settings: CodeDeployDefault.AllAtOnce

### 8.Create deployment
Deployment group: testDeply
Revision type: My application is stored in Github
GitHub token name: Githubのname
Repository name: ${githubname}/${repository name}
Commit ID: GithubのcommitのID

$ pwd
/home/release
$ ls
LICENSE appspec.yml index.html

EC2起動からLaravelプロジェクトのデプロイまで

### 1. elastic ipをインスタンスに割り当て & security groupにhttp追加
-elastic ipをインスタンスに割り当て
-security groupのruleにHTTPを追加

### 2. ssh ログイン
ssh ec2-user@${elastic ip} -i ~/.ssh/***.pem

### 3.ec2-user グループ
$ sudo groupadd www
// ユーザー(ec2-user)を www グループに追加
$ sudo usermod -a -G www ec2-user
$ groups

### 4. rootユーザpass変更
$ sudo su –
$ passwd

### 5. git install
// 省略

### 6. Node.js install
// 省略

### 7. Apache HTTP Server
// 省略

### 8. php 7.3 install
// 省略

### 9. MySQL 8.0 install
// 省略 インスタンスタイプがnanoだとmemory不足となるので要注意

### 10. ansible install
// 省略

### 11. date time変更
// 省略

### 12. *.conf の設置
$ sudo mkdir /var/www/log
$ sudo vi /etc/httpd/conf.d/custom.conf

# エラーログ
ErrorLog "/var/www/log/error_log"

# アクセスログ
<IfModule log_config_module>
    CustomLog "/var/www/log/access_log" combined
</IfModule>

### 13. git clone
$ sudo git clone https://github.com/***/***.git

// ドキュメントルート変更
$ sudo vi /etc/httpd/conf.d/custom.conf

DocumentRoot "/var/www/hoge/public"

# .htaccess 有効化
<Directory /var/www/hoge/public>
    AllowOverride All
</Directory>         

### 14. パーミッション変更
$ sudo chmod -R 777 hoge/storage
$ sudo chmod -R 775 hoge/bootstrap/cache
// /var/www とそのコンテンツのグループ所有権を www グループに変更
$ sudo chown -R root:www /var/www

### 15. project
$ curl -sS https://getcomposer.org/installer | php
$ sudo php composer.phar install
$ sudo php composer.phar dump-autoload
$ sudo php artisan key:generate
// 省略

### 16. Elastic ipにアクセスし、動作確認
http://***/login
http://***/register

EC2の起動からSSH接続までの一連の流れ

### 前提条件
– MFA認証のIAMユーザ作成済
– VPC、public subnet、InternetGateway、RouteTable作成済
– セキュリティグループ作成済
– Key Pairsで秘密鍵・公開鍵作成済

### EC2
1. launch instance
2. Amazon Linux 2 AMI (HVM), SSD Volume Type 64bit(x86)
3. Choose instance type
4. networkで作成したVPC、public subnetを設定(InternetGateway紐付け済)
  Auto-assign Public IPをenableにする disableのままだと、privateしか割り当てられない
5. storage sizeはdefaultの8GiB
6. Add tag: keyにdev, valueにdev-testとする
7. Configure Security Groupで作成したsecurity groupを紐付け(ssh許可)
8. 作成したkey pairを選択
※VPCのDNS resolution、DNS hostnamesがEnabledになっていることを確認。desabledの場合はactionで変更。instanceを再起動

接続

ssh ec2-user@${public ip} -i  ~/.ssh/***.pem

cyberduckでも同様に、ssh-private keyで.pemを指定すると、接続できる。

お、お、お、お疲れ様でしたー

EC2のKey Pairs作成(mac編)

### Key Pairs作成
– EC2のleft paneのNetwork & Security -> Key Pairsを選択
– Create key pair
– Name: aws-dev(file formatはpem)

### macの.sshに保存
$ pwd
/Users/${username}
$ ls -a
$ cd .ssh
$ ls
aws-dev.pem

アクセス権限の変更: オーナーのみ読み出しができる400(所有者:R)
$ sudo chmod 400 aws-dev.pem 
$ ls -l
-r——–@

pemファイルは秘密鍵
流れとしては
1. ssh接続要求
2. aws側でランダムデータを生成し、公開鍵を使ってクライアントに送る
3. 受け取ったクライアント側は秘密鍵でデータを復号化して送り返す
4. aws側でランダムデータと受け取った復号化データを比較して認証する

このような仕組みから、key parisはAWSで生成するのではなく、ローカルマシンでの生成が望ましい。
$ ssh-keygen -t rsa -f hoge.pem

VPCセキュリティグループの作成

セキュリティグループとは?
-> セキュリティグループとはインスタンスに関連付ける仮想ファイアウォール
-> インバウンドトラフィックとアウトバウンドトラフィックを許可する形でルール追加
-> 拒否するルールは設定できない
-> セキュリティグループはsubnetの中

### Security groupの作成
Security group name: dev-security-group
Description: Allow SSH Access
VPC: dev-vpc

Edit inbound rules
Type: SSH
Protocol: TCP
PortRange: 22
Source: MyIP(全てのipを許可する場合は0.0.0.0/0)