今日はなにの日。

気になったこと勉強になったことのメモ。

今日は、AWSでMySQL検証環境を最速構築の日。

目次

とある日

AWSで、MySQLの環境が検証用としてほしいなと思いました。

そうだ、CDKで作ろうと思い、以降錯誤しながら四時間ぐらいで作りました。

はじめに

想定読者

AWSをそこそこ勉強している人。

CDKをそこそこ使っている人。

注意

  • 使用するAWSサービスについての詳細説明はしません
  • CDK(Python)で開発しますが、プログラムの詳細説明はしません
  • 別環境での構築をしたので、コンソール画面などはありません
  • CDKの構築については言及しません
  • 別環境から移植してるので間違っている部分があるかと思います

AWSMySQL最速構築

概要

まず、検証用なので検証時のみ使用することとするので、繰り返し使用できようにする必要があります。

ということで、CDK(Python)でコード化を行います。

構築速度

cdk deployを実行してから時間を計測しています。

EC2インスタンスが、操作可能になるまでに約4分。

EC2に接続してMySQLの構築をして約2分。

合わせて、6分あればMySQLが触れる環境が作れます。

MySQL構築環境

MySQLを構築するAWSサービスは、EC2を採用します。

理由としては、ユーザデータでコマンドを実行してMySQLをインストールが事前に行えること。

そして、デプロイまでが早いことです。

ほかにも、追加要件が発生した場合に、対応がしやすいことなどが挙げれます。

MySQLバージョン

今回はMySQL8.0を構築します。

CDK

ディレクトリ構造

cdk
├EC2mysql
│   ├EC2mysql.py
│   └userdata.sh
└app.py

cdk synth`やcdk deploy`はcdkのディレクトリで実行しています。

コード

EC2mysql.py

from aws_cdk import (
    aws_ec2,
    core,
    aws_lambda as _lambda,
    aws_apigateway as _apigw,
    aws_iam as _iam,
    aws_ec2 as _ec2
)

import json

class EC2inMySQL80(core.Stack):

    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)
        # VPC
        vpc_cidr = '10.0.0.0/16'
        subnet_mask = 24
        vpc = _ec2.Vpc(
            self,
            id="updraft-cdk-dev-vpc",
            cidr=vpc_cidr,
            subnet_configuration=[
                _ec2.SubnetConfiguration(
                    cidr_mask=subnet_mask, name='public', subnet_type=_ec2.SubnetType.PUBLIC)
            ]
        )
        # セキュリティグループ作成
        security_group_ssh = _ec2.SecurityGroup(
            self,
            id='updraft-cdk-dev-sg',
            vpc=vpc,
            allow_all_outbound=True,
            security_group_name='updraft-cdk-dev-sg-vpc-ie',
            description='For MySQL validation environment by updraft'
        )
        security_group_ssh.add_ingress_rule(
            peer=_ec2.Peer.ipv4("xxx.xxx.xxx/xx"),
            connection=_ec2.Port.tcp(22),
        )
        security_group_ssh = _ec2.SecurityGroup.from_security_group_id(
            self,
            id="updraft-cdk-ec2",
            security_group_id=security_group_ssh.security_group_id
        )
        # AMIイメージ
        amzn_linux = _ec2.MachineImage.latest_amazon_linux(
            generation=_ec2.AmazonLinuxGeneration.AMAZON_LINUX_2,
            edition=_ec2.AmazonLinuxEdition.STANDARD,
            virtualization=_ec2.AmazonLinuxVirt.HVM,
            storage=_ec2.AmazonLinuxStorage.GENERAL_PURPOSE
        )
        # userdata 処理
        userData = _ec2.UserData.for_linux(shebang='#!/bin/bash')
        file = ""
        with open("./EC2mysql/userdata.sh", encoding="utf-8"as t:
            file = t.readlines()
            file = "\n".join(file)
        # ↓が文字列を要求するので改行を追加して配列を文字列に変換処理
        userData.add_commands(file)
        # EC2
        ec2 = _ec2.Instance(
            self,
            id='updraft-dev-ec2',
            machine_image=amzn_linux,
            instance_name="updraft-dev-mysql",
            instance_type=_ec2.InstanceType("t2.micro"),
            key_name='updraft-web-ec2-01',
            security_group=security_group_ssh,  #  配列定義するとエラーになる
            vpc=vpc,
            user_data=userData
        )
        # EIPの付与
        ec2eip = _ec2.CfnEIP(
            self, id="updraft-ec2eip",
            instance_id=ec2.instance_id
        )
EIPについて

peer=_ec2.Peer.ipv4("xxx.xxx.xxx/xx"):接続するIPを指定してください。

EC2セキュリティグループ
security_group=security_group_ssh,  #  配列定義するとエラーになる
security_group=[security_group_ssh],  #  配列定義するとエラーになる

例とかみても、配列だったので配列にしていたのですがうまく行かず。

初めは、下のように配列で定義していたのですが、エラーが起きうまくできないので配列じゃなくしたらできた。

app.py

import os
from aws_cdk import core as cdk
from EC2mysql.cdk_stack import EC2inMySQL80

app = core.App()
EC2inMySQL80(app, "EC2inMySQL80")
app.synth()

EC2mysqlをインポートして呼び出します。

ユーザデータ

概要

MySQLインストールをインストールするのは、EC2のユーザデータでコマンドを実行して行います。

更に、MySQL8.0からはrootのパスワードを初期化しないといけないので、

その処理を自動化するのは難しそうなので。

シェルスクリプトで初期化コマンドを実行して初期パスワードを自動で入力が行われるまでを行います。

それと、MySQLにログインする際にコマンドを打つのはめんどくさいので、それも自動化するシェルスクリプトを作成します。

スクリプト

sudo yum -y remove mariadb - libs
sudo rpm -ivh https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm
sudo yum -y install mysql - community - server mysql - devel
sudo systemctl start mysqld.service
sudo systemctl enable mysqld.service
sudo cat /var/log/mysqld.log | grep 'temporary password'
sudo yum -y install expect
echo "#!/bin/bash" > /home/ec2-user/mysql.sh
echo 'expect -c "' >> /home/ec2-user/mysql.sh
echo  '  spawn sudo mysql_secure_installation' >> /home/ec2-user/mysql.sh
echo '  expect \"Enter your name:\"' >> /home/ec2-user/mysql.sh
temp = '  send \"'
temp +=`sudo cat /var/log/mysqld.log | grep 'temporary password' | awk '{print $NF}'`
temp += '\n\"'
echo "$temp" >> /home/ec2-user/mysql.sh
echo '  interact"' >> /home/ec2-user/mysql.sh
chmod 777 /home/ec2-user/mysql.sh
echo " mysql -uroot -p@a@1@2@3@4@55azA@" > /home/ec2-user/mylogin.sh
chmod 777 /home/ec2-user/mylogin.sh

MySQLインストール

sudo yum - y remove mariadb - libs
sudo rpm - ivh https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm
sudo yum - y install mysql-community-servermysql-devel
sudo systemctl start mysqld.service
sudo systemctl enable mysqld.service

手順としては下記のとおりです。

  1. MariaDB削除
  2. MySQLパッケージインストール
  3. MySQLインストール
  4. MySQL起動
  5. MySQL自動起動

rpmでインストールするMySQLのURLは任意のOSバージョンを選択して下さい。

MySQL初期化

sudo yum - y install expect
echo "#!/bin/bash" > /home/ec2-user/mysql.sh
echo 'expect -c "' >> /home/ec2-user /mysql.sh
echo  '  spawn sudo mysql_secure_installation' >> /home/ec2-user/mysql.sh
echo '  expect \"Enter your name:\"' >> /home/ec2-user/mysql.sh
temp = '  send \"'
temp +=`sudo cat /var/log/mysqld.log | grep 'temporary password' | awk '{print $NF}'`
temp += '\n\"'
echo "$temp" >> /home/ec2-user/mysql.sh
echo '  interact"' >> /home/ec2-user/mysql.sh
chmod 777 /home/ec2-user/mysql.sh

ここでは、シェルスクリプトを作成しています。

シェルスクリプトで、入力を自動化するのには、expectが必要だったのでインストール。

expectの自動化については詳しく解説はしません。

もっと良い方法がありそうですが、echomysql.shに出力してます。

sudo mysql_secure_installationMySQLの初期化コマンドです。

sudo cat / var / log / mysqld.log | grep 'temporary password' | awk '{print $NF}'がROOTの初期パスワードがある場所です。

気をつけないといけないポイントしては、mysql.shの作成場所を絶対パスで指定しないと。

トップディレクトリで作成されます。

あとは、シェルスクリプトに実行権限を付与します。

MySQLログイン

echo " mysql -uroot -p@a@1@2@3@4@55azA@" > /home/ec2-user/mylogin.sh
chmod 777 /home/ec2-user/mylogin.sh

これは単純で、MySQLコマンドを指定しているだけです。

ちゃんと実行権限を付与するだけです。

EC2作成後

cdk deployしてEC2が作成されたことが確認できたら次のステップに移ります。

EIPが付与されているので、マネージドコンソールでターミナルで接続します。

ec2-userのホームディレクトリに作成したシェルスクリプトがあるので順番に実行します。

  1. mysql.sh実行
  2. rootパスワードを”@a@1@2@3@4@55azA@”に設定

あとは、全部Yesでいいと思います。

そのあとは、mysqllogin.shを実行してMySQLへアクセスができます。

コード化は便利だと思う今日このごろ。