こんにちは、uemura_rks です。
個人的な勉強目的で GitLab 上で AWS Lambda のデプロイを自動化してみました。
GitLab での CICD や AWS SAM、あとは Docker に興味を持っている方に向けて、その構築履歴を紹介したいと思います。
基本的には各ツールのドキュメントを参照しつつ、追記した設定などを共有していきます。
作りたいもの
ローカルに Docker で GitLab や GitLab Runner を立てつつ、プッシュしたら AWS 上に自動デプロイが走る構成を目指します。
- GitLab に push したら GitLab Runner が走る。
- GitLab Runner から ジョブ実行用コンテナを起動。
コンテナには AWS SAM CLI が使えるイメージを利用します。 - AWS SAM CLI を使って Lambda 本体や AWS リソースを定義した Stack をデプロイ。
1.GitLab 構築
参考:GitLab Docker images | GitLab
さっそく GitLab の構築からはじめていきます。
Docker 上に構築するので、参考ドキュメントのdocker-compose.yml
の部分をベースとして拝借していきます。
version: '3' services: gitlab: container_name: gitlab image: 'gitlab/gitlab-ce:latest' restart: always hostname: 'local-gitlab' environment: GITLAB_OMNIBUS_CONFIG: | external_url 'http://local-gitlab:8929' ports: - '80:8929' volumes: - ./gitlab/config:/etc/gitlab - ./gitlab/logs:/var/log/gitlab - ./gitlab/data:/var/opt/gitlab shm_size: '2gb'
ドキュメントでは エンタープライズ版の gitlab-ee
イメージを指定していますが、
今回は個人利用なのでコミュニティ版のgitlab-ce
を使います。
volumes:
セクションに関して、フォルダ構成はこんな感じにしています
$ tree ├── gitlab (GitLab の volume) ├── gitlab-runner (GitLab Runner の volume とする予定) ├── docker-compose.yml └── sampleapp (サンプルアプリを入れる予定)
一度立ち上げてみます
docker-compose up -d
名前解決できるようにローカルマシンの hosts ファイルに
127.0.0.1 local-gitlab
を追記すると GitLab( http://local-gitlab/ ) でアクセス出来るようになります。
初回は root ユーザでログインすることになりますが、
root のパスワードはこちらのコマンドで知ることが出来ます。
# Visit the GitLab URL, and sign in with the username root and the password from the following command:
sudo docker exec -it gitlab grep 'Password:' /etc/gitlab/initial_root_password
2.GitLab Runner 構築
参考:Run GitLab Runner in a container
こちらもドキュメントに載っている docker run コマンドを参考に、docker-compose.yml
に起こしていきます。
version: '3' networks: gitlab-network: name: gitlab-network driver: bridge services: gitlab: container_name: gitlab image: 'gitlab/gitlab-ce:latest' restart: always hostname: 'local-gitlab' environment: GITLAB_OMNIBUS_CONFIG: | external_url 'http://local-gitlab:8929' ports: - '80:8929' volumes: - ./gitlab/config:/etc/gitlab - ./gitlab/logs:/var/log/gitlab - ./gitlab/data:/var/opt/gitlab shm_size: '2gb' networks: - gitlab-network runner: container_name: gitlab-runner image: gitlab/gitlab-runner:latest restart: always volumes: - ./gitlab-runner/config:/etc/gitlab-runner - /var/run/docker.sock:/var/run/docker.sock networks: - gitlab-network
ついでに内部ネットワークを作成して、二つのコンテナを同じネットワークに入れておきます。
GitLab Runner の登録
GitLab Runner コンテナも立ち上げたら、GitLab に Runner を登録していきます。
登録トークン取得
参考:Registering runners (deprecated) | GitLab
Runner の登録に入る前に GitLab の登録トークンというものを取得しておきます。
GitLab にリポジトリを作ると、リポジトリのSettings > CI/CD > Runners
から GitLab Runner の登録時に必要な「GitLab の URL」と「登録トークン」が取得できます。
注意点として、今紹介している登録トークンを使った方法は、現在の GitLabバージョン15.6 では deprecated となっております。
新しく認証トークンによる登録ができるようになる予定みたいですが、現在はまだ登録トークンを使うしかないのでそのまま進めます。(絶妙にタイミングが悪かったです。)
登録コマンドの実行
参考:one-line-registration-command
Runner の登録に必要な URL と登録トークンが確認できたので、GitLab Runner コンテナに入って register コマンドを実行していきます。
gitlab-runner register \ --non-interactive \ --url "http://local-gitlab:8929/" \ --registration-token "PROJECT_REGISTRATION_TOKEN" \ --executor "docker" \ --docker-image alpine:latest \ --description "docker-runner" \ --docker-network-mode gitlab-network
--url
:docker ネットワーク内の通信になるので、コンテナポートを付け足しておきます。--docker-image
:後に作成する.gitlab-ci.yml
にコンテナイメージを指定しなかった場合のデフォルトになるみたいです。今回は使う予定がないのでサンプルのまま登録しています。--docker-network-mode
:docker-compose.yml で用意したネットワークを指定しておきます。
登録に成功すると GitLab に「Available specific runners」が増えています。
3.Lambda 環境構築
GitLab Runner の構築までできたので、次は Lambda を用意していきます。
「Lambda のデプロイを自動化する」というゴールから考えると Lambda 単体で試してもよかったのですが、 前から興味があったという理由で今回は AWS SAM を使ってみます。
この投稿では触れませんが、AWS SAM はローカル環境も手に入るのが良いです。
AWS SAM チュートリアル
参考:チュートリアル: Hello World アプリケーションのデプロイ - AWS Serverless Application Model
チュートリアルの Hello World アプリケーションをデプロイしてみます。
API Gateway と Lambda ですね。
チュートリアルの #Step 1 をローカルで実行します。
#Step 1 - Download a sample application
sam init
すると、「hello world」と出力するだけの Lambda 関数とインフラ定義ファイルの template.yml
が作成されます。
一度この状態でローカルからデプロイしてみます。
#Step 2 - Build your application
cd sam-app
sam build
#Step 3 - Deploy your application
sam deploy --guided
dry-run の結果を教えてくれます。
Waiting for changeset to be created.. CloudFormation stack changeset ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Operation LogicalResourceId ResourceType Replacement ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Add HelloWorldFunctionHelloWorldPermissionProd AWS::Lambda::Permission N/A + Add HelloWorldFunctionRole AWS::IAM::Role N/A + Add HelloWorldFunction AWS::Lambda::Function N/A + Add ServerlessRestApiDeploymentxxxxxxxxxx AWS::ApiGateway::Deployment N/A + Add ServerlessRestApiProdStage AWS::ApiGateway::Stage N/A + Add ServerlessRestApi AWS::ApiGateway::RestApi N/A ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Changeset created successfully. arn:aws:cloudformation:ap-northeast-1:000000000000:changeSet/samcli-deploy0000000000/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Previewing CloudFormation changeset before deployment ====================================================== Deploy this changeset? [y/N]:
AWS SAM は CloudFormation を拡張したサービスらしいので、メッセージに CloudFormation という単語がちょくちょく出てきますね。
問題ないので「Deploy this changeset? 」に y で答えてデプロイを実行します。
無事に CloudFormation に Stack ができています。
Lambda や API Gateway を個別に見に行ってもちゃんとできています。
デプロイできたので、curl を叩いて hello world が返ってくることを確認しておきます。
$ curl https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/Prod/hello {"message": "hello world"}
4.デプロイ自動化
参考:GitLab CI/CD を使用したデプロイ - AWS Serverless Application Model
AWS SAM だけでも1コマンドでデプロイできるようになるので十分便利なのですが、極力人の操作を減らしたいです。
GitLab Runner を使って、プッシュしたら自動で SAM アプリがデプロイされるようにしていきます。
#Step 2 - Build your application
cd sam-app
sam build
#Step 3 - Deploy your application
sam deploy --guided
先ほど手で実行した↑の部分が CI/CD 部分ということで、ここを.gitlab-ci.yml
に切り出します。
image: public.ecr.aws/sam/build-python3.9 stages: - build - deploy job_build: stage: build script: - cd sam-app - sam build job_deploy: stage: deploy variables: GIT_CLEAN_FLAGS: none script: - cd sam-app - sam deploy --no-confirm-changeset --no-fail-on-empty-changeset
GitLab Runner のジョブ実行用コンテナには AWS が提供しているイメージを利用します。
AWS SAM CLI が最初から入っているので助かります。
また、ジョブ実行時に利用される IAM のアクセスキーなどを GitLab の Variables に登録しておきます。
参考:Deploying AWS Lambda function using GitLab CI/CD | GitLab
リポジトリのSettings > CI/CD > Variables
から登録できます。
あとは、.gitlab-ci.yml
をプッシュすれば GitLab Runner ジョブが立ちあがるようになります。
5.自動デプロイの確認
AWS SAM の Lambda と テンプレートをいじって push→deploy してみます。
Lambda の変更
Hello World アプリケーションで元々コメントアウトされていたグローバルIP取得の処理を アンコメントしてみます。
import json import requests def lambda_handler(event, context): ~~~ ~~~ try: ip = requests.get("http://checkip.amazonaws.com/") except requests.RequestException as e: # Send some context about this error to Lambda Logs print(e) raise e return { "statusCode": 200, "body": json.dumps({ "message": "hello world", "location": ip.text.replace("\n", "") // ★ IP出力部分をアンコメント }), }
テンプレートの変更
参考:FunctionUrlConfig - AWS Serverless Application Model
API Gateway を破棄して、代わりに Lambda の 関数 URL をエンドポイントとして用意してみます。
Resources: HelloWorldFunction: Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction Properties: CodeUri: hello_world/ Handler: app.lambda_handler Runtime: python3.9 Architectures: - x86_64 FunctionUrlConfig: AuthType: NONE Outputs: HelloWorldFunctionUrlEndpoint: Description: "Hello World Lambda Function URL Endpoint" Value: !GetAtt HelloWorldFunctionUrl.FunctionUrl
Properties:Events:
セクションで定義されていた API Gateway を 関数 URL の設定に置き換えています。
変更が終わったので、プッシュして、GitLab の Pipeline が走ることを確認します。
無事に Pipeline が走って、
されています。
最後に確認として変更後のエンドポイントに curl してみます。
$ curl https://xxxxxxxxxxxxxxxx.lambda-url.ap-northeast-1.on.aws/ {"message": "hello world", "location": "3.115.88.55"}
IPアドレスも返ってきました。
終わりに
ひとまず GitLab + GitLab Runner + AWS SAM という構成で、プッシュしたものを AWS 上に自動でデプロイする土台は作ることができました。
昔、Lambda をマネジメントコンソールから毎回アップロードしていたことがあったので、今後はその手間から解放されそうです。
また、私は Docker についても最近触り始めたばかりなのですが、「GitLab + GitLab Runner」という構成は複数コンテナを組み合わせた構成ということもあって、Docker 初学者にとって良い練習教材になりました。
実業務では自動デプロイだけでなく UT や SAST など自動テストの考慮も必要になると思います。
それらと今回作ってみた構成の相性については、別途検証が必要かなと考えています。
参考
公式ドキュメント以外で参考にさせていただいたブログです。
Dockerコンテナでgitlabとgitlab-runnerを構築してCI/CD | SyachikuLOG
エンジニア中途採用サイト
ラクスでは、エンジニア・デザイナーの中途採用を積極的に行っております!
ご興味ありましたら是非ご確認をお願いします。
https://career-recruit.rakus.co.jp/career_engineer/
カジュアル面談お申込みフォーム
どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。
以下フォームよりお申込みください。
rakus.hubspotpagebuilder.com
ラクスDevelopers登録フォーム
https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/
イベント情報
会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください!
◆TECH PLAY
techplay.jp
◆connpass
rakus.connpass.com