kakakakakku blog

Weekly Tech Blog: Keep on Learning!

ElastiCache for Redis でシングルコアに対応したメトリクス EngineCPUUtilization が追加された

今月発表された ElastiCache for Redis のリリースで,新 CloudWatch メトリクス EngineCPUUtilization が追加された.

今まで

もともと Redis はシングルコアで稼働するため,例えば vCPU 4 を搭載する cache.r4.xlarge を使う場合,CPUUtilization の 25% で「実質 100%」を意味する.この仕様を理解できていないと,Redis の CPU 負荷を見逃してしまう可能性もあり,よく知られていると思う.Black Belt 資料にも記載がある.

www.slideshare.net

これから

今後はシングルコアに対応したメトリクス EngineCPUUtilization を使えば,vCPU を気にせずにモニタリングすることができる.監視設定で計算をする必要もなくなり,とにかく便利!

新しいメトリックスは以前存在した CPUUtilization メトリックスに加えられ、その他のオペレーティングシステムや管理プロセスを含むサーバーインスタンスの CPU の使用状況の全体をまとめて示します。新しい EngineCPUUtilization と以前の CPUUtilization メトリックスの両方をまとめて使用して、お使いの Redis 環境の CPU 使用状況の詳細を理解されることをお勧めいたします。

実際に CloudWatch で確認をしてみた.

f:id:kakku22:20180417193941p:plain

注意点は ElastiCache for Redis クラスタを構築した時期によって EngineCPUUtilization を取得できないことで,日本語のドキュメントには「2017/11/01 以降」と書かれていた.ただし,英語のドキュメントには「February 14, 2017 19:58 (UTC)」と書かれていて,そこそこズレているので,実際に確認してみるのが良さそう.

docs.aws.amazon.com

docs.aws.amazon.com

Mackerel AWS Integration

昨日のリリースで,Mackerel AWS Integration でも EngineCPUUtilization を取得できるようになった.ElastiCache は Mackerel でモニタリングをしているので,すぐにリリースしてもらえて助かった.

mackerel.io

実際に Mackerel で確認をしてみた.

f:id:kakku22:20180417194157p:plain

まとめ

  • ElastiCache for Redis のメトリクスに EngineCPUUtilization が追加された
  • 今後は vCPU を気にせずにモニタリングすることができる
  • Mackerel AWS Integration でも,既にメトリクスが取得できるようになっている

Amazon Elasticsearch Service で「アクセスポリシー」を即時反映できるようになっていた

Amazon ES (Amazon Elasticsearch Service) で,例えば「アクセス許可 IP」を追加するなど「アクセスポリシー」を変更する場合,クラスタも再構築されてしまうため,待ち時間が長時間化したり,場合によっては再構築がエラーになって,クラスタが死んでしまう場合もあった.Amazon ES を運用している人たちと話すと必ず話題に出るツライ仕様だったし,これまで何度も AWS サポートに改善要望を出していた 😰

最近どうしても「アクセスポリシー」を変更する必要があり,試したところ,数分以内で完了してしまった.今までは Amazon ES の CloudWatch メトリクス Nodes を見ていると,一時的にノード数が2倍にスケールアウトして,徐々にスケールインするという挙動だったのに,その挙動も確認できなかったため,もしかして改善された?と思ったら,本当に改善されていた!

僕はリリースノートを見逃していて,Twitter で教えて頂いた @shinodogg さんに感謝 🎉

インスタントアクセスポリシーアップデート : 2018/03/07 リリース

「インスタントアクセスポリシーアップデート」って,カタカナで書くと名前が長いけど,ようするに Amazon ES の「アクセスポリシー」を変更すると,クラスタを再構築せずに,即時反映できる機能と言える.リリースノートにも書いてある通り,全ての Elasticsearch バージョンで使えるのも良かった.個人的には Amazon ES 関連で,過去最大の神アップデートだと思う❗️

詳細な構成はわからないけど,Amazon ES は Elasticsearch クラスタの前にロードバランサがあるので,ロードバランサのレイヤーで「アクセスポリシー」を反映できるようになった感じ?

www.slideshare.net

まとめ

「インスタントアクセスポリシーアップデート」は Amazon ES 運用者にとって神アップデートなのに,あまり知られていないような気がするので,普及のために記事を書いた.最近は Elasticsearch 6.2 までサポートされていたり,待望だった VPC 対応もリリースされたり,Amazon ES も日々良くなっているので,今後も積極的に使っていく❗️

関連記事

去年に比較的大きめの Elasticsearch クラスタを Amazon ES に移行した事例をまとめた記事もある.

kakakakakku.hatenablog.com

Amazon ES を運用するコツをまとめた記事もある.

kakakakakku.hatenablog.com

AWS で Kubernetes クラスタを構築して学ぶワークショップ「aws-workshop-for-kubernetes」

Kubernetes を学ぶため,AWS から公式に公開されているワークショップ資料「aws-workshop-for-kubernetes」を試した.Kubernetes を学ぶためのコンテンツが網羅的にあるため,今回はワークショップの紹介と,実際に試した一部のコンテンツをまとめたいと思う.既に Kubernetes を詳しく知っている人であれば早く進められるかもしれないけど,Kubernetes 初心者だと,理解しながら進めることになるので,全コンテンツを終えるのはかなりの時間が必要になる気がする.ワークショップ資料は全て GitHub に公開されていて,誤植などがあれば,プルリクエストを送ることもできる.

github.com

なお,ワークショップ資料は AWS Technical Evangelists の「グプタ先生」がメインで作成されていて,それだけでもうモチベーションが上がる!

aws.amazon.com

aws-workshop-for-kubernetes 紹介

「aws-workshop-for-kubernetes」には,大きく3種類の「コース」がある.まずは「Standard」を試して,次に「Developer」か「Operations」に進むようになっている.

ワークショップ資料には計27個の「コンテンツ」があり,「コース」ごとに「コンテンツ」が割り当てられている.一部の「コンテンツ」はどの「コース」にも割り当てられていなかったりもするので,以下に割り当て表を作ってみた.気になる「コンテンツ」だけを試すこともできる.かなり,幅広く Kubernetes を学べるようになっている.

コンテンツ Standard コース Developer コース Operations コース
101: Start Here
102: Create a Kubernetes cluster using kops
103: Introduction to the Kubernetes CLI
201: Monitoring a Kubernetes Cluster
202: Leveraging a Service Mesh
203: Upgrading a Kubernetes Cluster
204: Logging with an EFK Stack
205: Autoscaling a Kubernetes Cluster
206: Deploy Kubernetes with Terraform and CloudFormation
301: Setting up a Local Development Environment
302: Service Discovery for Microservices
303: Updating Applications on Kubernetes
304: Scaling Applications on Kubernetes
305: Tracing Applications with Jaeger and X-Ray
306: Manage Applications with Helm
307: Store Persistent Data with StatefulSets and PVs
308: Cicd Workflows
309: Deploying a Chart Repository
310: Applying Chaos Engineering
401: ConfigMaps and Secrets
402: Authentication, Authorization, and Access
403: Admission Control for Kubernetes on AWS
404: Network Policies
405: Ingress Controllers
406: CoreDNS
501: Best Practices
502: For Further Reading

所要時間と料金

README を読むと,以下のように書いてあったけど,個人的にはもっと時間が掛かると思う(Kubernetes の理解度による).

  • Standard
    • 少なくとも2時間
  • Developer
    • 少なくとも4時間
  • Operations
    • 少なくとも4時間

We recommend at least 2 hours to complete the workshop. We recommend at least 4 hours for each of the extended paths.

さらに Kubernetes クラスタを Multi-Master で構築すると,インスタンス数も増えるため,料金もそこそこになる.README には「1日 $20 以下」と書いてあった.

You will incur charges as you go through these workshop guides as it will exceed the limits of AWS free tier. An estimate of charges (<$20/day) can be seen at this simple monthly calculator

101: Start Here

まず,開発環境として Cloud9 を使うため,CloudFormation で構築をする.東京リージョンでは Cloud9 が使えないため,今回はバージニアリージョンにした.また「新規 VPC」と「既存 VPC」から選べるため,今回は「既存 VPC」を選んだ.スタックを書く必要はなく「Deploy to AWS」を押すだけで,テンプレートが指定された状態で起動する.「サブネット」を指定したら,あとは特に何も指定せず,ポチポチと「次へ」を押せば,Cloud9 にアクセスできるようになる.

f:id:kakku22:20180402205107p:plain

次に,Cloud9 のターミナルで以下のスクリプトを実行する.

$ aws s3 cp s3://aws-kubernetes-artifacts/lab-ide-build.sh . && \
chmod +x lab-ide-build.sh && \
. ./lab-ide-build.sh

実行すると kubectl / kops をインストールすることができる.例えば kubectl だと以下のように確認できる.まだ Kubernetes クラスタを構築していないので kubectl get nodes がエラーになるのは問題なし.

$ which kubectl
/usr/local/bin/kubectl
$ kubectl get nodes
The connection to the server localhost:8080 was refused - did you specify the right host or port?

102: Create a Kubernetes cluster using kops

次に Kubernetes クラスタを管理するためのツール kops を使って,Kubernetes クラスタを構築する.なお,今回はクラスタ名の接尾辞を example.cluster.k8s.local にする.

github.com

Kubernetes クラスタの構成には,以下の2種類がある.例えば「ローリングアップデート」など,一部の機能に制約があるため,ワークショップでは「Multi-Master Cluster」で構築することが推奨になっていた.

  • Single-Master Cluster
  • Multi-Master Cluster

kops でクラスタを構築するときの $AWS_AVAILABILITY_ZONES には,リージョンごとの AZ を設定している.

$ echo $AWS_AVAILABILITY_ZONES
us-east-1a,us-east-1b,us-east-1c,us-east-1d,us-east-1e,us-east-1f

次に kops で「Multi-Master Cluster」を構築する.今回は3台のマスターノードと5台のワーカーノードにした.

$ kops create cluster \
  --name example.cluster.k8s.local \
  --master-count 3 \
  --node-count 5 \
  --zones $AWS_AVAILABILITY_ZONES \
  --yes

すると,構築が開始されて kops validate cluster で,状況を確認することができる.全ノード Ready になると,以下のような結果になる.AZ もキレイに分散されている.

$ kops validate cluster
Using cluster from kubectl context: example.cluster.k8s.local

Validating cluster example.cluster.k8s.local

INSTANCE GROUPS
NAME                    ROLE    MACHINETYPE     MIN     MAX     SUBNETS
master-us-east-1a       Master  m3.medium       1       1       us-east-1a
master-us-east-1b       Master  m3.medium       1       1       us-east-1b
master-us-east-1c       Master  c4.large        1       1       us-east-1c
nodes                   Node    t2.medium       5       5       us-east-1a,us-east-1b,us-east-1c,us-east-1d,us-east-1e,us-east-1f

NODE STATUS
NAME                            ROLE    READY
ip-172-20-126-120.ec2.internal  node    True
ip-172-20-127-95.ec2.internal   master  True
ip-172-20-154-201.ec2.internal  node    True
ip-172-20-187-147.ec2.internal  node    True
ip-172-20-206-67.ec2.internal   node    True
ip-172-20-48-37.ec2.internal    node    True
ip-172-20-52-159.ec2.internal   master  True
ip-172-20-76-97.ec2.internal    master  True

Pod Failures in kube-system
NAME
kube-dns-7f56f9f8c7-qxxbd

Validation Failed
Ready Master(s) 3 out of 3.
Ready Node(s) 5 out of 5.

your kube-system pods are NOT healthy example.cluster.k8s.local

構築後にコンテキストを確認した.

$ kubectl config get-contexts
CURRENT   NAME                        CLUSTER                     AUTHINFO                    NAMESPACE
*         example.cluster.k8s.local   example.cluster.k8s.local   example.cluster.k8s.local 

$ kubectl config current-context
example.cluster.k8s.local

103: Introduction to the Kubernetes CLI

103 では,kubectl を使って,Kubernetes の基本的なコンセプトを学んだ.

kubectl get nodes

まずは kubectl get nodes で,今回は Multi-Master でクラスタを構築したため,3台のマスターノードと5台のワーカーノードを確認することができた.

$ kubectl get nodes
NAME                             STATUS    ROLES     AGE       VERSION
ip-172-20-126-120.ec2.internal   Ready     node      7m        v1.8.7
ip-172-20-127-95.ec2.internal    Ready     master    8m        v1.8.7
ip-172-20-154-201.ec2.internal   Ready     node      7m        v1.8.7
ip-172-20-187-147.ec2.internal   Ready     node      7m        v1.8.7
ip-172-20-206-67.ec2.internal    Ready     node      7m        v1.8.7
ip-172-20-48-37.ec2.internal     Ready     node      7m        v1.8.7
ip-172-20-52-159.ec2.internal    Ready     master    8m        v1.8.7
ip-172-20-76-97.ec2.internal     Ready     master    6m        v1.8.7

次に Kubernetes クラスタの中に nginx のポッドを起動する.ポッドだけではなく,デプロイメントも確認することができた.

$ kubectl run nginx --image=nginx
deployment.apps "nginx" created

$ kubectl get deployments
NAME      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx     1         1         1            1           10s

$ kubectl get pods
NAME                    READY     STATUS    RESTARTS   AGE
nginx-7c87f569d-vwxjw   1/1       Running   0          30s

さらに docker exec のように kubectl exec でポッドの中に入ることもできた.最後は kubectl delete でデプロイメントごと削除をした.

$ kubectl exec -it nginx-7c87f569d-vwxjw /bin/bash
root@nginx-7c87f569d-vwxjw:/# ls -al /etc/nginx/conf.d/default.conf 
-rw-r--r-- 2 root root 1093 Mar 20 10:03 /etc/nginx/conf.d/default.conf
root@nginx-7c87f569d-vwxjw:/# exit

$ kubectl delete deployment/nginx
deployment.extensions "nginx" deleted

他にも

  • ポッド作成
  • デプロイメント作成
  • サービス作成

なども試した.デーモンセット,ジョブあたりは,今回は割愛した.

201: Monitoring a Kubernetes Cluster

次は Kubernetes のモニタリングを3種類学んだ.

  • Kubernetes Dashboard
  • Heapster, InfluxDB and Grafana
  • Prometheus, Node exporter and Grafana

まずは Kubernetes Dashboard をインストールした.

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommended/kubernetes-dashboard.yaml
secret "kubernetes-dashboard-certs" created
serviceaccount "kubernetes-dashboard" created
role.rbac.authorization.k8s.io "kubernetes-dashboard-minimal" created
rolebinding.rbac.authorization.k8s.io "kubernetes-dashboard-minimal" created

deployment.apps "kubernetes-dashboard" created
service "kubernetes-dashboard" created

次に Cloud9 で Kubernetes Dashboard を起動すると,ターミナルが待機状態になるので,プロキシの URL にアクセスする.認証ではトークンが必要になるため kubectlsecret を取得する.

$ kubectl proxy --address 0.0.0.0 --accept-hosts '.*' --port 8080

# https://ENVIRONMENT_ID.vfs.cloud9.REGION_ID.amazonaws.com/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/ にアクセスする

$ kubectl -n kube-system get secret
$ kubectl -n kube-system describe secret default-token-9znml  

すると,Kubernetes Dashboard にアクセスすることができて,ノード一覧などを確認することができた.

f:id:kakku22:20180402205259p:plain

f:id:kakku22:20180402205311p:plain

Heapster は今回は試さず,Kubernetes のモニタリングで導入事例もよく聞く Prometheus + Grafana を試した.ここはコンテンツの通りに進めることができた.

202: Leveraging a Service Mesh

次は Kubernetes で,サービスメッシュを実現するために,2種類のサービスを試した.

  • Linkerd
  • Istio

Linkerd

まず,Linkerd をインストールした.

$ kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/linkerd.yml
configmap "l5d-config" created
daemonset.extensions "l5d" created
service "l5d" created

$ kubectl get pods
NAME        READY     STATUS    RESTARTS   AGE
l5d-bd6w4   2/2       Running   0          28s
l5d-l47gd   2/2       Running   0          28s
l5d-ldhxd   2/2       Running   0          28s
l5d-t6c2k   2/2       Running   0          28s
l5d-vrhm7   2/2       Running   0          28s

$ kubectl get svc
NAME         TYPE           CLUSTER-IP      EXTERNAL-IP        PORT(S)                                        AGE
kubernetes   ClusterIP      100.64.0.1      <none>             443/TCP                                        32m
l5d          LoadBalancer   100.65.92.151   a2a9d866b34c4...   4140:31859/TCP,4141:32072/TCP,9990:30369/TCP   48s

$ LINKERD_ELB=$(kubectl get svc l5d -o jsonpath="{.status.loadBalancer.ingress[0].*}")
$ echo http://$LINKERD_ELB:9990

# URL にアクセスをする

次に,Linkerd のデモとして,2種類のマイクロサービス helloworld を起動し,お互いにリクエストを飛ばしてみた.

$ kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/hello-world.yml
replicationcontroller "hello" created
service "hello" created
replicationcontroller "world-v1" created
service "world-v1" created

$ http_proxy=$LINKERD_ELB:4140 curl -s http://hello
Hello (100.96.3.5) world (100.96.3.6)!!

すると,マイクロサービス間のリクエストを Linkerd でモニタリングすることができた.

f:id:kakku22:20180402212846p:plain

Istio

次に Istio で,同じく kubectl apply でインストールをした.

$ curl -L https://git.io/getLatestIstio | sh -
$ cd istio-0.6.0

$ istioctl version
Version: 0.6.0
GitRevision: 2cb09cdf040a8573330a127947b11e5082619895
User: root@a28f609ab931
Hub: docker.io/istio
GolangVersion: go1.9
BuildStatus: Clean

$ kubectl apply -f install/kubernetes/istio.yaml

$ kubectl get all --namespace istio-system

NAME                             READY     STATUS              RESTARTS   AGE
istio-ca-cd9dfbdbb-vc8mb         1/1       Running             0          11s
istio-ingress-84c7ddcb7f-g9kmb   0/1       ContainerCreating   0          12s
istio-mixer-67d9bd59cb-8swld     0/3       ContainerCreating   0          16s
istio-pilot-5dd75b8f7f-qfp22     0/2       ContainerCreating   0          13s

NAME            TYPE           CLUSTER-IP       EXTERNAL-IP        PORT(S)                                                            AGE
istio-ingress   LoadBalancer   100.66.156.34    a858a858a34c5...   80:32168/TCP,443:31401/TCP                                         13s
istio-mixer     ClusterIP      100.69.49.254    <none>             9091/TCP,15004/TCP,9093/TCP,9094/TCP,9102/TCP,9125/UDP,42422/TCP   16s
istio-pilot     ClusterIP      100.68.195.148   <none>             15003/TCP,8080/TCP,9093/TCP,443/TCP                                13s

NAME            DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
istio-ca        1         1         1            1           12s
istio-ingress   1         1         1            0           12s
istio-mixer     1         1         1            0           16s
istio-pilot     1         1         1            0           13s

NAME                       DESIRED   CURRENT   READY     AGE
istio-ca-cd9dfbdbb         1         1         1         12s
istio-ingress-84c7ddcb7f   1         1         0         12s
istio-mixer-67d9bd59cb     1         1         0         16s
istio-pilot-5dd75b8f7f     1         1         0         13s

NAME            DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
istio-ca        1         1         1            1           12s
istio-ingress   1         1         1            0           12s
istio-mixer     1         1         1            0           16s
istio-pilot     1         1         1            0           13s

NAME                       DESIRED   CURRENT   READY     AGE
istio-ca-cd9dfbdbb         1         1         1         12s
istio-ingress-84c7ddcb7f   1         1         0         12s
istio-mixer-67d9bd59cb     1         1         0         16s
istio-pilot-5dd75b8f7f     1         1         0         13s

次に,書籍のレビューを管理するサンプルアプリを起動し,Ingress のエンドポイントにアクセスをする.

$ kubectl apply -f <(istioctl kube-inject -f samples/bookinfo/kube/bookinfo.yaml)
service "details" created
deployment.extensions "details-v1" created
service "ratings" created
deployment.extensions "ratings-v1" created
service "reviews" created
deployment.extensions "reviews-v1" created
deployment.extensions "reviews-v2" created
deployment.extensions "reviews-v3" created
service "productpage" created
deployment.extensions "productpage-v1" created
ingress.extensions "gateway" created

$ ISTIO_INGRESS=$(kubectl get ingress gateway -o jsonpath="{.status.loadBalancer.ingress[0].*}")
echo http://$ISTIO_INGRESS/productpage

# URL にアクセスをする

マイクロサービスに,星付きのレビュー(v3)と星なしのレビュー(v1)があり,Envoy で加重ルーティングをしている.よって,リクエストを繰り返すと,星の有無が変わるというデモを試すことができた.

$ kubectl create -f samples/bookinfo/kube/route-rule-all-v1.yaml
routerule.config.istio.io "productpage-default" created
routerule.config.istio.io "reviews-default" created
routerule.config.istio.io "ratings-default" created
routerule.config.istio.io "details-default" created

$ kubectl replace -f samples/bookinfo/kube/route-rule-reviews-50-v3.yaml
routerule.config.istio.io "reviews-default" replaced

f:id:kakku22:20180402205504p:plain

試し終わったら

Kubernetes クラスターを削除しないと,特に Multi-Master の場合はインスタンスが多く起動しているため,予想以上に料金が発生してしまう.よって,試し終わったら,必ず削除する.削除も kops でできる.

$ kops get cluster
NAME                            CLOUD   ZONES
example.cluster.k8s.local       aws     us-east-1a,us-east-1b,us-east-1c,us-east-1d,us-east-1e,us-east-1f

$ kops delete cluster example.cluster.k8s.local --yes

まとめ

  • 「aws-workshop-for-kubernetes」を試した
  • 計27個の「コンテンツ」があり,充実しているので,Kubernetes 初心者じゃなくても楽しめる
  • 大きく3種類の「コース」があるのも良かった
  • 今回は「Standard コース」の途中までを試した

合わせて読む

もう少し Kubernetes の知識を増やしてからワークショップを試した方が理解が深まりそうなので,以下の2冊を購入した.さっそく読んでみて,読み終わったら,もう1度ワークショップを再開する予定.

入門 Kubernetes

入門 Kubernetes

  • 作者: Kelsey Hightower,Brendan Burns,Joe Beda,松浦隼人
  • 出版社/メーカー: オライリージャパン
  • 発売日: 2018/03/22
  • メディア: 単行本(ソフトカバー)
  • この商品を含むブログを見る

コンテナ・ベース・オーケストレーション Docker/Kubernetesで作るクラウド時代のシステム基盤

コンテナ・ベース・オーケストレーション Docker/Kubernetesで作るクラウド時代のシステム基盤

  • 作者: 橋本直哉,須江信洋,前佛雅人,境川章一郎,佐藤聖規,山田修司,青山尚暉,市川豊,平岡大祐,福田潔,矢野哲朗
  • 出版社/メーカー: 翔泳社
  • 発売日: 2018/03/15
  • メディア: 単行本(ソフトカバー)
  • この商品を含むブログを見る

AWS re:Invent 2017 : Mastering Kubernetes on AWS (CON308)

去年の re:Invent 2017 でグプタ先生の講演動画が公開されている.Kubernetes の構築(Minikube / Kops / EKS),Kubernetes における継続的デリバリー,IAM 管理,ロギングなど,多岐にわたる話が聞けてすごく良かった.グプタ先生が熱血すぎて英語が早すぎるけど(笑)講演の最後に「aws-workshop-for-kubernetes」の紹介も入っていて,どんな目的でワークショップ資料を作ったのか?などを聞くことができる.

www.youtube.com

Lambda / Kinesis / DynamoDB / X-Ray などを組み合わせた実装を学べる「サーバーレスアプリケーション開発ガイド」を読んだ

今月発売されたばかりの「サーバーレスアプリケーション開発ガイド」を読んだので,書評をまとめたいと思う.著者の西谷さん,献本ありがとうございます!

Amazon Web Servicesを使ったサーバーレスアプリケーション開発ガイド

Amazon Web Servicesを使ったサーバーレスアプリケーション開発ガイド

  • 作者:西谷 圭介
  • 発売日: 2018/03/16
  • メディア: 単行本(ソフトカバー)

なお,サポートページからソースコードをダウンロードできる.コマンドもソースコードもそこそこ量があるため,写経せずに試したいという人はダウンロードして使うと良いかと.

book.mynavi.jp

概要

「サーバレスとは何か?」という解説からはじまり,実際に数種類の「サーバレスアプリケーション」を実装しながら理解を深めていく流れになっている.特に,多くの AWS サービスを組み合わせて学べる点が素晴らしく,例えば X-Ray などは,僕もまだ試したことがなかったので,今回学ぶことができた.実装する「サーバレスアプリケーション」ごとに,組み合わせる AWS サービスをザッと挙げる.こんなにある!

  • Amazon CloudWatch のアラームをトリガーに自動処理をする
    • Kinesis
    • CloudWatch
    • SNS
    • Lambda
  • Web サイトの状態を定期的にチェックする
    • Lambda
    • CloudWatch Events
  • Amazon Kinesis を使って Twitter のデータを受け取る
    • EC2
    • Kinesis
    • Lambda
    • DynamoDB
  • 写真投稿サイト
    • API Gateway
    • Lambda
    • DynamoDB
    • Rekognition
    • S3
    • Cognito
    • CloudFormation
    • Serverless Application Model (AWS SAM)
  • デリバリプロセスの自動化
    • CloudFormation
    • Serverless Application Model (AWS SAM)
    • CodeBuild
    • CodePipeline
  • トラブルシューティング
    • CloudWatch
    • CloudWatch Logs
    • X-Ray

本書の特徴は「ほぼ全てのオペレーションを AWS CLI で行う」という点だと思う.管理コンソールのデザインが変わっても AWS CLI のオペレーションは大幅に変わらないというメリットがあるし,オペレーションを積極的に Infrastructure as Code にするという意味でも AWS CLI をベースに学べるのはメリットだと思う.ただし,管理コンソールを意識しなくなるため,ちょっとでも気を抜くと「今,何をしてるんだっけ?」と方向性を見失ってしまう場面があった.このあたりはトレードオフだし,西谷さんのブログ記事にも意図が詳細に書かれている.

keisuke69.hatenablog.jp

Kinesis リシャーディング

まず「Amazon CloudWatch のアラームをトリガーに自動処理をする」を実際に試してみた.アーキテクチャは以下のようになっていて,Kinesis のデータストリームに閾値以上のレコードが登録された場合に,自動的にリシャーディングを行う.

f:id:kakku22:20180326204618p:plain

Kinesis にレコードを登録するために,以下の put-records.py を使った(データストリーム名は sample となる).AWS CLI は量が多くなってしまうため,本書を読んでもらえればと!

import boto3
import datetime
import time
import uuid

kinesis = boto3.client('kinesis')
stream_name = 'sample'

partition_key = str(uuid.uuid4())
data = datetime.datetime.utcnow().strftime('%s')

for i in range(15):
    kinesis.put_record(
        StreamName=stream_name,
        Data=data,
        PartitionKey=partition_key,
    )

作成した Lambda 関数の構成は,以下のようになっている.

f:id:kakku22:20180326204947p:plain

実際にリシャーディングを行った結果が以下となる.ちゃんと OpenShardCount の値が 1 → 2 に変わっている.

# Before
$ aws kinesis describe-stream-summary --stream-name sample
{
    "StreamDescriptionSummary": {
        "OpenShardCount": 1,
        "EncryptionType": "NONE",
        "StreamStatus": "ACTIVE",
        "StreamName": "sample",
        "StreamARN": "arn:aws:kinesis:ap-northeast-1:111111111111:stream/sample",
        "EnhancedMonitoring": [
            {
                "ShardLevelMetrics": []
            }
        ],
        "StreamCreationTimestamp": 1521993626.0,
        "RetentionPeriodHours": 24
    }
}

# Put
$ python put-records.py

# After
$ aws kinesis describe-stream-summary --stream-name sample
{
    "StreamDescriptionSummary": {
        "OpenShardCount": 2,
        "EncryptionType": "NONE",
        "StreamStatus": "ACTIVE",
        "StreamName": "sample",
        "StreamARN": "arn:aws:kinesis:ap-northeast-1:111111111111:stream/sample",
        "EnhancedMonitoring": [
            {
                "ShardLevelMetrics": []
            }
        ],
        "StreamCreationTimestamp": 1521993626.0,
        "RetentionPeriodHours": 24
    }
}

X-Ray

トラブルシューティングの事例として紹介されている X-Ray も実際に試してみた.設定は特に難しくなく,Lambda のトレースモードを有効にして,あとは X-Ray の結果を見るだけだった.X-Ray は今まで使ったことがなかったので,実際に処理内部のトレース結果が見れて良かった.

$ aws lambda update-function-configuration \
--function-name s3-get-object --tracing-config Mode=Active

f:id:kakku22:20180326205003p:plain

まとめ

  • 「サーバーレスアプリケーション開発ガイド」を読んだ
  • AWS サービスを組み合わせて数種類のアプリケーションを実装できた
  • Lambda だけじゃなく Kinesis / DynamoDB / AWS SAM などに興味があるなら読むべき
  • 本書のメインコンテンツとも言える「写真投稿サイト」は Vue.js で実装されていてフロントエンドの勉強にもなった
    • 途中まで写経してたけど,量が多くて,途中からソースコードをダウンロードして進めた

関連記事

去年に読んだ「サーバーレスシングルページアプリケーション」と似ている部分も多かった.ただし,フロントエンドは jQuery → Vue.js になっているし,組み合わせる AWS サービスも多いし,今から読むなら「サーバーレスアプリケーション開発ガイド」かなぁーと.

kakakakakku.hatenablog.com

同じく去年に読んだ「実践 AWS Lambda」も関連書籍と言える.もし AWS CLI メインで改版されるなら,もう1度読む!

kakakakakku.hatenablog.com

CircleCI 2.0 の「ワークフロー機能」を学べる公式デモ用リポジトリ circleci-demo-workflows

前回の記事に続き,CircleCI 2.0 の調査をしている.今回は CircleCI から公式に提供されている「ワークフローデモ用リポジトリ」を活用して,CircleCI 2.0 の新機能である「ワークフロー機能」の仕組みと,設定ファイルのポイントを学んだ.「ワークフローデモ用リポジトリ」では,以下の4種類(+1種類)のデモがある.

  • Parallel Jobs
  • Sequential Job / Branch-Level
  • Fan-in / Fan-out
  • Workspace Forwarding
  • Schedule

github.com

Parallel Jobs

CircleCI 2.0 の「ワークフロー機能」では,複数のジョブを並列に実行することができる(デフォルトで並列に実行される).デモでは,3種類の異なる Ruby バージョンで並列にテストを実行しているため,CI の実行時間を短縮することができる.CI の実行時間が伸びるとツライため,並列に実行できるのは素晴らしい!

workflows:
  version: 2
  build:
    jobs:
      - "ruby-2.2"
      - "ruby-2.3"
      - "ruby-2.4"

f:id:kakku22:20180322024726p:plain

Sequential Job

並列に実行できるのは素晴らしいけど,意図的に直列に実行したいという場合も多くある.そんなときは requires を使う.デモでは build ジョブを実行した後に deploy ジョブを実行するようになっている.また,ジョブに対して実行するブランチを制限する filters も使われていて,参考になる.

workflows:
  version: 2
  build-and-deploy:
    jobs:
      - build
      - deploy:
          requires:
            - build
          filters:
            branches:
              only: sequential-branch-filter

さらに,デモでは .circleci/setup-heroku.sh が用意されていて config.yml から以下のように呼び出されている.このあたりのテクニックは CircleCI 1.0 と同じだけど,できる限り config.yml の設定を薄く維持するというのは今後も意識したいと思う.

jobs:
  (中略)
  deploy:
    (中略)
    steps:
      - checkout
      - run:
          name: Setup Heroku
          command: bash .circleci/setup-heroku.sh

f:id:kakku22:20180322024740p:plain

Fan-in / Fan-out

Fan-in と Fan-out は,一言で言えば「集約」のことで,ジョブパイプラインのようにジョブを直列に実行したり,並列に実行したり,複数のジョブの完了を待機することができる.ただし,これは既に紹介した requires を使うだけで,専用の機能があるわけではなかった.設定ファイルだけだと読みにくいけど,ワークフロー図を見れば,意図した通りに構成できているかはすぐにわかる.

workflows:
  version: 2
  build-and-deploy:
    jobs:
      - checkout_code
      - bundle_dependencies:
          requires:
            - checkout_code
      - rake_test:
          requires:
            - bundle_dependencies
      - precompile_assets:
          requires:
            - bundle_dependencies
      - deploy:
          requires:
            - rake_test
            - precompile_assets

f:id:kakku22:20180322024756p:plain

Workspace Forwarding

CircleCI 2.0 の「ワークフロー機能」では,ジョブごとに独立したコンテナで実行されるため,一時ファイルなどを共有する場合,ジョブで作成したファイルをワークフローのワークスペースに保存し,他のジョブでマウントする必要がある.この機能は非常に便利だし,逆に知らないとワークフローの設定で苦労しそう.

設定としては2種類あり,まず attach_workspace でワークフローのワークスペースをコンテナにマウントすることができる.次に persist_to_workspace でワークフローのワークスペースにファイルを永続化する.なお,ワークフローのワークスペースにあるファイルを削除することはできず,あくまで追加だけとなる.また,CircleCI を使うなら,以下の3種類のデータの違いを理解しておく必要があるとドキュメントに書いてあった.

  • Artifacts
  • Workspaces
  • Caches

circleci.com

version: 2.0

jobs:
  bundle_dependencies:
    docker:
      - image: circleci/ruby:2.4-node
      - image: circleci/postgres:9.4.12-alpine
    working_directory: ~/circleci-demo-workflows
    steps:
      - checkout
      - attach_workspace:
          at: ~/circleci-demo-workflows
      - restore_cache:
          keys:
            - v1-bundle-{{ checksum "Gemfile.lock" }}
      - run: bundle install --path vendor/bundle
      - save_cache:
          key: v1-bundle-{{ checksum "Gemfile.lock" }}
          paths:
            - ~/circleci-demo-workflows/vendor/bundle
      - persist_to_workspace:
          root: .
          paths: vendor/bundle

  rake_test:
    docker:
      - image: circleci/ruby:2.4-node
      - image: circleci/postgres:9.4.12-alpine
    working_directory: ~/circleci-demo-workflows
    steps:
      - checkout
      - attach_workspace:
          at: ~/circleci-demo-workflows
      - run: bundle --path vendor/bundle
      - run: bundle exec rake db:create db:schema:load
      - run:
          name: Run tests
          command: bundle exec rake
(中略)

f:id:kakku22:20180322024901p:plain

Schedule

GitHub の README.md には書かれていなかったけど,ブランチ一覧を見てみたところ「スケジュール実行」のデモも用意されていた.CircleCI 2.0 では schedule で cron 形式のジョブ実行ができる.よって,全ての git push に hook するのではなく,深夜に1回実行するジョブ(例えば)を作ることができる.この機能を知らない人が結構いる気がして,知っておくと CI の幅が広がるのでオススメ!

workflows:
  version: 2
  commit-workflow:
    jobs:
      - build 
  scheduled-workflow:
    triggers:
      - schedule:
          cron: "0 1 * * *"
          filters:
            branches:
              only: try-schedule-workflow

f:id:kakku22:20180322024914p:plain

関連記事

CircleCI 1.0 の設定ファイルを CircleCI 2.0 にマイグレーションをする「config-translation API」の紹介を前に書いた.

kakakakakku.hatenablog.com