Tocyukiのブログ

ギターと柔術とプログラミングが好き!

ALB+EC2+RDS+EFS構成でWordpress環境を作ったらCSSが崩れてハマった

というわけで、何度現場を移ってもWordpressから逃げられないんですよこれが。

久しぶりに1から構築するということでEFSの速度改善もしたし、使ってみるかぁという感じでやってみました。

aws.amazon.com

しかし構築したもののCSSが適用されず微妙にハマり以下のQiita記事を見て膝からがっくり落ちましたよ。。。

qiita.com

とりあえずfastcgi_paramHTTPS onを渡して対応しておしまい。 あとはRedisとS3を準備しておけばOKかな〜。

TerraformでDynamoDBのロックがおかしくなってplanできなくなった時の対応

その時は急にやってきた

terraform plan実行して問題ないことを確認して、数秒後に再実行したらこれですよ。。。

$ terraform plan
Creating terraform-aws_terraform_run ... done
Acquiring state lock. This may take a few moments...
╷
│ Error: Error acquiring the state lock
│ 
│ Error message: ConditionalCheckFailedException: The conditional request failed
│ Lock Info:
│   ID:        0bab5536-fbfb-8878-012a-1696f30d9c96
│   Path:      dev-tfstate-XXXXXXXXXXXX/dev.tfstate
│   Operation: OperationTypeApply
│   Who:       root@XXXXXXXXXXXX
│   Version:   1.0.0
│   Created:   2021-10-26 04:58:02.9271349 +0000 UTC
│   Info:      
│ 
│ 
│ Terraform acquires a state lock to protect the state from being written
│ by multiple users at the same time. Please resolve the issue above and try
│ again. For most commands, you can disable locking with the "-lock=false"
│ flag, but this is not recommended.
╵

ロックの強制解除をしてみる

はいはい、強制解除強制解除ぐらいのノリで、ツイートしたりしちゃうぐらい呑気な感じでした。

$ terraform force-unlock 0bab5536-fbfb-8878-012a-1696f30d9c96
Creating terraform-aws_terraform_run ... done
Do you really want to force-unlock?
  Terraform will remove the lock on the remote state.
  This will allow local Terraform commands to modify this state, even though it
  may be still be in use. Only 'yes' will be accepted to confirm.

  Enter a value: yes

Terraform state has been successfully unlocked!

The state has been unlocked, and Terraform commands should now be able to
obtain a new lock on the remote state.

改善せず

はい、治ったーと思ったら、以下のエラーでplanもapplyもできなくなってしまった。

╷
│ Error: Error loading state: state data in S3 does not have the expected content.
│ 
│ This may be caused by unusually long delays in S3 processing a previous state
│ update.  Please wait for a minute or two and try again. If this problem
│ persists, and neither S3 nor DynamoDB are experiencing an outage, you may need
│ to manually verify the remote state and update the Digest value stored in the
│ DynamoDB table to the following value: 755b517c310c11f04b3dfef86988ffce
│ 
│ 
│ 
╵

DynamoDBテーブルの確認

上記のエラーで出ているDigest値と異なっていることが確認できた。

  • 755b517c310c11f04b3dfef86988ffce
  • 48f5307177582df2355d9b55f7a5105b
$ aws dynamodb scan --table-name dev-tfstate-lock --profile dev
{
    "Items": [
        {
            "Digest": {
                "S": "48f5307177582df2355d9b55f7a5105b"
            },
            "LockID": {
                "S": "dev-tfstate-XXXXXXXXXXXX/dev.tfstate-md5"
            }
        }
    ],
    "Count": 1,
    "ScannedCount": 1,
    "ConsumedCapacity": null
}

update-itemでDigestを更新

aws cliで直接DynamoDBのDigestを更新してみる

$ aws dynamodb update-item --table-name dev-tfstate-lock --key '{"LockID": {"S": "dev-tfstate-xxxxxxxxxxxx/dev.tfstate-md5"}}' --attribute-updates '{"Digest": {"Value": {"S": "755b517c310c11f04b3dfef86988ffce"},"Action": "PUT"}}' --return-values UPDATED_NEW --profile dev | jq '.Attributes.RuleSetVersion.S'

再度確認

お、ちゃんと変わってる

$ aws dynamodb scan --table-name dev-tfstate-lock --profile dev
{
    "Items": [
        {
            "Digest": {
                "S": "755b517c310c11f04b3dfef86988ffce"
            },
            "LockID": {
                "S": "dev-tfstate/dev.tfstate-md5"
            }
        }
    ],
    "Count": 1,
    "ScannedCount": 1,
    "ConsumedCapacity": null
}

再度、コマンド実行してみたところ、planapplyも問題なく実行できるようになりました!

参考

pygillier.me

MySQL5.7でibtmp1が枯渇した際の対応

ibtmp1が枯渇してCPUのアラートが上がってその対応をしたのでメモ

ディスク状況の確認

/mnt/extdiskが100%になっちゃってるよ

[root@db:~]# df -h
Filesystem                      Size  Used Avail Use% Mounted on
devtmpfs                        985M     0  985M   0% /dev
tmpfs                          1000M     0 1000M   0% /dev/shm
tmpfs                          1000M  105M  895M  11% /run
tmpfs                          1000M     0 1000M   0% /sys/fs/cgroup
/dev/vda3                        16G   12G  3.7G  76% /
/dev/mapper/vg_extdisk-lv_data   99G   94G     0 100% /mnt/extdisk
tmpfs                           200M     0  200M   0% /run/user/0
tmpfs                           200M     0  200M   0% /run/user/1000

innodb_temp_data_file_pathの設定を確認

デフォルトのままっぽい

mysql> SELECT @@innodb_temp_data_file_path;
+------------------------------+
| @@innodb_temp_data_file_path |
+------------------------------+
| ibtmp1:12M:autoextend        |
+------------------------------+
1 row in set (0.00 sec)

innodb_temp_data_file_pathの設定変更を実施

とりあえず10Gを上限とするように/etc/my.cnfに記述を追記

[mysqld]
innodb_temp_data_file_path=ibtmp1:12M:autoextend:max:10G

設定が反映されたか確認

サーバー再起動しないと設定反映&ibtmp1の領域が開放されないので再起動を実施

/mnt/extdiskが5%にちゃんと減っちゃってるよ!

[root@db:~]# df -h
Filesystem                      Size  Used Avail Use% Mounted on
devtmpfs                        985M     0  985M   0% /dev
tmpfs                          1000M     0 1000M   0% /dev/shm
tmpfs                          1000M  8.7M  991M   1% /run
tmpfs                          1000M     0 1000M   0% /sys/fs/cgroup
/dev/vda3                        16G   12G  3.7G  76% /
/dev/mapper/vg_extdisk-lv_data   99G  4.3G   90G   5% /mnt/extdisk
tmpfs                           200M     0  200M   0% /run/user/0
tmpfs                           200M     0  200M   0% /run/user/1000

ibtmp1の設定も無事反映されてるよ!

mysql> SELECT @@innodb_temp_data_file_path;
+-------------------------------+
| @@innodb_temp_data_file_path  |
+-------------------------------+
| ibtmp1:12M:autoextend:max:10G |
+-------------------------------+

参考情報

docs.oracle.com

AWS DMSでDB移行をした際に移行されない属性を移行するためのSQL文

今、お仕事でとあるIaaSからAWSへのインフラ移行をしていて、DMS(Database Migration Service)を使っててめちゃ便利で最高なんですけど、これインデックスやらプライマリーキーに設定されているAUTO_INCREMENT属性やらもろもろ移行してくれないものがあります。

docs.aws.amazon.com

ただし、 AWS DMS はターゲットデータベース内にセカンダリインデックス、外部キー、ユーザーアカウントなどを自動的に作成しません。

docs.aws.amazon.com

列の AUTO_INCREMENT 属性は、ターゲットデータベース列に移行されません。

というわけでもろもろの属性を移行するためのSQLを書いたので覚書のため記載しておきます。
{SCHEMA_NAME}は対象のDBスキーマに読み替えてください。

Index移行用SQL

SELECT
  CONCAT(
    "ALTER TABLE ",
        t1.table_name,
        " ADD INDEX ",
    t1.index_name, 
    "(",
    (
      SELECT
        GROUP_CONCAT(DISTINCT t2.column_name SEPARATOR ', ')
      FROM
        information_schema.statistics AS t2
      WHERE
        t1.index_name = t2.index_name AND t1.table_name = t2.table_name
      ORDER BY
        t2.table_name,
        t2.index_name,
        t2.seq_in_index
    ),
    ");"
  ) AS alter_table_add_index_query
FROM
  information_schema.statistics AS t1
WHERE
  table_schema = "{SCHEMA_NAME}" AND index_name != "PRIMARY"
GROUP BY
  t1.table_name,
  t1.index_name
;

プライマリーキーのAUTO_INCREMENT属性移行用SQL

SELECT
 CONCAT(
   "ALTER TABLE ",
   TABLE_NAME,
   " CHANGE ",
   COLUMN_NAME,
   " ",
   COLUMN_NAME,
   " ",
   COLUMN_TYPE,
   " AUTO_INCREMENT;"
 ) as alter_auto_increment
FROM
 information_schema.columns
WHERE
 table_schema = "{SCHEMA_NAME}"
and is_nullable = "NO"
and column_key = "PRI"
and extra = "auto_increment"
;

おわりに

あとはそれぞれ生成したALTER文を移行先のDBで流せばOKです! 動作責任は負いかねますが、どなたかの助けになれば嬉しいです!

おまけ

外部キーを貼っているテーブルに関する調査もしたのでその際に確認したコマンドも記載しておきます。

外部キーを貼っているテーブルの調査

select * from information_schema.table_constraints where table_schema = "{SCHEMA_NAME}" and constraint_type = "FOREIGN KEY";

特定のテーブルへの外部キーを貼っているテーブルの調査

select distinct(referenced_table_name) from information_schema.key_column_usage where constraint_schema = "{SCHEMA_NAME}";

bashの変数展開で最後の文字を取り出す方法

Bashの変数展開で最後の文字だけ取得する際の仕様がちょっと分かりづらかったのでメモ

やりたいこと

以下のような変数と値があった場合に最後の文字であるdだけを変数展開で取り出したい!

text="Hello World"

やりかた

以下のように変数展開の:のうしろにスペースをいれてやる必要があった

echo ${text: -1}
d

スペースなしだと以下のようになる

echo ${text:-1}
Hello World

参考

genzouw.com

2020年の振り返りと2021年の目標

コロナに主役を完全に奪われた2020年でしたが、思い返してみるとそこそこ色々あったな〜と感じますなぁ

トピックとしては

  • 長女が小学生になる
  • 在宅勤務による生活スタイルの変化
  • 仕事でいくつかの大きめのPJTを独力で完走
  • AWS SysOps取得
  • 転職
  • 柔術再開

という感じかな

2020年の振り返り

とりあえず去年の振り返りと目標で照らし合わせてみると全然達成できてなくて笑えてくる感じだなぁw blog.tocyuki.com

勉強

目標 実績 達成率
TOEIC700点以上 470点 60%
AWS資格5冠達成
(残りSysOps/DVA/SAP/DOPの4つを取得)
SysOpsのみ取得 30%
今積まれている技術書やUdemyを消化する
※主にPython系を
すこーしだけ消化できた 30%

去年に1ヶ月セブ留学したけどそこで得られる英語力はたかが知れてるもので、帰国後にノー勉強で受けたTOEICの結果がそれを表している

資格も結局SysOpsの一つのみのしか取得できずもとりあえず一つは取得したということで自分を褒めてあげよう

積読になっていた技術書やUdemyも少しだけ消化できたのでそれもやっただけよしということで

仕事

目標 実績 達成率
監視基盤の再構築 Datadogを導入 100%
CI/CDパイプライン構築&運用にのせる 一部運用開始するまでできた 20%
GitHub、Slackの導入 Slackのみ導入(GitHub導入自体がなくなった) 30%
定期的な勉強会の実施 まったくなにもせず 0%

仕事では監視基盤にDatadogを提案&導入し、すごくスムーズにいき開発者の運用参加のきっかけと伴う品質の向上に大きく貢献できたかなと

あとは完全にブラックボックスとなっていたシステムのリプレースも一人で担当し、短納期&トラブルなしで完了することができた

やったこととしては以下

  • Ansible化&Terraform化
  • PHP5系&MySQL5.5のバージョンアップ
  • AmazonLinux1からAmazonLinux2へのバージョンアップ
  • ルートアカウントから別サービスアカウントへの移行

GitHubの導入は当初PJ化して進める予定だったけど色々あってPJ自体が頓挫し、Slackに関してはチーム内利用&通知に留まってしまった

勉強会の開催も色々思うところもありまったくやらず個人的に外部の勉強会に参加するに留まってしまった

とりあえずはそんなこんなもあり12月に転職して心機一転SREチームの立ち上げからインフラのグランドデザインから担当できるのでとても楽しみである!

健康

目標 実績 達成率
6月までの間最低週2回は追い込む コロナのため2月からまったくジムに行けずも年末から柔術開始 20%
体脂肪率15%を切る まったく目標におよばずも柔術を始め光が見え始める 10%
月から柔術再開し最低週2回稽古を行う コロナのため12月ぐらいから開始 50%

ゴールドジムを半年契約したものの結局コロナで12月と1月の2ヶ月しか通えず、筋力の向上もかなり中途半端なもので終わってしまったが、ジムに行ったのは初めてだったので器具を使ったトレーニングがどういうものなのか等がわかりそこはひとつの収穫だったのかなと思える

また12月から柔術も再開し、約1年半ぶりということでびっくりするぐらい動けず、紫帯をつけているのが恥ずかしい感じだけどこちらは引き続き継続していこう

その他

目標 実績 達成率
ブログを週に一度は書く 22記事 40%

アウトプットのルーティン化も必要だなとも思いつつ、アウトプット駆動で物事にとりかかるのも必要なのかなとも思ったので、質より量でやっていこうと思いました

総括

とりあえず、全然達成はできずとも足掻くように前進することはできているのかなという一点のみで自分を褒めよう

  • Datadogの提案・検証・導入まですべて一人で素早くできた
  • 結構大きめのプロジェクトを一人でトラブルなく実施できた
  • TOEIC受けた
  • SysOps取得した
  • Udemyや技術書を少しだけど消化できた
  • 柔術再開した
  • 転職した

12月から転職もして、より大きな裁量でSREとして働くことができているし、完全在宅になったことで家族との時間も確保できて、無駄な飲み会(自分は飲むのが好きなので出勤すると高確率で飲みに行ってしまう)も減らせて伴って出費も減り、柔術もコンスタントに行けて、とてもポジティブな要素はたくさんつくることができたという2020年ではあったので2021年も良い部分はそのままに頑張りたい

課題としてはルーティン化と継続が弱かったのでそこも強化していきたい

2021年の目標

今年も勉強、仕事、健康を軸に目標を立てて達成していきたい

勉強

TOEIC600点

  • 毎日iKnow!とスタディサプリをやる
  • TOEIC2回受験する

iknow.jp

app.eigosapuri.jp

AWS資格6冠達成

  • 2月にSAP取得
  • 4月にDVA取得
  • 7月にDOP取得
  • 8月にCloudPractitoner取得

という感じで取得できて行ったら良いなという感じで!

その他

  • 毎週Atcoder参戦
  • 今積まれている技術書やUdemyを消化する(主にPython系を)
  • 学んだことは必ずブログにアウトプットする

atcoder.jp

仕事

  • SREチーム立ち上げ
  • 新規インフラのグランドデザイン

健康

体脂肪率15%を切る

  • 柔術稽古を最低週2回死守
  • 暴飲暴食をなくす
  • お酒を控える

おわりに

とりあえず振り返りと目標の確認をしてみて、こりゃやばいなという危機感が持てたので粛々と頑張ろうと思ったのでした
そして一時期やっていた振り返りのアウトプットもするようにしよう

ヒアドキュメントでインデントを含めた文字列を使う方法

ヒアドキュメントでインデントを含めたものを使いたいときには<<だけではだめで- <<とすると行頭のタブを無視してくれるので、この書き方だと以下のような用途の際にスクリプトできれいに書けるので便利

# configuration of td-agent
cat - << 'EOM' > /etc/td-agent/td-agent.conf
@include conf.d/*.conf

<match fluent.**>
  @type file
  path /var/log/td-agent/fluent.log
</match>
EOM

参考

qiita.com

qiita.com

【AWS】 instance profileを削除する方法

instance profileはCLIからしか削除できないっぽかったのでメモ

状況

Terraformでapply処理が途中でコケてしまいその影響なのか以下のエラーが表示され先に進めなくなってしまった

Error: Error creating IAM instance profile example-app-iam-instance-profile: EntityAlreadyExists: Instance Profile example-app-iam-instance-profile already exists.
        status code: 409, request id: 7e7d16b7-4ca2-4737-8210-b42c0a8620bb

削除方法

管理コンソールから削除しようとしたけど、どこからも削除ができなさそうだったが、CLIで削除ができそうだったので以下コマンドで無事削除できた

aws iam delete-instance-profile --instance-profile-name example-app-iam-instance-profile

参考情報

awscli.amazonaws.com

【Terraform】 skip_final_snapshot を設定しないでRDSを作成したらterraform destroyできなくなった

というわけで、これちょいちょいやってしまうんですが、Terraformでskip_final_snapshot = trueを設定しないでRDSリソースを作成して、その後削除しようとすると以下のエラーが出るようになってしまったんですよ

Error: RDS Cluster FinalSnapshotIdentifier is required when a final snapshot is required

というわけで対応手順をメモして行こうと思います

再現方法

以下のような感じでRDSのリソースを作成する

resource "aws_rds_cluster" "db" {
  cluster_identifier      = "${var.name}-${var.env}-db"
  engine                  = local.engine
  engine_version          = local.engine_version
  engine_mode             = local.engine_mode
  availability_zones      = values(var.azs)
  master_username         = aws_ssm_parameter.db_username.value
  master_password         = aws_ssm_parameter.db_password.value
  backup_retention_period = var.backup_retention_period
  preferred_backup_window = local.preferred_backup_window

  tags = merge(var.common_tags, {
    Name = "${var.name}-${var.env}-db"
    Role = "RDS"
  })
}

で、applyはうまくいくのでその後、destroyを実行すると・・・

Error: RDS Cluster FinalSnapshotIdentifier is required when a final snapshot is required

というエラーが出てしまい、Terraformでのこのリソースの削除ができなくなってしまいました

修正方法

stackoverflowの回答を参考に以下を実施したところ解決した

  • backup_retention_periodの値を0にする
  • preferred_backup_windowのパラメータを削除する
  • skip_final_snapshot = trueapply_immediately = trueを追加する

以下が修正後のコード

resource "aws_rds_cluster" "db" {
  cluster_identifier      = "${var.name}-${var.env}-db"
  engine                  = local.engine
  engine_version          = local.engine_version
  engine_mode             = local.engine_mode
  availability_zones      = values(var.azs)
  master_username         = aws_ssm_parameter.db_username.value
  master_password         = aws_ssm_parameter.db_password.value
  backup_retention_period = 0
  skip_final_snapshot     = true
  apply_immediately       = true

  tags = merge(var.common_tags, {
    Name = "${var.name}-${var.env}-db"
    Role = "RDS"
  })
}

そしてapplyを実施後、destroyで正常にリソースが削除されるようになりました〜!

参考情報

stackoverflow.com

【Terraform】 countからfor_eachへ書き換えたらスプラット演算子の動きが変わった

いままでcountで記述していたものをfor_eachに直してみたところスプラット演算子の動きが変わったのでメモ

状況

いままではVPCのサブネットリソースをcountで複数作ってそれをoutputで他のモジュールに渡して利用しておりました

resource "aws_subnet" "private_data" {
  count                   = length(var.azs)
  vpc_id                  = aws_vpc.vpc.id
  cidr_block              = cidrsubnet(aws_vpc.vpc.cidr_block, 8, 11 + count.index)
  availability_zone       = element(var.azs, count.index)
  map_public_ip_on_launch = false
}

output "data_private_subnets" {
  value = aws_subnet.private_data
}

他のモジュールで使うときはこんな感じで使ってた

resource "aws_db_subnet_group" "db" {
  name        = "${var.name}-${terraform.workspace}-db-subnet"
  description = "Database Subnet Group for ${var.name}-${terraform.workspace}"
  subnet_ids  = var.data_private_subnets[*].id # この部分
}

そんでもって、for_eachを使って書き直したのがこちら

resource "aws_subnet" "private_db" {
  for_each          = var.azs
  cidr_block        = cidrsubnet(aws_vpc.vpc.cidr_block, 8, index(values(var.azs), each.value) + 11)
  availability_zone = each.value
  vpc_id            = aws_vpc.vpc.id
  map_public_ip_on_launch = false
}

すると以下のようなエラーが出るようになった

Error: Unsupported attribute

  on modules/aws/database/subnet_group.tf line 4, in resource "aws_db_subnet_group" "db":
   4:   subnet_ids  = var.data_private_subnets[*].id

This object does not have an attribute named "id".

Issue

とりあえずIssueを漁ってみたら以下が見つかった

github.com

github.com

Issueを読んでみると以下のように修正すれば大丈夫っぽいことがわかった

The short answer is that if you were to modify your code to values(aws_route53_record.record)[*].fqdn it will work as you're expecting it to.

修正

Issueに書いてあるとおり、aws_db_subnet_groupのリソース作成部分を以下のように修正したら問題なく動くようになった

resource "aws_db_subnet_group" "db" {
  name        = "${var.name}-${terraform.workspace}-db-subnet"
  description = "Database Subnet Group for ${var.name}-${terraform.workspace}"
  subnet_ids  = values(var.private_subnets_db)[*].id # この部分
}

おわりに

for_each便利だけど思わぬ落とし穴?にハマってしまいました

Intellij IDEA の ideavim で h,j,k,l で連続移動できない場合の修正方法

自宅のMacでIntellij IDEAにideavimのプラグインを入れて使っているんですが、なぜか、h,j,k,lのキーバインドで移動ができず困っていたらこちらにソリューションが記載されていて、試してみたら解消できたのでメモ

t.co

実行したコマンド

defaults write -g ApplePressAndHoldEnabled -bool false

Bashの変数で大文字、小文字の変換をsedを使わないでやる方法

mattnさんの以下ツイートが流れてきてめちゃ便利じゃんと感動したのでメモ

まとめ

最初の文字だけ大文字にする

$ os=linux; echo ${os^}
Linux

全部大文字にする

$ os=linux; echo ${os^^}
LINUX

最初の文字だけ小文字にする

$ os=LinuX; echo ${os,}
linuX

最初と最後の文字だけ小文字にする

$ os=LinuX; echo ${os,,}
linux

大文字小文字を入れ替える

$ os=LiNuX; echo ${os~~}
lInUx

指定文字置換

$ os=Linux; echo ${os//inu/umi}
Lumix

おわりに

これらの記法はbash v4以降で使えるものなので、MacとかのBashだと動きません\(^o^)/
Bash Tipsすきだわ〜\(^o^)/

php-fpm + apache環境での環境変数の持たせ方

php-fpm環境下でApache httpdのSetEnvで設定された環境変数は、PHPのenv()等では取得できるが、
execで実行されるコマンドには、SetEnvで設定された環境変数が反映されなかったので(php-fpmの仕様?)実施した回避策を書く!

要約

  • ApacheのSetEnvは使わず/etc/environmentに環境変数を記載して利用する

/etc/environmentの環境変数利用手順

/etc/systemd/system/httpd.serviceを作成

  • 以下内容で作成する
.include /lib/systemd/system/httpd.service

[Unit]
After=network.target remote-fs.target nss-lookup.target httpd-init.service cloud-config.service

[Service]
UMask=002
EnvironmentFile=/etc/environment

/etc/systemd/system/php-fpm.serviceを作成

  • 以下内容で作成する
.include /lib/systemd/system/php-fpm.service

[Unit]
After=syslog.target network.target cloud-config.service

[Service]
UMask=002
EnvironmentFile=/etc/environment
PrivateTmp=false

/etc/php-fpm.d/www.confに1行追加

  • 以下を追記
clear_env = no

あとは/etc/environmentに環境変数を記載していくだけ!