#author("2019-03-15T13:11:19+00:00","","") #mynavi(AWSメモ) #setlinebreak(on); * 目次 [#wef7852b] #contents - 関連 -- [[AWSメモ]] - 参考 -- https://aws.amazon.com/jp/getting-started/projects/setup-jenkins-build-server/ -- https://aws.amazon.com/jp/blogs/devops/integrating-aws-codecommit-with-jenkins/ * 概要 [#w74ec372] #html(<div style="padding-left: 10px;">) EC2インスタンス上にJenkinsをインストールして、API Gateway & Lambda をテスト/デプロイする環境を構築する。 #html(</div>) * IAMユーザの作成 [#dc777e43] #html(<div style="padding-left: 10px;">) [[マネジメントコンソール>https://console.aws.amazon.com/iam/home?region=ap-northeast-1#/users]] から Jenkins がデプロイ等に使用するIAMユーザを作成する。 #TODO(アタッチするポリシーを書く) // AWSCodeCommitFullAccess // IAMFull // cloudformation #html(</div>) * CodeCommitリポジトリの作成 [#be04414e] #html(<div style="padding-left: 10px;">) [[マネジメントコンソール>https://ap-northeast-1.console.aws.amazon.com/codesuite/codecommit/repositories?region=ap-northeast-1]] からリポジトリを作成しておく。 #html(</div>) * EC2インスタンスの作成 [#p40f0751] #html(<div style="padding-left: 10px;">) [[マネジメントコンソール>https://ap-northeast-1.console.aws.amazon.com/ec2/v2/home?region=ap-northeast-1#Instances:sort=instanceId]] からJenkinsをインストールするEC2インスタンスを作成する。 ※セキュリティグループでポート 8080 を許可しておく事。 #html(</div>) * EC2インスタンスの設定 [#bbce0ba9] #html(<div style="padding-left: 10px;">) EC2インスタンスに接続して以下の作業を行う。 ** ec2-user用の aws-cli の設定 [#s769b608] 確認用に ec2-user 用に aws-cli の設定をしておく。 ここでは、作成しておいたIAMユーザの AWS Access Key ID、AWS Secret Access Key、リージョン等を設定する。 #myterm2(){{ aws configure AWS Access Key ID [None]: XXXXXXXXXXXXXXXXXXXX AWS Secret Access Key [None]: XXXXX.......XXXXXX Default region name [None]: ap-northeast-1 Default output format [None]: }} ** ec2-user 用の git の設定 [#oc27edcb] 確認用に ec2-user 用に git クライアントの設定を行っておく。 認証にはIAMを使用する為、以下の通り設定する。 #myterm2(){{ git config --global credential.helper '!aws codecommit credential-helper $@' git config --global credential.useHttpPath true git config --global user.name "ユーザ名" git config --global user.email "メールアドレス" }} ** CodeCommit へのアクセス確認 [#s1298ac9] 先ほど作成した CodeCommit リポジトリにIAMでアクセスできるか確認する。 #myterm2(){{ git clone https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/Xxxxxxx }} ※Jenkins からのアクセスは jenkinsユーザでのアクセスになる為、別途設定が必要。(後述) ** Jenkinsのインストール [#c31e9f98] 起動したEC2インスタンスで以下の作業を行う。 ※参考: https://d1.awsstatic.com/Projects/P5505030/aws-project_Jenkins-build-server.pdf ** JDK8 のインストール [#f664e401] #myterm2(){{ sudo yum install -y java-1.8.0-openjdk-devel }} ** 使用するJavaバージョンの切替 [#r78e8b85] #myterm2(){{ sudo alternatives --config java 2 プログラムがあり 'java' を提供します。 選択 コマンド ----------------------------------------------- *+ 1 /usr/lib/jvm/jre-1.7.0-openjdk.x86_64/bin/java 2 /usr/lib/jvm/jre-1.8.0-openjdk.x86_64/bin/java Enter を押して現在の選択 [+] を保持するか、選択番号を入力します:2 }} バージョンが切り替わったか確認 #myterm2(){{ java -version openjdk version "1.8.0_201" OpenJDK Runtime Environment (build 1.8.0_201-b09) OpenJDK 64-Bit Server VM (build 25.201-b09, mixed mode) }} ** Gitのインストール [#w1c5446a] #myterm2(){{ sudo yum install git -y }} ** Jenkinsのインストール [#n4605e1f] #myterm2(){{ sudo yum update -y sudo wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo sudo rpm --import https://pkg.jenkins.io/redhat/jenkins.io.key sudo yum install jenkins -y }} ** Jenkins ユーザ用の git 設定 [#f9310d5f] jenkins からCodeCommit にアクセスする際に IAMロールでアクセスするように設定する。 jenkins ユーザのホームディレクトリは /var/lib/jenkins になっているので、その配下に .gitconfig を以下の通り作成する。 #myterm2(){{ sudo touch /var/lib/jenkins/.gitconfig sudo chmod 664 /var/lib/jenkins/.gitconfig sudo chown jenkins:jenkins /var/lib/jenkins/.gitconfig sudo vim /var/lib/jenkins/.gitconfig [user] name = ユーザ名 email = メールアドレス [credential] helper = !aws codecommit credential-helper $@ useHttpPath = true }} ** Jenkinsユーザ用の aws-cliの設定 [#p686d994] 作成しておいたIAMユーザの AWS Access Key ID、AWS Secret Access Key、リージョン等を設定する。 #myterm2(){{ sudo -u jenkins aws configure AWS Access Key ID [None]: XXXXXXXXXXXXXXXXXXXX AWS Secret Access Key [None]: XXXXX.......XXXXXX Default region name [None]: ap-northeast-1 Default output format [None]: }} ** Jenkinsのサービス開始 [#gdbfc49e] #myterm2(){{ sudo service jenkins start }} ** Jenkinsインストール用の管理者パスワードを確認 [#lc81743b] #myterm2(){{ sudo cat /var/lib/jenkins/secrets/initialAdminPassword }} #html(</div>) * 処理の作成 [#dffd36c5] #html(<div style="padding-left: 10px;">) ここからはローカル環境で処理をデプロイする処理(API Gateway 及び Lambda)を作成していく。 ali-cli や git の設定は [[上記>#s769b608]] と同じ感じで設定しておく事。 ** 準備 [#c8596510] #html(<div style="padding-left: 10px;">) *** git チェックアウト [#v0d4c0f8] #html(<div style="padding-left: 10px;">) #myterm2(){{ mkdir ~/workspace git clone https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/SampleRepo # 作成しておいたCodeCommitリポジトリのURL cd SampleRepo git checkout develop }} #html(</div>) #html(</div>) ** 処理の作成 [#lb9987cf] #html(<div style="padding-left: 10px;">) *** book.py [#od3ba411] #html(<div style="padding-left: 10px;">) #mycode2(){{ # coding: utf-8 """ サンプルLambda. """ import json def index(event, context): """本の一覧を取得する. Args: event (obj): イベント context (obj): コンテキスト """ # 本の一覧 books = [{'isbn': f'sample{i+1:03d}', 'title': f'BOOK{i+1:03d}'} for i in range(5)] # 戻り値 response = { 'statusCode': 200, 'headers': { 'Content-Type': 'application/json' }, 'body': json.dumps({'list': books, 'count': len(books)}) } return response }} #html(</div>) *** template.yml [#w4800203] #html(<div style="padding-left: 10px;">) #mycode2(){{ AWSTemplateFormatVersion : '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: Test serverless application. Resources: SampleBookApi: Type: AWS::Serverless::Function Properties: FunctionName: SampleBookFunction Description: "Sample" Handler: book.index Runtime: python3.6 Events: BookList: Type: Api Properties: Path: /book Method: get BookGet: Type: Api Properties: Path: /book/{id} Method: get Outputs: SampleBookApiUri: # 作成したAPIのURIをエクスポートしておく(AWS::Serverless変換を使用した場合、ステージは Stage,Prod の2つが作成される) Description: "API Gateway endpoint URL for Prod stage" Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/" Export: Name: SampleBookApiUri }} #html(</div>) #html(</div>) #html(</div>) * ローカルで動作確認 [#b41a391f] #html(<div style="padding-left: 10px;">) 作成した処理をSAMローカルで動作確認する。 ** sam-cli インストール [#d5d1185f] #html(<div style="padding-left: 10px;">) #myterm2(){{ sudo yum -y install gcc sudo yum install python-devel pip install --upgrade pip pip install --user aws-sam-cli }} #html(</div>) ** python3.6インストール [#v5868c0b] #html(<div style="padding-left: 10px;">) #myterm2(){{ yum list available | grep "python36" sudo yum install python36 }} #html(</div>) ** Dockerインストール&起動 [#wecaef91] #html(<div style="padding-left: 10px;">) Dockerをインストールして起動しておく。 linuxの場合は自分をdockerグループに追加しておく。( /var/run/docker.sock にアクセスできる状態にしておかないと docker コマンドが使用できない ) #myterm2(){{ sudo yum install -y docker sudo service docker start sudo usermod -a -G docker ユーザ名 }} #html(</div>) ** その他のツールをインストール [#fe5299d8] #html(<div style="padding-left: 10px;">) jq など使用しそうなツールをインストール #myterm2(){{ sudo yum -y install jq # sudo pip install yq }} #html(</div>) ** SAMローカルを起動 [#i7e5d422] #html(<div style="padding-left: 10px;">) いったんターミナルからログアウト。(環境変数を読み込み直したいだけ) #myterm2(){{ exit }} 再度ログインして SAM Local起動 #myterm2(){{ cd ~/workspace/SampleRepo sam local start-api --template template.yml 2019-01-01 08:15:11 Found credentials in shared credentials file: ~/.aws/credentials 2019-01-01 08:15:11 Mounting BookFunction at http://127.0.0.1:3000/book [GET] 2019-01-01 08:15:11 You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload SAM CLI while working on your functions, changes will be reflected instantly/automatically. You only need to restart SAM CLI if you update your AWS SAM template 2019-01-01 08:15:11 * Running on http://127.0.0.1:3000/ (Press CTRL+C to quit) }} #html(</div>) 別のターミナルを起動してリクエストを投げてみる #myterm2(){{ curl http://127.0.0.1:3000/book | jq % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 237 100 237 0 0 236 0 0:00:01 0:00:01 --:--:-- 236 { "list": [ { "isbn": "sample001", "title": "BOOK001" }, { "isbn": "sample002", "title": "BOOK002" }, { "isbn": "sample003", "title": "BOOK003" }, { "isbn": "sample004", "title": "BOOK004" }, { "isbn": "sample005", "title": "BOOK005" } ], "count": 5 } }} #html(</div>) #html(</div>) * デプロイ用のシェルを作成する [#if4dd452] #html(<div style="padding-left: 10px;">) デプロイ処理は Jenkins からそのまま使用できるようにシェル化する。 ** シェルの作成 [#h3e9df56] #html(<div style="padding-left: 10px;">) Jenkins から利用する為のデプロイ用シェルを作成する。 build.sh #mycode2(){{ #!/bin/bash echo "" MODE=$1 # スタック名 DIR_NAME=`basename \`pwd\`` STACK_NAME=`echo $DIR_NAME | sed 's/Repo$/Stack/'` # アカウントIDの取得 ACCOUNT_ID=`aws sts get-caller-identity | grep Account | awk '{print $2}' | sed -e "s/[^0-9]//g"` # スタック作成時のイベント確認 if [ "${MODE}" == "desc" ]; then aws cloudformation describe-stack-events --stack-name $STACK_NAME exit 0 fi # 削除 if [ "${MODE}" == "del" ]; then aws cloudformation delete-stack --stack-name $STACK_NAME aws cloudformation wait stack-delete-complete --stack-name $STACK_NAME exit 0 fi # S3バケットがない場合は作る(バケット名は世界で唯一である必要がある為、末尾にアカウントID等を付与しておく) BUCKET_NAME=my-cloudformation-templates-${ACCOUNT_ID} BUCKET_COUNT=`aws s3api list-buckets | grep -e "\"${BUCKET_NAME}\"" | wc -l` if [ "${BUCKET_COUNT}" == "0" ]; then echo aws s3api create-bucket --create-bucket-configuration '{"LocationConstraint": "ap-northeast-1"}' --bucket $BUCKET_NAME fi # 検証&パッケージング&デプロイ (成功時は作成したAPIのURIを表示する) aws cloudformation validate-template --template-body file://template.yml \ && aws cloudformation package --template-file template.yml --s3-bucket $BUCKET_NAME --output-template-file packaged-template.yml \ && aws cloudformation deploy --template-file packaged-template.yml --stack-name $STACK_NAME --capabilities CAPABILITY_IAM \ && echo "" \ && echo "### Exported Value ###" \ && aws cloudformation describe-stacks --stack-name $STACK_NAME | awk 'BEGIN{key=""}{ if ($1 == "\"OutputKey\":") key=$2; if ($1 == "\"OutputValue\":") print key" : "$2 }' | sed 's/[",]//g' \ && echo "######################/" \ && echo "" }} #html(</div>) ** テストデプロイ [#y810683f] #html(<div style="padding-left: 10px;">) 作成したシェルでデプロイできるか確認。 #myterm2(){{ ./build.sh { "Description": "Test serverless application.", "Parameters": [] } Uploading to f799....c72 28043 / 28043.0 (100.00%) Successfully packaged artifacts and wrote output template to file packaged-template.yml. Execute the following command to deploy the packaged template aws cloudformation deploy --template-file /path_to/SampleRepo/packaged-template.yml --stack-name <YOUR STACK NAME> Waiting for changeset to be created.. Waiting for stack create/update to complete Successfully created/updated stack - SampleStack ### Exported Value ### SampleBookApiUri : https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/Prod/ ######################/ }} 良さげなので、アンデプロイしておく。 #myterm2(){{ ./build.sh del }} #html(</div>) #html(</div>) * git リポジトリにプッシュ [#s974f195] #html(<div style="padding-left: 10px;">) ** git commit & push [#ae6e2eca] #html(<div style="padding-left: 10px;">) #myterm2(){{ git add . git commit -m 'first commit' git push }} #html(</div>) ** masterにマージ [#pab838ad] #html(<div style="padding-left: 10px;">) #myterm2(){{ git checkout master git merge develop git push }} #html(</div>) #html(</div>) * Jenkinsの設定 [#c6e4a45a] #html(<div style="padding-left: 10px;">) ** Jenkinsにログイン [#g017c319] #html(<div style="padding-left: 10px;">) 対象のEC2インスタンスの 8080ポート(※)にアクセスし、Administrator password に、先程確認した管理者パスワードを入力してログイン後、 [Install suggested plugins] で適当なプラグインをインストールしておく。 ※ http://EC2のパブリックDNS:8080 #html(</div>) ** ジョブの作成 [#gd3abfe0] #html(<div style="padding-left: 10px;">) #TODO #html(</div>) ** XXXXXXXXXX [#m88eb6d4] #html(<div style="padding-left: 10px;">) #TODO #html(</div>) #html(</div>)