SSM SessionManagerのログをS3 bucket/CloudWatchLogに保存する
SSM SessionManagerでのコンソールの操作ログをS3やCloudWatchLogsに保存できるということなので試してみた。Terraformで設定。
1. IAMrole / Instance Profileを作成
ec2インスタンスにインストールされているSSMエージェントがログを書き込むので、インスタンスに権限を付与してあげる必要がある。こちらのドキュメントを参考に設定。今回は AmazonSSMManagedInstanceCore
に権限を追加してみた。Terraformのコードはこんな感じ。
data "aws_iam_policy" "amazon_ssm_managed_instance_core" { arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" } data "aws_iam_policy_document" "ec2_ssm_test_policy_doc" { source_json = data.aws_iam_policy.amazon_ssm_managed_instance_core.policy statement { effect = "Allow" resources = ["*"] actions = [ "s3:PutObject", "s3:GetEncryptionConfiguration", "logs:PutLogEvents", "logs:CreateLogStream", "logs:DescribeLogGroups", "logs:DescribeLogStreams", "ssm:GetParameter", "ssm:GetParameters", "ssm:GetParametersByPath", "kms:Decrypt", "kms:GenerateDataKey", ] } } resource "aws_iam_policy" "ec2_ssm_test_policy" { name = "ec2-ssm-test-policy" policy = data.aws_iam_policy_document.ec2_ssm_test_policy_doc.json } resource "aws_iam_role" "ec2_ssm_test_role" { name = "ec2-ssm-test-role" assume_role_policy = <<EOF { "Version": "2012-10-17", "Statement": [ { "Action": "sts:AssumeRole", "Principal": { "Service": "ec2.amazonaws.com" }, "Effect": "Allow", "Sid": "" } ] } EOF tags = { Name = "ec2-ssm-test-role" } } resource "aws_iam_role_policy_attachment" "ssm_role_attachment" { role = aws_iam_role.ec2_ssm_test_role.name policy_arn = aws_iam_policy.ec2_ssm_test_policy.arn } resource "aws_iam_instance_profile" "ec2_ssm_test_profile" { name = "ec2-ssm-test-profile" role = aws_iam_role.ec2_ssm_test_role.name }
2. 作成したinstance profileをアタッチしたec2インスタンスを作成
amazon linux2を利用*1。Terraformのコードはこんな感じ。VPCとかSubnet、SecurityGroupは適宜設定。
data "aws_ssm_parameter" "amzn2_ami" { name = "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2" } resource "aws_instance" "ssm_test_server" { ami = data.aws_ssm_parameter.amzn2_ami.value instance_type = "t2.micro" subnet_id = aws_subnet.ec2_ssm_test_private_subnet.id iam_instance_profile = aws_iam_instance_profile.ec2_ssm_test_profile.name security_groups = [ aws_security_group.allow_http.id, ] tags = { Name = "ssm-test-server" } user_data = <<EOF #!/bin/bash yum update -y amazon-linux-extras install docker usermod -aG docker ec2-user systemctl enable docker systemctl start docker EOF }
3. SSM SessionManager設定用Documentの作成
SSM SessionManagerの設定はSSM Documentで作成するようなので、terraformで作成。今回はテストなので暗号化はしない設定。ログ保存用のS3 bucketとCloudWatchLogsのLogGroupも一緒に作成。因みにDocumentの名前は "SSM-SessionManagerRunShell"にしておくとよい。session mamager使う時にデフォルトで読み込んでくれる。勿論名前変えて、CLIの引数で渡して指定することも可能*2。
resource "aws_s3_bucket" "ec2_ssm_test_log_bucket" { bucket = "ec2-ssm-test-log-bucket-xxx" force_destroy = true lifecycle_rule { enabled = true expiration { days = 3 } } } resource "aws_cloudwatch_log_group" "ec2_ssm_test_log" { name = "/ec2-ssm-test-log" retention_in_days = 3 } resource "aws_ssm_document" "session_manager_run_shell" { name = "SSM-SessionManagerRunShell" document_type = "Session" document_format = "JSON" content = <<EOF { "schemaVersion": "1.0", "description": "Document to hold regional settings for Session Manager", "sessionType": "Standard_Stream", "inputs": { "s3BucketName": "${aws_s3_bucket.ec2_ssm_test_log_bucket.id}", "s3EncryptionEnabled": false, "cloudWatchLogGroupName": "${aws_cloudwatch_log_group.ec2_ssm_test_log.name}", "cloudWatchEncryptionEnabled": false } } EOF }
いざapplyと思って実行するとエラー。SSM-SessionManagerRunShell
が存在するとのこと。どうもSSMを使ったことがあると自動で作成されている模様。消す*3かimportすればよさそう。今回はimportしちゃった。
$ terraform import --target aws_ssm_document.session_manager_run_shell SSH-SessionManagerRunShell aws_ssm_document.session_manager_run_shell: Importing from ID "SSM-SessionManagerRunShell"... aws_ssm_document.session_manager_run_shell: Import prepared! Prepared aws_ssm_document for import aws_ssm_document.session_manager_run_shell: Refreshing state... [id=SSM-SessionManagerRunShell] Import successful! The resources that were imported are shown above. These resources are now in your Terraform state and will henceforth be managed by Terraform.
無事importできた。その後applyすると無事適用できました。
$ terraform apply ...
4. 確認
- ログはSessionを終了すると保存される模様
- CloudWatch、S3ともに保存できてました。CloudWatchLogsだとこんな感じ。文字化けしてるけど、コンソールで実行したコマンド、その結果ちゃんと保存できてる。
Script started on 2020-10-18 13:32:11+0000 [?1034hsh-4.2$ [Ksh-4.2$ bash ]0;@ip-10-0-1-xxx:/usr/bin[?1034h[ssm-user@ip-10-0-1-xxx bin]$ sudo su - ec2-use ]0;ec2-user@ip-10-0-1-xxx:~[ec2-user@ip-10-0-1-xxx ~]$ uname -a Linux ip-10-0-1-xxx.ap-northeast-1.compute.internal 4.14.193-149.317.amzn2.x86_64 #1 SMP Thu Sep 3 19:04:44 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux ]0;ec2-user@ip-10-0-1-xxx:~[ec2-user@ip-10-0-1-xxx ~]$ hostname ip-10-0-1-xxx.ap-northeast-1.compute.internal ]0;ec2-user@ip-10-0-1-xxx:~[ec2-user@ip-10-0-1-xxx ~]$ uptime 13:26:27 up 5 min, 0 users, load average: 0.02, 0.12, 0.08 ]0;ec2-user@ip-10-0-1-xxx:~[ec2-user@ip-10-0-1-xxx ~]$ whoami ec2-user ]0;ec2-user@ip-10-0-1-xxx:~[ec2-user@ip-10-0-1-xxx ~]$ exit logout ]0;@ip-10-0-1-xxx:/usr/bin[ssm-user@ip-10-0-1-xxx bin]$ exit exit sh-4.2$ exit exit Script done on 2020-10-18 13:32:11+0000
CodePipelineでCodeCommitとCodeBuildを利用してはまる
CodePipeline、CodeCommit、CodeBuildで遊んでみたのですが、CodePipeline利用するときにハマったのでメモ。
前提
- 最初CodePipelineを利用せずに、CodeCommitとCodeBuildでBuildできるか等々試していた
- CodeBuildで利用してた
buildspec.yml
はこんな感じ- やっていることはdocker buildしてECRに突っ込んでいるだけ
- イメージのタグとして、commit idを利用している
- CodePipelineを使わない状況では上手く動いていた
version: 0.2 phases: pre_build: commands: - echo "Login to Amazon ECR" - aws ecr get-login-password --region ${AWS_REGION} | docker login --username AWS --password-stdin ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com - IMAGE_TAG=$(git rev-parse --short HEAD) - echo "IMAGE_TAG=${IMAGE_TAG}" build: commands: - echo "Build started in $(date)" - echo "Building a docker image..." - docker build -t ${IMAGE_REPO_NAME}:${IMAGE_TAG} . - docker tag ${IMAGE_REPO_NAME}:${IMAGE_TAG} ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${IMAGE_REPO_NAME}:${IMAGE_TAG} - docker tag ${IMAGE_REPO_NAME}:${IMAGE_TAG} ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${IMAGE_REPO_NAME}:latest post_build: commands: - echo "Build completed in $(date)" - echo "Pushing the docker image..." - docker push ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${IMAGE_REPO_NAME}:${IMAGE_TAG} - docker push ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${IMAGE_REPO_NAME}:latest
問題
CodePipelineを利用して、Pipelineを作成
- Source Stage --> CodeCommit
- Build Stage --> CodeBuild
CodeBuildでエラー
- どうやらgitリポジトリじゃないらしい
[Container] Running command aws ecr get-login-password --region ${AWS_REGION} | docker login --username AWS --password-stdin ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com WARNING! Your password will be stored unencrypted in /root/.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store Login Succeeded [Container] Running command IMAGE_TAG=$(git rev-parse --short HEAD) fatal: not a git repository (or any parent up to mount point /codebuild) Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).
結果
- いろいろ調べた結果、どうも source stageのartifactはgitリポジトリでなくなるらしい
- .gitがなかった
- じゃあcommit idどうやって取るの?と思って調べてみたら
CODEBUILD_RESOLVED_SOURCE_VERSION
が求めているものっぽいので、そちらを利用するように変更
version: 0.2 phases: pre_build: commands: - echo "Login to Amazon ECR" - aws ecr get-login-password --region ${AWS_REGION} | docker login --username AWS --password-stdin ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com - COMMIT_HASH=$(echo ${CODEBUILD_RESOLVED_SOURCE_VERSION} | cut -c 1-7) - IMAGE_TAG=${COMMIT_HASH} build: commands: - echo "Build started in $(date)" - echo "Building a docker image..." - docker build -t ${IMAGE_REPO_NAME}:${IMAGE_TAG} . - docker tag ${IMAGE_REPO_NAME}:${IMAGE_TAG} ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${IMAGE_REPO_NAME}:${IMAGE_TAG} - docker tag ${IMAGE_REPO_NAME}:${IMAGE_TAG} ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${IMAGE_REPO_NAME}:latest post_build: commands: - echo "Build completed in $(date)" - echo "Pushing the docker image..." - docker push ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${IMAGE_REPO_NAME}:${IMAGE_TAG} - docker push ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${IMAGE_REPO_NAME}:latest
エラー出ずに動きましたとさ。
AWS managed policyを作成したIAMroleに紐づける
自分で作成したIAMpoliciesであれば、datasource利用してPolicy document作成し、aws_iam_role_policy_attachmentで紐づければ良いけど、AWS managedの場合どうするのがよいか調べたのでメモ。
方法1 - 直接ARNを書く
例えば AmazonSSMManagedInstanceCore (arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore)
ポリシをIAMrole (my-test-role)に付与したい場合は下記な感じ。
resource "aws_iam_role" "my_test_role" { name = "my-test-role" .... } resource "aws_iam_role_policy_attachment" "my_test_role_pol_attachment" { role = aws_iam_role.my_test_role.name policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" }
方法2 - data source を利用する
方法1同様、 AmazonSSMManagedInstanceCore (arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore)
ポリシをIAMroleに付与したい場合は下記のようになる。
resource "aws_iam_role" "my_test_role" { name = "my-test-role" .... } data "aws_iam_policy" "AmazonSSMManagedInstanceCore" { arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" } resource "aws_iam_role_policy_attachment" "my_test_role_pol_attachment" { role = aws_iam_role.my_test_role.name policy_arn = data.aws_iam_policy.AmazonSSMManagedInstanceCore.arn }
方法2の方がTerraform的な書き方ですかね。
参考
Jiraの設定周りを整理
Jiraの設定をたまにするのだけど、ドキュメントさらっと読みつつ何となく設定して誤魔化してて、理解してやってないと良くないよねと思いまして、ドキュメントを読んでみました。絶対忘れるのでメモしておく。
今回下記内容をざっと理解。
- issue type
- issue type scheme
- workflow
- workflow scheme
- screen
- screen scheme
- issue type screen scheme
- field configuration
- field configuration scheme
issue type
- Jiraは基本issueをチケット化して管理するんだけど、そのissueの種類
- 例えば... Epic、Story、Task、Subtask、Bugとか
- 階層化することが可能(デフォルトでは3階層)
- Parent/Epic issues
- (Standard) issues
- Child issues (subtask)
issue type scheme
- issueのセットみたいなもの
- プロジェクトに割り当てて使う
- 当該プロジェクトはissue type schemeに紐づけられているissue typeのみ使える
- 用途:テンプレートとなるような共通のissueセットを作成しておいて、関連するプロジェクトでは同じものを使うとか?
workflow
- issueが処理されていく流れ = 業務フローという感じ
- 例:ToDo --> In progress --> Review --> Done
- StatusとTransitionを定義
- Status = issueの状態(上の例だとToDoとかIn progressとか)
- Transition = あるStatusから別のStatusに移動できるようにするリンク
- Status間の移動を定義できる
- 例えば、Review StatusのチケットのみDoneに移動できるとか
- GUI使って設定できる
- Transitionに関連して色々できる
- Triggers: リンクされてる外部ツールのイベントをトリガにしてStatusを変更したりすることが可能
- Conditions: issueを移動できるユーザに条件つける
- Validators: issue移動時に入力された内容が有効かチェック
- post-functions: issue移動後に追加の処理を実施(Fieldのアップデートとか)
workflow scheme
- workflowとissue typeを紐づける = 特定のissue typeのworkflowを設定する
- issue type毎にworkflowを設定することが可能
- workflow schemeをプロジェクトに割り当てる
- issue typeでプロジェクトで利用するissueの種類を決める
- workflow schemeでissue type毎のworkflowを決める
screen
- (Issueの操作で表示する)画面を定義*1
- こんな画面と定義する
- fieldの集合
screen sheme
- 画面の定義とissueの操作(issueの作成、編集、表示)と画面を紐づけ
- issueのこの操作ではこの画面を表示すると定義
- issueの操作毎に画面を変えることが可能
issue type screen scheme
- screen shemeとissue typeを紐づける
- このissue typeでは、このscreen schmeを利用する(この操作でこの画面を表示する)と定義
- issue type screen schemeをプロジェクトに割り当てる
field configuration
- screenと重複している感じ
- field視点で、表示する/しないを設定することが可能
- fieldとscreenの紐づけをここで変更することが可能だけど、これはfield configurationローカルの変更ではなくて、Globalな変更となる。要はここで割り当てを変更すると、他のfield configurationの部分にも影響がでる
- とても分かり難い挙動。なんでこれだけglobal?
- 正直screen主体で考えた方が分かり易い気がした
field configuration scheme
- fieldとissue typeを紐づけ
- このissue typeではこのfieldを表示するみたいな感じ
- field configuration schemeをプロジェクトに割り当て
- 結局画面で表示されるのは、screenの設定とfieldの設定のAND
プロジェクトとscreen/workflow/field schemeの関係
たぶんこのドキュメントが一番分かり易いからこれを読めばOK
*1:issueの操作との紐づけはここではしない
pipでのパッケージのインストール先
pip使ってpythonのパッケージをインストールするときに、dnfやapt-getのようにsudoを付けて実行すると警告が表示されますね。
$ sudo pip3 install <package> WARNING: Running pip install with root privileges is generally not a good idea. Try `pip3 install --user` instead.
--user
オプション使えということですが、--user
使うとどこにインストールされるのか気になったので調べてみました。
まず、helpから調べてみる。
$ pip3 install --help ... --user Install to the Python user install directory for your platform. Typically ~/.local/, or %APPDATA%\Python on Windows. (See the Python documentation for site.USER_BASE for full details.)
通常、~/.local/
との事だけど、Pythonドキュメントのsite.USER_BASE
を読めとあるので探してみる。
site.USER_BASE Path to the base directory for the user site-packages. Can be None if getuserbase() hasn’t been called yet. Default value is ~/.local for UNIX and Mac OS X non-framework builds, ~/Library/Python/X.Y for Mac framework builds, and %APPDATA%\Python for Windows. This value is used by Distutils to compute the installation directories for scripts, data files, Python modules, etc. for the user installation scheme. See also PYTHONUSERBASE.
site-packagesのベースディレクトリへのパスで、distutilsがパッケージとかをインストールするときに利用すると。通常は~/.local
とやはり書いてある。ついでにPYTHONUSERBASE
もPythonのドキュメントで調べてみる。
PYTHONUSERBASE Defines the user base directory, which is used to compute the path of the user site-packages directory and Distutils installation paths for python setup.py install --user.
site-packagesのディレクトリを設定できる環境変数のようだ。インストール先を変えたい場合、これを変更すればよさそう。
ちなみにsite-packagesとかuser site-packagesのお話は、PEP370に書いてある。
user site directory A site directory inside the users' home directory. A user site directory is specific to a Python version. The path contains the version number (major and minor only).
AWS Certified Solution Architect Associate受験
年末にCloud Practitionerに合格したので、お正月休みに少し勉強してSolution Architect Associateを受験してみた。
やったこと
- 黒本ざっと読んで章末問題を2回ほど解く。
- A Cloud GuruのCertified Solution Architect AssociateコースのQuizを3回くらい。
結果
合格しました
所感
- Cloud Practitionerでざっと覚えたばかりなので、特に苦労なく
- 当然と言えば当然なんだけどアーキテクチャ的な内容を問う問題が多く、そういうのは問題文が長いので読むの面倒だった
- 特にCloudGuruで英語読むの。。。
AWS Certified Cloud Practitioner 受験
AWS Certified DevOps Engineer Professionalを取るよう言われてるけど、まずはということでCloud Practitionerの試験を受験してみた。 お勉強は基本こちらの本。知識としては業務でAWS使い始めて4、5ヵ月というレベルです。
やったことは本読んで、問題解いて、問題だけもう一回やって、A Cloud GuruでQuizを解いて練習という感じでした。 いかんせん本買ってからモチベーションが維持できずだらだらと3、4ヵ月たってしまったのが反省点。
無事合格。