AWS documentDBにLambdaから書き込むメモ(terraform)

目的

  • documentDBにLambdaから書き込みたい
  • 構成はterraformにて行う

LambdaのVPC接続について

VPC接続

  • LambdaはVPC接続して動かすという方法がある模様
    • LambdaがVPC(自分で作ったVPC)にアクセスして動作するイメージ

利点

  • VPC内のエンドポイント等にLamdaからアクセスできる
  • VPC内のリソースにLamdaがアクセスする際、Security Groupによるアクセス制御が可能(これが非常に嬉しい)

昔は遅かった

  • VPC内接続のLambdaは昔は非常に遅く、一回の実行10秒とかかかってたらしい(ENIをまいどまいど作っていた)

DocumentDBへのLamdaからのアクセス(VPC接続)

  • DocumentDBはパブリックなエンドポイントを持たない
    • VPCのリソースからのアクセスしかできない(もしくはLB等でのアクセス)
  • LambdaをVPCに接続して、DocumentDBへアクセスさせる

DocumentDBへのLamdaからのアクセス(VPC接続しない場合)

  • LBを使ったアクセス方法もあるらしい(ちょっと古い記事だけど)

dev.classmethod.jp

DocumentDBを作る

  • docdb.tf
resource "aws_docdb_subnet_group" "service" {
  name       = "docdb-${var.base_name}-subnet"
  subnet_ids = [var.subnet_for_docdb1.id, var.subnet_for_docdb2.id]
}

resource "aws_docdb_cluster_instance" "service" {
  count              = 1
  identifier         = format("docdb-%s-instnace-%02d", var.base_name, count.index + 1)
  cluster_identifier = aws_docdb_cluster.service.id
  instance_class     = var.docdb_instance_class
}

resource "aws_docdb_cluster" "service" {
  skip_final_snapshot             = true
  db_subnet_group_name            = aws_docdb_subnet_group.service.name
  cluster_identifier              = "docdb-cluster-${var.base_name}"
  engine                          = "docdb"
  master_username                 = var.docdb_admin_user
  master_password                 = var.docdb_password
  db_cluster_parameter_group_name = aws_docdb_cluster_parameter_group.service.name
  vpc_security_group_ids          = [aws_security_group.docdb.id]
}

resource "aws_docdb_cluster_parameter_group" "service" {
  family = "docdb3.6"
  name   = "docdb-parameter-group-${var.base_name}"
}
  • variable.tf
# name
variable "base_name" {}

# vpc information.
variable "vpc_main" {}

# subnet for docdb
variable "subnet_for_docdb1" {}
variable "subnet_for_docdb2" {}

# instance class
variable "docdb_instance_class" {
  default = "db.t3.medium"
}

# admin
variable "docdb_admin_user" {}
variable "docdb_password" {}

# allowd security group
variable "allowed_security_group" {}
  • security-group.tf
resource "aws_security_group" "docdb" {
  name   = "docudb-${var.base_name}"
  vpc_id = var.vpc_main.id

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_security_group_rule" "allowd_secutiry" {
  type                     = "ingress"
  from_port                = 0
  to_port                  = 0
  protocol                 = "-1"
  source_security_group_id = var.allowed_security_group.id
  security_group_id        = aws_security_group.docdb.id
}

ポイント

  • security groupを指定している
resource "aws_docdb_cluster" "service" {
  ...
  vpc_security_group_ids          = [aws_security_group.docdb.id]
}
  • このaws_security_group.docdbにて特定のsecurity groupからしかアクセスを許可しない設定にしている(これがLambdaのsecurity group)
resource "aws_security_group_rule" "allowd_secutiry" {
  ...
  source_security_group_id = var.allowed_security_group.id
}

Lambdaを作る

  • lambda.tf
resource "aws_lambda_function" "lambda" {
  ...
  vpc_config {
    subnet_ids = [
      var.subnet_for_lambda1.id,
      var.subnet_for_lambda2.id
    ]
    security_group_ids = [aws_security_group.for_lambda.id]
  }

  environment {
    variables = {
      DOCDB_CLUSTER_ENDPOINT = var.docdb_cluster_endpoint
      DOCDB_ADMIN_USER       = var.docdb_admin_user
      DOCDB_ADMIN_PASSWORD   = var.docdb_password
    }
  }
}

このようにvpc_configをつけてやればVPC接続で動いてくれるらしい

Lambdaのロールについて

  • VPC接続で実行する場合、ENIを作ったり、アクセスしたりするので、そのあたりの権限が必要
    • このあたりが必要らしい参考
ec2:CreateNetworkInterface
ec2:DescribeNetworkInterfaces
ec2:DeleteNetworkInterface
  • AWSLambdaVPCAccessExecutionRoleこれを使えばいいとか。

github.com

Lambdaソース

  • 公式を参考に

プログラムによる Amazon DocumentDB への接続 - Amazon DocumentDB

実行

X-rayで見てみました

  • 初回起動時(コールドスタート)

    • 結構遅い f:id:y-ni-shi:20200830001810j:plain
  • 2回め起動時

    • 1回目よりは速い(しかし全体で400ms.遅い) f:id:y-ni-shi:20200830001814j:plain
  • メモリを大きくしてもそこまで速度変わらず

まとめ

  • DocumentDBはパブリックなエンドポイントを持たないので、Lambdaからアクセスするには工夫が必要
    • LambdaをVPCアクセス
    • LambdaからLBでアクセス
  • LambdaのVPC接続は昔は遅かったけど、今は速い
    • ENIにアクセスするコストはかかっていると思われるが、大したこと無い
  • documentDBへのアクセスはほどほどに時間かかりそう(単なる通信のコストだろうか)
  • VPC接続なしのdocumentDBアクセスでどれくらいの速度かやってみたい(LBでのアクセス)

AWS documentDBメモ

Amazon documentDB

メモの内容

AWSにdocumentDBをたてる

  • awsコンソールからdocumentDBの画面から「作成」 f:id:y-ni-shi:20200829131510p:plain

AWS documentDBにアクセスする前の準備

  • EC2などのAWSリソースからしかアクセスできない(パブリックなエンドポイントはない)
Amazon DocumentDB は VPC のみのサービスであり、パブリックエンドポイントをサポートしていません。その結果、AWS 外部の環境から Amazon DocumentDB クラスターに直接接続することはできません

今回はEC2を立ててそこからアクセスする

EC2のインスタンスを起動してSSH

  • ここは割愛

EC2にmongo shellをインストールしたい

  • 参考(公式ページ) aws.amazon.com

  • 以下のコマンドでmongo shellインストール

$ echo -e "[mongodb-org-3.6] \nname=MongoDB Repository\nbaseurl=https://repo.mongodb.org/yum/amazon/2013.03/mongodb-org/3.6/x86_64/\ngpgcheck=1 \nenabled=1 \ngpgkey=https://www.mongodb.org/static/pgp/server-3.6.asc" | sudo tee /etc/yum.repos.d/mongodb-org-3.6.repo
$ sudo yum install -y mongodb-org-shell

証明書のダウンロード

  • 証明書で暗号化をして通信をする必要がある
    • デフォルトでは暗号化通信が有効になっているので、この証明書を使うことが必須のよう
  • 以下のコマンドでダウンロードしておく
$ wget https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.pem

AWSのdocumentDBクラスタに接続する

これがよくわからん・・・(接続失敗することが当初多発した)

f:id:y-ni-shi:20200829131733p:plain

  • 上記のように接続情報が出る
  • mongo シェルでこのクラスターに接続するの部分に記載のある情報でアクセスしたい
    • しかし、なぜか失敗することがある(起動直後はだめだったので、クラスタが立ち上がるまで結構かかる?)
  • 以下がエラーメッセージ
$ mongo --ssl --host <cluster-endpoint>.ap-northeast-1.docdb.amazonaws.com:27017 --sslCAFile rds-combined-ca-bundle.pem --username masteruser --password secretsecret
MongoDB shell version v3.6.19
connecting to: mongodb://<cluster-endpoint>.ap-northeast-1.docdb.amazonaws.com:27017/?gssapiServiceName=mongodb
2020-08-29T03:58:48.208+0000 I NETWORK  [thread1] getaddrinfo("<cluster-endpoint>.ap-northeast-1.docdb.amazonaws.com") failed: Name or service not known
2020-08-29T03:58:48.208+0000 E QUERY    [thread1] Error: couldn't initialize connection to host <cluster-endpoint>.ap-northeast-1.docdb.amazonaws.com, address is invalid :
connect@src/mongo/shell/mongo.js:263:13
@(connect):1:6
exception: connect failed

Failed: Name or service not known

  • クラスタの名前が解決できていない?(DNSへの反映?)
    • クラスタの準備ができるまでは接続できないのか

クラスタにアクセスするのではなく、インスタンスに直接アクセスも可能

  • とりあえずトラブルシュートするときにはインスタンスへのアクセス方法も知っておいていいと思う
    • クラスタエンドポイントではなく、インスタンスにならとりあえず直接可能
  • 以下に手順。

AWSCLIを使ってdocumentDBのクラスタとかインスタンスを確認する

docs.aws.amazon.com

$ aws docdb describe-db-instances \
   --db-instance-identifier sample-instance \
   --query 'DBInstances[*].[Endpoint.Address,Endpoint.Port]'
  • ここで取得したエンドポイントに対してmongo shellで接続!
$ mongo --ssl --host <インスタンスエンドポイント>:27017 --sslCAFile rds-combined-ca-bundle.pem --username masteruser --password <insertYourPassword>

mongo shellでの接続後

  • DB表示
$ show dbs
  • DB使う(勝手に作る)
$ use <db name>
  • collection表示
$ show collections
  • myというコレクション作る
$ db.createCollection('my');
  • myというコレクションの全件表示
$ db.my.find()
  • myというコレクションにインサート
$ db.my.insert({name: 'myname',})

mongodbをDockerで起動するメモ

Dockerにてmongodbを起動したい

$ docker run --rm -it -d mongo
  • このコマンドでmongodbがバックグラウンドで起動します

バージョン指定したい場合

$ docker run --rm -it -d mongo:version
  • こんな感じでバージョン指定

mongodbのコンテナ内に入る

  • まずはdockerのコンテナIDを確認(docker ps)
  • 以下のは例ですが、94f49d3d4626と確認できます
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
94f49d3d4626        mongo               "docker-entrypoint.s…"   2 seconds ago       Up 1 second         27017/tcp           kind_pascal
  • このコンテナに入ります(bash
$ docker exec -it 94f49d3d4626 bash
root@94f49d3d4626:/#
  • こんな感じでrootユーザで入れるはず

mongodbの操作をする

  • 上記のような要領でまずはコンテナに入る
# mongo
  • これでmongoシェルが起動

EKSコマンドメモ

EKS関連

  • EKSへのログイン
$ aws eks --region ap-northeast-1 update-kubeconfig --name eks-test

K8メモ

  • コンテキストのリストの表示
$ kubectl config get-contexts
  • 現在のコンテキストの表示
$ kubectl config current-context
$ kubectl get po --selector=app=nginx --all-namespaces

terraformでfileを相対パス記載する

terraform version

  • 0.12以上

記載方法

  • module内にてfileを相対パスで指定したい場合、${path.module}が使える
    • 例えば"${path.module}/cert/sample.pem"でファイルのパスを作ってくれる(相対パスを作成してくれる)

具体例

  • certのpemを指定する場合(ファイルを展開したい場合)
    • moduleのcertディレクトリにあるファイルを指定したい
    • /path/to/module/cert/sample.pemを指定する
resource "aws_iot_certificate" "cert" {
  csr    = file("${path.module}/cert/sample.pem")
  active = true
}

memo

CodeCommitでDinDするときのメモ

サンプルbuildspec.yml

version: 0.2

phases:
  install:
    commands:
      - nohup /usr/local/bin/dockerd --host=unix:///var/run/docker.sock --host=tcp://127.0.0.1:2375 --storage-driver=overlay2&
      - timeout 15 sh -c "until docker info; do echo .; sleep 1; done"
  pre_build:
    commands:
      - docker info
      - aws sts get-caller-identity
      - aws eks update-kubeconfig --name ${EKS_CLUSTER_NAME}
  build:
    commands:
      - echo build
      - kubectl get all

ポイント

docs.aws.amazon.com

  • installフェーズでdockerの起動をする
  install:
    commands:
      - nohup /usr/local/bin/dockerd --host=unix:///var/run/docker.sock --host=tcp://127.0.0.1:2375 --storage-driver=overlay2&
      - timeout 15 sh -c "until docker info; do echo .; sleep 1; done"

AWS EKSをCodePipelineから操作するメモ

内容

  • CodeBuildeでkubectl applyを実施したい
  • エラーerror: You must be logged in to the server (Unauthorized)
    • CodeBuildでkubectlしたいが、このエラーが出てしまう

参考ページ

dev.classmethod.jp

qiita.com

メモ

  • 基本的に上記クラスメソッドさんのブログのように進めればOK
    1. EKS, EKSノードグループ作成
    2. CodePipeline, CodeBuild作成
    3. CodeBuildのロールの調整(CodeBuildがkubectlできるようにする)

上記 CodeBuildのロールの調整(CodeBuildがkubectlできるようにする)これでハマった

  • 上記ブログにもあるように、EKSクラスタのConfigMap情報を編集する必要がある
    • CodeBuildがEKSクラスタにアクセスできるような設定にしてやる必要がある
  • EKSクラスタにログインできるコンソールから以下のコマンドを実行してaws-auth
$ kubectl edit -n kube-system configmap/aws-auth

これでCodebuilで使用するロール情報を追記してやる必要がある

    - rolearn: <CodeBuildのサービスロールのARN>
      username: codebuild
      groups:
        - system:masters

これを追記

CodeBuildのサービスロールのARNについて

  • CodeBuildにアタッチしてあるロールを見てみると以下のようになってる
    • arn:aws:iam::xxxxxxxxx:role/service-role/codebuild-role
  • このarnrolearnとして記載してもうまくいかない
  • 上記Qiitaブログに書いてあるが
○: arn:aws:iam::xxxxx:role/codebuild-hoge-service-role
×: arn:aws:iam::xxxxx:role/service-role/codebuild-hoge-service-role

ということらしい