Blogaomu

WEBアプリケーション開発とその周辺のメモをゆるふわに書いていきます。

ALB で gRPC を利用する on EKS

先日、Application Load Balancer (ALB)が HTTP/2 および gRPC に対応するようになったという発表がありました。これをEKS上で稼働するアプリケーションにも適用できるかを試してみました。

ALB の HTTP/2 および gRPC 対応

EKS で ALB を利用するには?

想定構成

f:id:TAKAyuki_atkwsk:20201214103446p:plain

作成手順

$ eksctl utils associate-iam-oidc-provider \
  --region ap-northeast-1 \
  --cluster floral-mongoose-1607656608 \
  --approve
 []  eksctl version 0.32.0
 []  using region ap-northeast-1
 []  will create IAM Open ID Connect provider for cluster "floral-mongoose-1607656608" in "ap-northeast-1"
 []  created IAM Open ID Connect provider for cluster "floral-mongoose-1607656608" in "ap-northeast-1"
 
# AWS Load Balancer Controller 用 IAM Policy の作成
$ curl -o iam-policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.1.0/docs/install/iam_policy.json
 
$ aws iam create-policy \
     --policy-name AWSLoadBalancerControllerIAMPolicy \
     --policy-document file://iam-policy.json
 {
     "Policy": {
         "PolicyName": "AWSLoadBalancerControllerIAMPolicy",
         "PolicyId": "ANPA3TVC4QV7DOBMICOZQ",
         "Arn": "arn:aws:iam::accoundid:policy/AWSLoadBalancerControllerIAMPolicy",
         "Path": "/",
         "DefaultVersionId": "v1",
         "AttachmentCount": 0,
         "PermissionsBoundaryUsageCount": 0,
         "IsAttachable": true,
         "CreateDate": "2020-12-11T03:40:45+00:00",
         "UpdateDate": "2020-12-11T03:40:45+00:00"
     }
 }

# 先ほど作成した IAM Policy にひもづける ServiceAccount を作成
$ eksctl create iamserviceaccount \
  --cluster=floral-mongoose-1607656608 \
  --namespace=kube-system \
  --name=aws-load-balancer-controller \
  --attach-policy-arn=arn:aws:iam::accountid:policy/AWSLoadBalancerControllerIAMPolicy \
  --approve
 []  eksctl version 0.32.0
 []  using region ap-northeast-1
 []  1 existing iamserviceaccount(s) (kube-system/aws-node) will be excluded
 []  1 iamserviceaccount (kube-system/aws-load-balancer-controller) was included (based on the include/exclude rules)
 []  1 iamserviceaccount (kube-system/aws-node) was excluded (based on the include/exclude rules)
 [!]  serviceaccounts that exists in Kubernetes will be excluded, use --override-existing-serviceaccounts to override
 []  1 task: { 2 sequential sub-tasks: { create IAM role for serviceaccount "kube-system/aws-load-balancer-controller", create serviceaccount "kube-system/aws-load-balancer-controller" } }
 []  building iamserviceaccount stack "eksctl-floral-mongoose-1607656608-addon-iamserviceaccount-kube-system-aws-load-balancer-controller"
 []  deploying stack "eksctl-floral-mongoose-1607656608-addon-iamserviceaccount-kube-system-aws-load-balancer-controller"
 []  created serviceaccount "kube-system/aws-load-balancer-controller"
 
# Controller をクラスターにインストール
$ helm repo add eks https://aws.github.io/eks-charts
 "eks" has been added to your repositories
 
$ kubectl apply -k "github.com/aws/eks-charts/stable/aws-load-balancer-controller//crds?ref=master"
 customresourcedefinition.apiextensions.k8s.io/targetgroupbindings.elbv2.k8s.aws created
 
# helm install eks/aws-load-balancer-controller だと上手くいかなかった...
# see https://github.com/aws/eks-charts/tree/master/stable/aws-load-balancer-controller
$ helm upgrade \
    -i aws-load-balancer-controller \
    eks/aws-load-balancer-controller \
    -n kube-system \
    --set clusterName=floral-mongoose-1607656608 \
    --set serviceAccount.create=false \
    --set serviceAccount.name=aws-load-balancer-controller
 Release "aws-load-balancer-controller" does not exist. Installing it now.
 NAME: aws-load-balancer-controller
 LAST DEPLOYED: Fri Dec 11 12:52:57 2020
 NAMESPACE: kube-system
 STATUS: deployed
 REVISION: 1
 TEST SUITE: None
 NOTES:
 AWS Load Balancer controller installed!
# --validation-method は DNS も選べるが、今回は都合によりeメール認証を選んだ
# この ARN を後ほど使うのでコピーしておく
$ aws acm request-certificate --domain-name albgrpcsample.niboshino-tech.net --validation-method EMAIL
 {
     "CertificateArn": "arn:aws:acm:ap-northeast-1:accountid:certificate/f49ed98b-935e-4adc-ab82-b7f35c293f9c"
 }
  • manifest作成、適用
# helloworld.yml
apiVersion: v1
kind: Service
metadata:
  name: helloworld
spec:
  selector:
    app: helloworld
  ports:
    - port: 50051
      targetPort: 50051
  type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: helloworld
spec:
  selector:
    matchLabels:
      app: helloworld
  template:
    metadata:
      labels:
        app: helloworld
    spec:
      containers:
        - name: helloworld
          image: accountid.dkr.ecr.ap-northeast-1.amazonaws.com/albgrpcsample/helloworld:v0.0.1
          resources:
            limits:
              memory: "128Mi"
              cpu: "500m"
          ports:
            - containerPort: 50051
# routeguide.yml
apiVersion: v1
kind: Service
metadata:
  name: routeguide
spec:
  selector:
    app: routeguide
  ports:
    - port: 10000
      targetPort: 10000
  type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: routeguide
spec:
  selector:
    matchLabels:
      app: routeguide
  template:
    metadata:
      labels:
        app: routeguide
    spec:
      containers:
        - name: routeguide
          image: accountid.dkr.ecr.ap-northeast-1.amazonaws.com/albgrpcsample/route_guide:v0.0.1
          resources:
            limits:
              memory: "128Mi"
              cpu: "500m"
          ports:
            - containerPort: 10000
# alb-grpc-sample-ingress.yml
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: alb-grpc-sample
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/backend-protocol-version: GRPC
    # このアノテーションがあることでリスナープロトコルのデフォルトが HTTPS (443) になる
    # see https://kubernetes-sigs.github.io/aws-load-balancer-controller/latest/guide/ingress/annotations/#listen-ports
    alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:ap-northeast-1:accountid:certificate/f49ed98b-935e-4adc-ab82-b7f35c293f9c
spec:
  rules:
    - http:
        paths:
          - backend:
              serviceName: helloworld
              servicePort: 50051
            path: /helloworld.Greeter/*
          - backend:
              serviceName: routeguide
              servicePort: 10000
            path: /routeguide.RouteGuide/*
  • これらを適用したところ ALB が作成された

f:id:TAKAyuki_atkwsk:20201213102923p:plain f:id:TAKAyuki_atkwsk:20201213103015p:plain f:id:TAKAyuki_atkwsk:20201213103026p:plain f:id:TAKAyuki_atkwsk:20201213103003p:plain

  • 動作確認
    • ドメインの管理が Route53 以外で行われているので /etc/hosts を編集して確認した
    • 正常にレスポンスが返ってくることを確認できた
# /etc/hostsを書き換えるため、ALBのIPアドレスを取得
$ dig k8s-default-albgrpcs-5fb02487bb-383351884.ap-northeast-1.elb.amazonaws.com +short
 
 52.198.135.63
 18.182.181.161
 13.230.14.197
 
$ sudo vi /etc/hosts
 # 以下追加
 52.198.135.63 albgrpcsample.niboshino-tech.net
 
$ grpcurl -d '{"name": "foo"}' -proto helloworld/helloworld/helloworld.proto albgrpcsample.niboshino-tech.net:443 helloworld.Greeter/SayHello
 {
   "message": "Hello foo"
 }
 
$ grpcurl -d '{"latitude": 407838351, "longitude": -746143763}' -proto route_guide/routeguide/route_guide.proto albgrpcsample.niboshino-tech.net:443 routeguide.RouteGuide/GetFeature
 {
   "name": "Patriots Path, Mendham, NJ 07945, USA",
   "location": {
     "latitude": 407838351,
     "longitude": -746143763
   }
 }

まとめ

AWS Load Balancer Controller をインストールして Ingress に特定の annotation を追加したものを適用すると ALB が作成されることが分かりました。Ingress で指定したパスごとにターゲットグループが対応しているので理解しやすく感じました。EKS で gRPC を利用するシステムにおいてルーティングや負荷分散を担う要素として選択肢の一つになりそうです。

ExternalDNS の policy を軽く調べたメモ

AWS の EKS 上で ExternalDNS を利用する際に policy という概念が分からなかったので、動かしながら簡単に調べてみたメモです。

policyって?

https://github.com/kubernetes-sigs/external-dns/blob/master/pkg/apis/externaldns/types.go#L410

Modify how DNS records are synchronized between sources and providers

  • マニフェストファイルで定義されるものとDNSプロバイダー間でDNSレコードがどのように同期が取られるかというのを設定する
  • sync, upsert-only, create-only の3種類のうちどれか
    • 鋭い方ならこの時点である程度想像付くかと思う

AWS Route53と連携する場合

こちらを参照。 https://github.com/kubernetes-sigs/external-dns/blob/master/docs/tutorials/aws.md#deploy-externaldns

  • ExternalDNSの引数として --policy=upsert-only が例示されている

would prevent ExternalDNS from deleting any records, omit to enable full synchronization

  • またこの引数のコメントとして、(upsert-onlyは)レコードを削除するのを防ぐ、完全な同期を行う場合は(引数を)省略する、ということを言っている
  • 読んで一瞬分からなかったため動かしながら確かめたという経緯

それぞれのpolicyによる働き

  • 動作を確認するために、DNSレコード作成→変更→削除という流れを想定した操作を行った
    • Serivce(type: LoadBalancer)を2つ用意する
    • 1つ目のサービスにアノテーションを付与する(=レコードが作成される想定)
    • 1つ目のサービスからアノテーションを削除し、2つ目のサービスにアノテーションを付与する(=レコードの値が置き換わる想定)
    • 2つ目のサービスからアノテーションを削除する(=レコードが削除される想定)

事前準備

話に関わる部分だけ掻い摘んで紹介。基本的には external-dns/aws.md at master · kubernetes-sigs/external-dns · GitHub で紹介されている方法で行った。

external-dns-test.niboshino-tech.net. という hosted zone を作成。

$ aws route53 create-hosted-zone --name "external-dns-test.niboshino-tech.net." --caller-reference "external-dns-test-$(date +%s)"
 {
     "Location": "https://route53.amazonaws.com/2013-04-01/hostedzone/Z0608323LFWKCVBOP5JV",
     "HostedZone": {
         "Id": "/hostedzone/Z0608323LFWKCVBOP5JV",
         "Name": "external-dns-test.niboshino-tech.net.",
         "CallerReference": "external-dns-test-1606996869",
         "Config": {
             "PrivateZone": false
         },
         "ResourceRecordSetCount": 2
     },
     "ChangeInfo": {
         "Id": "/change/C067512728AL1CJFU0BF9",
         "Status": "PENDING",
         "SubmittedAt": "2020-12-03T12:01:11.058000+00:00"
     },
     "DelegationSet": {
         "NameServers": [
             "ns-131.awsdns-16.com",
             "ns-1855.awsdns-39.co.uk",
             "ns-1374.awsdns-43.org",
             "ns-903.awsdns-48.net"
         ]
     }
 }
$ hosted_zone_id='/hostedzone/Z0608323LFWKCVBOP5JV'

external-dns deployment コンテナ args の --policy 値を変えながら確認。ポリシーを切り替える時には以下手順で生成されるDNSレコードを削除しながら行った。

# external-dns.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: external-dns
spec:
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: external-dns
  template:
    metadata:
      labels:
        app: external-dns
    spec:
      serviceAccountName: external-dns
      containers:
      - name: external-dns
        image: k8s.gcr.io/external-dns/external-dns:v0.7.3
        args:
        - --source=service
        - --source=ingress
        - --domain-filter=external-dns-test.niboshino-tech.net
        - --provider=aws
        - --policy=sync # ここを変えながら確認する
        - --aws-zone-type=public
        - --registry=txt
        - --txt-owner-id=my-hostedzone-identifier
        - --log-level=debug
      securityContext:
        fsGroup: 65534 # For ExternalDNS to be able to read Kubernetes and AWS token files

2つの service と nginx deployment。コメントアウトしているアノテーションをいじりながら確認。

# sample-service.yml
apiVersion: v1
kind: Service
metadata:
  name: nginx-1
    #annotations:
    #  external-dns.alpha.kubernetes.io/hostname: nginx.external-dns-test.niboshino-tech.net
spec:
  type: LoadBalancer
  ports:
  - port: 80
    name: http
    targetPort: 80
  selector:
    app: nginx
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-2
    #annotations:
    #  external-dns.alpha.kubernetes.io/hostname: nginx.external-dns-test.niboshino-tech.net
spec:
  type: LoadBalancer
  ports:
  - port: 80
    name: http
    targetPort: 80
  selector:
    app: nginx
---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        ports:
        - containerPort: 80
          name: http

これを適用して2つのELBとひもづくサービスが生成されたのを確認。

$ kubectl apply -f sample-service.yml
service/nginx-1 created
service/nginx-2 created
deployment.apps/nginx created

$ kubectl describe svc nginx-1 | grep -i ingress
LoadBalancer Ingress:     a99a72c973d704f21b37154b784f9e42-511373786.ap-northeast-1.elb.amazonaws.com

$ kubectl describe svc nginx-2 | grep -i ingress
LoadBalancer Ingress:     a6779323f48a9429896681eff5889292-1848281942.ap-northeast-1.elb.amazonaws.com

sync

全てのアノテーション操作がDNSレコードと同期された。

# nginx-1 にアノテーション付与
$ kubectl logs external-dns-xxxxx
time="2020-12-03T13:12:54Z" level=debug msg="Considering zone: /hostedzone/Z0608323LFWKCVBOP5JV (domain: external-dns-test.niboshino-tech.net.)"
time="2020-12-03T13:12:54Z" level=debug msg="No endpoints could be generated from service kube-system/kube-dns"
time="2020-12-03T13:12:54Z" level=debug msg="No endpoints could be generated from service default/nginx-2"
time="2020-12-03T13:12:54Z" level=debug msg="Endpoints generated from service: default/nginx-1: [nginx.external-dns-test.niboshino-tech.net 0 IN CNAME  a99a72c973d704f21b37154b784f9e42-511373786.ap-northeast-1.elb.amazonaws.com []]"
time="2020-12-03T13:12:54Z" level=debug msg="No endpoints could be generated from service default/kubernetes"
time="2020-12-03T13:12:55Z" level=debug msg="Considering zone: /hostedzone/Z0608323LFWKCVBOP5JV (domain: external-dns-test.niboshino-tech.net.)"
time="2020-12-03T13:12:55Z" level=debug msg="Adding nginx.external-dns-test.niboshino-tech.net. to zone external-dns-test.niboshino-tech.net. [Id: /hostedzone/Z0608323LFWKCVBOP5JV]"
time="2020-12-03T13:12:55Z" level=debug msg="Adding nginx.external-dns-test.niboshino-tech.net. to zone external-dns-test.niboshino-tech.net. [Id: /hostedzone/Z0608323LFWKCVBOP5JV]"
time="2020-12-03T13:12:55Z" level=info msg="Desired change: CREATE nginx.external-dns-test.niboshino-tech.net A [Id: /hostedzone/Z0608323LFWKCVBOP5JV]"
time="2020-12-03T13:12:55Z" level=info msg="Desired change: CREATE nginx.external-dns-test.niboshino-tech.net TXT [Id: /hostedzone/Z0608323LFWKCVBOP5JV]"
time="2020-12-03T13:12:55Z" level=info msg="2 record(s) in zone external-dns-test.niboshino-tech.net. [Id: /hostedzone/Z0608323LFWKCVBOP5JV] were successfully updated"

# ターゲットがnginx-1のロードバランサーであるAliasレコードが作成された
$ aws route53 list-resource-record-sets --output json --hosted-zone-id $hosted_zone_id \
    --query "ResourceRecordSets[?Name == 'nginx.external-dns-test.niboshino-tech.net.']|[?Type == 'A']"
[
    {
        "Name": "nginx.external-dns-test.niboshino-tech.net.",
        "Type": "A",
        "AliasTarget": {
            "HostedZoneId": "Z14GRHDCWA56QT",
            "DNSName": "a99a72c973d704f21b37154b784f9e42-511373786.ap-northeast-1.elb.amazonaws.com.",
            "EvaluateTargetHealth": true
        }
    }
]

# nginx-1からアノテーションを削除しnginx-2にアノテーションを付与
$ kubectl logs external-dns-xxxxx
time="2020-12-03T13:14:56Z" level=debug msg="Considering zone: /hostedzone/Z0608323LFWKCVBOP5JV (domain: external-dns-test.niboshino-tech.net.)"
time="2020-12-03T13:14:56Z" level=debug msg="No endpoints could be generated from service default/kubernetes"
time="2020-12-03T13:14:56Z" level=debug msg="No endpoints could be generated from service kube-system/kube-dns"
time="2020-12-03T13:14:56Z" level=debug msg="Endpoints generated from service: default/nginx-2: [nginx.external-dns-test.niboshino-tech.net 0 IN CNAME  a6779323f48a9429896681eff5889292-1848281942.ap-northeast-1.elb.amazonaws.com []]"
time="2020-12-03T13:14:56Z" level=debug msg="No endpoints could be generated from service default/nginx-1"
time="2020-12-03T13:14:56Z" level=debug msg="Considering zone: /hostedzone/Z0608323LFWKCVBOP5JV (domain: external-dns-test.niboshino-tech.net.)"
time="2020-12-03T13:14:56Z" level=debug msg="Adding nginx.external-dns-test.niboshino-tech.net. to zone external-dns-test.niboshino-tech.net. [Id: /hostedzone/Z0608323LFWKCVBOP5JV]"
time="2020-12-03T13:14:56Z" level=debug msg="Adding nginx.external-dns-test.niboshino-tech.net. to zone external-dns-test.niboshino-tech.net. [Id: /hostedzone/Z0608323LFWKCVBOP5JV]"
time="2020-12-03T13:14:56Z" level=info msg="Desired change: UPSERT nginx.external-dns-test.niboshino-tech.net A [Id: /hostedzone/Z0608323LFWKCVBOP5JV]"
time="2020-12-03T13:14:56Z" level=info msg="Desired change: UPSERT nginx.external-dns-test.niboshino-tech.net TXT [Id: /hostedzone/Z0608323LFWKCVBOP5JV]"
time="2020-12-03T13:14:57Z" level=info msg="2 record(s) in zone external-dns-test.niboshino-tech.net. [Id: /hostedzone/Z0608323LFWKCVBOP5JV] were successfully updated"

# nginx-2のロードバランサーがターゲットに変更された
$ aws route53 list-resource-record-sets --output json --hosted-zone-id $hosted_zone_id \
    --query "ResourceRecordSets[?Name == 'nginx.external-dns-test.niboshino-tech.net.']|[?Type == 'A']"
[
    {
        "Name": "nginx.external-dns-test.niboshino-tech.net.",
        "Type": "A",
        "AliasTarget": {
            "HostedZoneId": "Z14GRHDCWA56QT",
            "DNSName": "a6779323f48a9429896681eff5889292-1848281942.ap-northeast-1.elb.amazonaws.com.",
            "EvaluateTargetHealth": true
        }
    }
]

# nginx-2からアノテーションを削除
time="2020-12-03T13:17:58Z" level=debug msg="Considering zone: /hostedzone/Z0608323LFWKCVBOP5JV (domain: external-dns-test.niboshino-tech.net.)"
time="2020-12-03T13:17:58Z" level=debug msg="No endpoints could be generated from service kube-system/kube-dns"
time="2020-12-03T13:17:58Z" level=debug msg="No endpoints could be generated from service default/nginx-2"
time="2020-12-03T13:17:58Z" level=debug msg="No endpoints could be generated from service default/nginx-1"
time="2020-12-03T13:17:58Z" level=debug msg="No endpoints could be generated from service default/kubernetes"
time="2020-12-03T13:17:58Z" level=debug msg="Considering zone: /hostedzone/Z0608323LFWKCVBOP5JV (domain: external-dns-test.niboshino-tech.net.)"
time="2020-12-03T13:17:58Z" level=debug msg="Adding nginx.external-dns-test.niboshino-tech.net. to zone external-dns-test.niboshino-tech.net. [Id: /hostedzone/Z0608323LFWKCVBOP5JV]"
time="2020-12-03T13:17:58Z" level=debug msg="Adding nginx.external-dns-test.niboshino-tech.net. to zone external-dns-test.niboshino-tech.net. [Id: /hostedzone/Z0608323LFWKCVBOP5JV]"
time="2020-12-03T13:17:58Z" level=info msg="Desired change: DELETE nginx.external-dns-test.niboshino-tech.net A [Id: /hostedzone/Z0608323LFWKCVBOP5JV]"
time="2020-12-03T13:17:58Z" level=info msg="Desired change: DELETE nginx.external-dns-test.niboshino-tech.net TXT [Id: /hostedzone/Z0608323LFWKCVBOP5JV]"
time="2020-12-03T13:17:59Z" level=info msg="2 record(s) in zone external-dns-test.niboshino-tech.net. [Id: /hostedzone/Z0608323LFWKCVBOP5JV] were successfully updated"

# Aliasレコードが消えているのを確認
$ aws route53 list-resource-record-sets --output json --hosted-zone-id $hosted_zone_id \
    --query "ResourceRecordSets[?Name == 'nginx.external-dns-test.niboshino-tech.net.']|[?Type == 'A']"
[]

upsert-only

作成、変更のアノテーション操作のみがDNSレコードと同期された。

# nginx-1 にアノテーション付与
time="2020-12-03T13:21:23Z" level=debug msg="Considering zone: /hostedzone/Z0608323LFWKCVBOP5JV (domain: external-dns-test.niboshino-tech.net.)"
time="2020-12-03T13:21:23Z" level=debug msg="No endpoints could be generated from service default/nginx-2"
time="2020-12-03T13:21:23Z" level=debug msg="Endpoints generated from service: default/nginx-1: [nginx.external-dns-test.niboshino-tech.net 0 IN CNAME  a99a72c973d704f21b37154b784f9e42-511373786.ap-northeast-1.elb.amazonaws.com []]"
time="2020-12-03T13:21:23Z" level=debug msg="No endpoints could be generated from service default/kubernetes"
time="2020-12-03T13:21:23Z" level=debug msg="No endpoints could be generated from service kube-system/kube-dns"
time="2020-12-03T13:21:24Z" level=debug msg="Considering zone: /hostedzone/Z0608323LFWKCVBOP5JV (domain: external-dns-test.niboshino-tech.net.)"
time="2020-12-03T13:21:24Z" level=debug msg="Adding nginx.external-dns-test.niboshino-tech.net. to zone external-dns-test.niboshino-tech.net. [Id: /hostedzone/Z0608323LFWKCVBOP5JV]"
time="2020-12-03T13:21:24Z" level=debug msg="Adding nginx.external-dns-test.niboshino-tech.net. to zone external-dns-test.niboshino-tech.net. [Id: /hostedzone/Z0608323LFWKCVBOP5JV]"
time="2020-12-03T13:21:24Z" level=info msg="Desired change: CREATE nginx.external-dns-test.niboshino-tech.net A [Id: /hostedzone/Z0608323LFWKCVBOP5JV]"
time="2020-12-03T13:21:24Z" level=info msg="Desired change: CREATE nginx.external-dns-test.niboshino-tech.net TXT [Id: /hostedzone/Z0608323LFWKCVBOP5JV]"
time="2020-12-03T13:21:24Z" level=info msg="2 record(s) in zone external-dns-test.niboshino-tech.net. [Id: /hostedzone/Z0608323LFWKCVBOP5JV] were successfully updated"

# ターゲットがnginx-1のロードバランサーであるAliasレコードが作成された
aws route53 list-resource-record-sets --output json --hosted-zone-id $hosted_zone_id \
    --query "ResourceRecordSets[?Name == 'nginx.external-dns-test.niboshino-tech.net.']|[?Type == 'A']"
[
    {
        "Name": "nginx.external-dns-test.niboshino-tech.net.",
        "Type": "A",
        "AliasTarget": {
            "HostedZoneId": "Z14GRHDCWA56QT",
            "DNSName": "a99a72c973d704f21b37154b784f9e42-511373786.ap-northeast-1.elb.amazonaws.com.",
            "EvaluateTargetHealth": true
        }
    }
]

# nginx-1からアノテーションを削除しnginx-2にアノテーションを付与
time="2020-12-03T13:23:25Z" level=debug msg="Considering zone: /hostedzone/Z0608323LFWKCVBOP5JV (domain: external-dns-test.niboshino-tech.net.)"
time="2020-12-03T13:23:25Z" level=debug msg="Endpoints generated from service: default/nginx-2: [nginx.external-dns-test.niboshino-tech.net 0 IN CNAME  a6779323f48a9429896681eff5889292-1848281942.ap-northeast-1.elb.amazonaws.com []]"
time="2020-12-03T13:23:25Z" level=debug msg="No endpoints could be generated from service default/nginx-1"
time="2020-12-03T13:23:25Z" level=debug msg="No endpoints could be generated from service default/kubernetes"
time="2020-12-03T13:23:25Z" level=debug msg="No endpoints could be generated from service kube-system/kube-dns"
time="2020-12-03T13:23:26Z" level=debug msg="Considering zone: /hostedzone/Z0608323LFWKCVBOP5JV (domain: external-dns-test.niboshino-tech.net.)"
time="2020-12-03T13:23:26Z" level=debug msg="Adding nginx.external-dns-test.niboshino-tech.net. to zone external-dns-test.niboshino-tech.net. [Id: /hostedzone/Z0608323LFWKCVBOP5JV]"
time="2020-12-03T13:23:26Z" level=debug msg="Adding nginx.external-dns-test.niboshino-tech.net. to zone external-dns-test.niboshino-tech.net. [Id: /hostedzone/Z0608323LFWKCVBOP5JV]"
time="2020-12-03T13:23:26Z" level=info msg="Desired change: UPSERT nginx.external-dns-test.niboshino-tech.net A [Id: /hostedzone/Z0608323LFWKCVBOP5JV]"
time="2020-12-03T13:23:26Z" level=info msg="Desired change: UPSERT nginx.external-dns-test.niboshino-tech.net TXT [Id: /hostedzone/Z0608323LFWKCVBOP5JV]"
time="2020-12-03T13:23:26Z" level=info msg="2 record(s) in zone external-dns-test.niboshino-tech.net. [Id: /hostedzone/Z0608323LFWKCVBOP5JV] were successfully updated"

# nginx-2のロードバランサーがターゲットに変更された
aws route53 list-resource-record-sets --output json --hosted-zone-id $hosted_zone_id \
    --query "ResourceRecordSets[?Name == 'nginx.external-dns-test.niboshino-tech.net.']|[?Type == 'A']"
[
    {
        "Name": "nginx.external-dns-test.niboshino-tech.net.",
        "Type": "A",
        "AliasTarget": {
            "HostedZoneId": "Z14GRHDCWA56QT",
            "DNSName": "a6779323f48a9429896681eff5889292-1848281942.ap-northeast-1.elb.amazonaws.com.",
            "EvaluateTargetHealth": true
        }
    }
]

# nginx-2からアノテーションを削除
# nginx-1, nginx-2 からエンドポイントが生成されていないが All records are already up to date となっていた
time="2020-12-03T13:25:26Z" level=debug msg="Considering zone: /hostedzone/Z0608323LFWKCVBOP5JV (domain: external-dns-test.niboshino-tech.net.)"
time="2020-12-03T13:25:26Z" level=debug msg="No endpoints could be generated from service default/nginx-2"
time="2020-12-03T13:25:26Z" level=debug msg="No endpoints could be generated from service default/nginx-1"
time="2020-12-03T13:25:26Z" level=debug msg="No endpoints could be generated from service default/kubernetes"
time="2020-12-03T13:25:26Z" level=debug msg="No endpoints could be generated from service kube-system/kube-dns"
time="2020-12-03T13:25:27Z" level=debug msg="Considering zone: /hostedzone/Z0608323LFWKCVBOP5JV (domain: external-dns-test.niboshino-tech.net.)"
time="2020-12-03T13:25:27Z" level=info msg="All records are already up to date"
 
# nginx-2のロードバランサーがターゲットのまま変更なし
aws route53 list-resource-record-sets --output json --hosted-zone-id $hosted_zone_id \
    --query "ResourceRecordSets[?Name == 'nginx.external-dns-test.niboshino-tech.net.']|[?Type == 'A']"
[
    {
        "Name": "nginx.external-dns-test.niboshino-tech.net.",
        "Type": "A",
        "AliasTarget": {
            "HostedZoneId": "Z14GRHDCWA56QT",
            "DNSName": "a6779323f48a9429896681eff5889292-1848281942.ap-northeast-1.elb.amazonaws.com.",
            "EvaluateTargetHealth": true
        }
    }
]

create-only

作成のアノテーション操作のみがDNSレコードと同期された。

# nginx-1 にアノテーション付与
time="2020-12-03T13:31:13Z" level=debug msg="Considering zone: /hostedzone/Z0608323LFWKCVBOP5JV (domain: external-dns-test.niboshino-tech.net.)"
time="2020-12-03T13:31:13Z" level=debug msg="No endpoints could be generated from service kube-system/kube-dns"
time="2020-12-03T13:31:13Z" level=debug msg="No endpoints could be generated from service default/nginx-2"
time="2020-12-03T13:31:13Z" level=debug msg="Endpoints generated from service: default/nginx-1: [nginx.external-dns-test.niboshino-tech.net 0 IN CNAME  a99a72c973d704f21b37154b784f9e42-511373786.ap-northeast-1.elb.amazonaws.com []]"
time="2020-12-03T13:31:13Z" level=debug msg="No endpoints could be generated from service default/kubernetes"
time="2020-12-03T13:31:13Z" level=debug msg="Considering zone: /hostedzone/Z0608323LFWKCVBOP5JV (domain: external-dns-test.niboshino-tech.net.)"
time="2020-12-03T13:31:13Z" level=debug msg="Adding nginx.external-dns-test.niboshino-tech.net. to zone external-dns-test.niboshino-tech.net. [Id: /hostedzone/Z0608323LFWKCVBOP5JV]"
time="2020-12-03T13:31:13Z" level=debug msg="Adding nginx.external-dns-test.niboshino-tech.net. to zone external-dns-test.niboshino-tech.net. [Id: /hostedzone/Z0608323LFWKCVBOP5JV]"
time="2020-12-03T13:31:13Z" level=info msg="Desired change: CREATE nginx.external-dns-test.niboshino-tech.net A [Id: /hostedzone/Z0608323LFWKCVBOP5JV]"
time="2020-12-03T13:31:13Z" level=info msg="Desired change: CREATE nginx.external-dns-test.niboshino-tech.net TXT [Id: /hostedzone/Z0608323LFWKCVBOP5JV]"
time="2020-12-03T13:31:14Z" level=info msg="2 record(s) in zone external-dns-test.niboshino-tech.net. [Id: /hostedzone/Z0608323LFWKCVBOP5JV] were successfully updated"

# ターゲットがnginx-1のロードバランサーであるAliasレコードが作成された
aws route53 list-resource-record-sets --output json --hosted-zone-id $hosted_zone_id \
    --query "ResourceRecordSets[?Name == 'nginx.external-dns-test.niboshino-tech.net.']|[?Type == 'A']"
[
    {
        "Name": "nginx.external-dns-test.niboshino-tech.net.",
        "Type": "A",
        "AliasTarget": {
            "HostedZoneId": "Z14GRHDCWA56QT",
            "DNSName": "a99a72c973d704f21b37154b784f9e42-511373786.ap-northeast-1.elb.amazonaws.com.",
            "EvaluateTargetHealth": true
        }
    }
]

# nginx-1からアノテーションを削除しnginx-2にアノテーションを付与
time="2020-12-03T13:33:15Z" level=debug msg="Considering zone: /hostedzone/Z0608323LFWKCVBOP5JV (domain: external-dns-test.niboshino-tech.net.)"
time="2020-12-03T13:33:15Z" level=debug msg="No endpoints could be generated from service default/nginx-1"
time="2020-12-03T13:33:15Z" level=debug msg="No endpoints could be generated from service default/kubernetes"
time="2020-12-03T13:33:15Z" level=debug msg="No endpoints could be generated from service kube-system/kube-dns"
time="2020-12-03T13:33:15Z" level=debug msg="Endpoints generated from service: default/nginx-2: [nginx.external-dns-test.niboshino-tech.net 0 IN CNAME  a6779323f48a9429896681eff5889292-1848281942.ap-northeast-1.elb.amazonaws.com []]"
time="2020-12-03T13:33:15Z" level=debug msg="Considering zone: /hostedzone/Z0608323LFWKCVBOP5JV (domain: external-dns-test.niboshino-tech.net.)"
time="2020-12-03T13:33:15Z" level=info msg="All records are already up to date"

# nginx-1のロードバランサーがターゲットのまま変更なし
aws route53 list-resource-record-sets --output json --hosted-zone-id $hosted_zone_id \
     --query "ResourceRecordSets[?Name == 'nginx.external-dns-test.niboshino-tech.net.']|[?Type == 'A']"
 [
     {
         "Name": "nginx.external-dns-test.niboshino-tech.net.",
         "Type": "A",
         "AliasTarget": {
             "HostedZoneId": "Z14GRHDCWA56QT",
             "DNSName": "a99a72c973d704f21b37154b784f9e42-511373786.ap-northeast-1.elb.amazonaws.com.",
             "EvaluateTargetHealth": true
         }
     }
 ]
 
# nginx-2からアノテーションを削除
time="2020-12-03T13:35:16Z" level=debug msg="Considering zone: /hostedzone/Z0608323LFWKCVBOP5JV (domain: external-dns-test.niboshino-tech.net.)"
time="2020-12-03T13:35:16Z" level=debug msg="No endpoints could be generated from service default/kubernetes"
time="2020-12-03T13:35:16Z" level=debug msg="No endpoints could be generated from service kube-system/kube-dns"
time="2020-12-03T13:35:16Z" level=debug msg="No endpoints could be generated from service default/nginx-2"
time="2020-12-03T13:35:16Z" level=debug msg="No endpoints could be generated from service default/nginx-1"
time="2020-12-03T13:35:16Z" level=debug msg="Considering zone: /hostedzone/Z0608323LFWKCVBOP5JV (domain: external-dns-test.niboshino-tech.net.)"
time="2020-12-03T13:35:16Z" level=info msg="All records are already up to date"

# nginx-1のロードバランサーがターゲットのまま変更なし
aws route53 list-resource-record-sets --output json --hosted-zone-id $hosted_zone_id \
    --query "ResourceRecordSets[?Name == 'nginx.external-dns-test.niboshino-tech.net.']|[?Type == 'A']"
[
    {
        "Name": "nginx.external-dns-test.niboshino-tech.net.",
        "Type": "A",
        "AliasTarget": {
            "HostedZoneId": "Z14GRHDCWA56QT",
            "DNSName": "a99a72c973d704f21b37154b784f9e42-511373786.ap-northeast-1.elb.amazonaws.com.",
            "EvaluateTargetHealth": true
        }
    }
]

調査まとめ

policy の名前通りにDNSレコードが同期されることが分かりました(素晴らしいネーミング!)。誤ってアノテーションを消してしまうようなオペレーションミスのことを考えると、ドキュメントに例示されているように upsert-only もしくは create-only を設定するのがベターな印象を受けました。

私が最近知ったGitHubのいくつかの便利機能

こんにちは。Webシステム開発や各種ソフトウェア開発において GitHub を利用する場面は多いかと思いますが、私が最近知った便利な機能をメモがてらいくつか紹介しようと思います。

Issue を Pull Request と関連付けて自動的にクローズさせる

docs.github.com

ある issue に対して Pull Request(以下PR)を作るというのは良くあることですが、PRを作る際に特定のキーワード(close, fix, resolve など詳しくはドキュメント参照)と対象のissue番号を書いておくと issue と PR が関連付けられます(画像1枚目, 2枚目)。右側のメニューに Linked issues という項目がありここに関連付けた issue が表示されます。

https://i.gyazo.com/127c48c1a7bca3d72a4cad2116f584e9.png

https://i.gyazo.com/9ef90b15d73400345557309a7e835826.png

この状態でPRがマージされると関連付けた issue が自動的にクローズされます!(画像3枚目, 4枚目) issue にはどのPRによってクローズされたかが明記され、また Linked pull requests という項目でも記録されます。

https://i.gyazo.com/7a17aecedf9402194ae3ff72c10fe416.png

https://i.gyazo.com/4ab694db3a239d4f47ac3c72b7a38fdc.png

これまではマージして自分で(もしくは他の誰かが) issue をクローズするという一手間がありましたが、自動化されるので楽できますね。あとは明示的に issue と特定のPRが関連しているというのが示されるのも後々振り返るときに便利だと思います。

複数の issue テンプレート作成

docs.github.com

レポジトリの issue テンプレートを複数作成できる機能について紹介します。

レポジトリの Settings から Features という項目内の Set up templates ボタンをクリック。 https://i.gyazo.com/281d63ceb5001edc6b8b9a1d6b6bfc5b.png

いくつかテンプレートの種類が用意されています。今回は既存のテンプレートを全て有効にしました。

https://i.gyazo.com/e04c26578dc5f7e13a029d233cdcd20a.png

https://i.gyazo.com/39e99649edcd760385f984e4f3de3204.png

Propose changes ボタンをクリックするとコミット操作メニューが表示されます。設定がレポジトリのコードとして含まれることが予想されます。

https://i.gyazo.com/bfd14a5edb297b07774e7bbe4e4670eb.png

上記のメニューからコミットしたところ、 .github/ISSUE_TEMPLATE というディレクトリができておりその中にはテンプレートごとのmarkdownファイルが生成されていました。このファイルを編集するとテンプレートの内容を変更できました。

https://i.gyazo.com/7bb8a410c4192ec8421486d3bc473e89.png

この状態で新しく issue を作成すると以下のようにテンプレートを選択できるようになっていました。リストの下には小さく open blank issue というリンクがあり、これまで同様の空の issue 編集ページに飛ぶことも可能です。

https://i.gyazo.com/82b32767dc1e4e4c979a052c69d21fa5.png

試しに Feature request というテンプレートを選択すると予め決められたフォーマットで文言がセットされた状態の編集ページが表示されました。

https://i.gyazo.com/910d5c796c02647a59a9279698e69a61.png

issue の体裁がある程度決まっているとメンテナンスする人にとっては情報を把握しやすくなり、issue を報告した人とのコミュニケーションの質が高まるため良いプラクティスだと思っています。テンプレート自体は以前から機能としてあったと思いますが、複数種類のテンプレートを用意できるのは助かるケースも多いのかなと思います。技術コミュニティの運営で issue を使って管理することがあり meetup を開催するに当たって毎回テンプレート的な issue をいくつか作成するため、こういう使い方にも応用できそうだなと思います。

コミット署名の必須化

docs.github.com

ブランチの保護に関してコミットに署名が付いたもののみマージを許可する設定が可能です。

レポジトリの Settings > Branches から Branch protection rules を追加します。Branch name patternは必須だったので、一旦ワイルドカードにして Require signed commits にチェックをいれ更新します。

https://i.gyazo.com/a89682b1650588061485083e4d98d5bb.png

この設定後、これまで通りローカルで新しいブランチを作成後コミット、プッシュしてPRを作成したところマージがブロックされました。

https://i.gyazo.com/d1a9ab7f82b8cbc3edc59f67bc9617b2.png

ということで署名方法の一つであるGPGを使ってコミットしてみます。GPGについては詳しくありませんので作成方法等は以下のドキュメントを参照してください。

docs.github.com

GPGを設定してコミットを行いPRを作成しました。コミットには verify マークが付与され、またマージもできるようになりました。

https://i.gyazo.com/c8e3ae20579f0037485eded28a92c52f.png

コミット署名によってコミットのなりすまし・偽装を防ぐことが期待されます。ぱっと見でこのユーザーのコミットだから信頼できると感じることはあるので署名によって担保しておくのは仕組みとして良いと思います。ローカルで署名の設定が少し手間取った(個人の感想)のでプロジェクトに導入する際はメンバー内で合意が取れているのと周知が必要になりそうです。

まとめ

GitHubに備わっているいくつかの便利な機能を紹介しました。使っていてちょっと不便というか自動化されてたら嬉しいということがいつの間にか実装されていてとてもありがたいです。いつも通り使っていても新しい機能や改善に気付かないこともあるので、自らに管理権限のあるレポジトリを作成して気が向いたときにいろいろ動かしてみることをオススメします。

今回調査のために作ったレポジトリです。 github.com

Kanazawa.rb meetup #92 に参加しました #kzrb

今回もオンライン開催のmeetupでした。

meetup.kzrb.org

kzrb.doorkeeper.jp

もくもく会

今回は、CloudFormation用JSON SchemaをVSCodeで利用しているのですがエラーが出ているので調査していました。現象については以下にまとめました。そこまで致命的なエラーというわけではないです。

github.com

JSON Schemaでは $ref というキーワードを使い特定のスキーマを参照できます。今回の問題ではこの参照先がファイル内に存在しないことでエラーが出ている模様でした。$ref に関しては以下を参照。

json-schema.org

具体的には AWS::ResourceGroups::Group の Tags という定義で、もくもく会のときに見たときは List of JSON というタイプだった記憶があるのですがこの記事書いている時点では List of Tag というより具体的なタイプになっています。もしかするとJSON Schema側を更新すれば解決するかもしれないですね。

docs.aws.amazon.com

作業環境とお題について

話は変わってもくもく会時の手元の作業環境ですが左半分にブラウザを、右半分の上部にSlack、下部にZoomをそれぞれ配置していました。本当はZoomを全画面にしてというのが理想的ですが作業しながら他の人の顔も見たかったのでこんな感じにしていました。別モニターにZoomを常時表示するのもいいかもしれませんね。

この画面をキャプチャしたのはもう一つ意図があります。作業中に「もくもく会でやることを毎回悩むのだけどみなさんどうやって見つけてますか?」という質問があり、私はまさにこのキャプチャ内のやりたいことリストというのを用意しています。調べてみたいことや作りたいことを思いついたときにメモしておいて、もくもく会当日にリストから選ぶという運用をしています。選ぶ基準はその時の気分ですw

f:id:TAKAyuki_atkwsk:20200426110102p:plain

他の人の話を聞いた感想など

  • Rubyの右代入演算子について(http://secret-garden.hatenablog.com/entry/2020/04/10/195207)
    • イデアはとても興味深い
    • プログラム書く側の考え方として、メソッドチェーンして最後に値を変数に入れるというのが新鮮だった
      • もしかすると日本語的な世界観???
    • irbなどのreplではざっと書いたものを逐次実行するので有用なのではと思う
      • 要するにコードスタイルはともかく実行結果がほしいので
      • ファイルに書くときは可読性の問題で左に変数があるスタイルで統一されている方がよいと思った
  • Rust
    • 学習コンテンツ(https://doc.rust-lang.org/book/index.html)
      • 本のようなフォーマットできれいだなと思っていたらmdBookというツールで作られているとのこと
    • 変数は基本的にイミュータブルという話が出てきて、驚いている参加者が多い印象があって逆に驚いた
      • たぶん慣れの問題で、私はScala関数型言語を触る機会が多いので一般的な感覚だった
      • 最近出ているプログラミング言語はイミュータブルな変数を採用しているものが多い気がする
      • こういうのは極論になりがちだけど、適材適所だと思う(私は基本的にはイミュータブルにしておいてループ内とか局所的にミュータブルな変数を使うというのはあり派)
      • 少しだけこの話(ミュータブルの方がいい例)に触れている発表がScalaMatsuri 2019で行われたので興味ある方はどうぞ
  • Cuprite - Headless Chrome driver for Capybara
    • 気になる

懇親会

懇親会は引き続きZoom上で行われました。途中退出したりまた戻ってきたりできて自由度が高くて良いですね。

f:id:TAKAyuki_atkwsk:20200426094132p:plain

作業用EC2インスタンスを cloud-init で準備する

AWS環境で単発の作業用サーバー(例: 負荷テストツールの実行用)を楽に準備したくて cloud-init を利用する方法を調べました。EC2インスタンスの起動時にユーザーが定義した設定を行ってくれる仕組み(= cloud-init)があり、この設定をユーザーデータという形でEC2インスタンスに渡すことができます。

cloudinit.readthedocs.io

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/user-data.html

要件

  • プライベートサブネットに配置
  • デフォルトの ec2-user ではなくて、特定のユーザーでSSHログインしたい(公開鍵認証)
  • OpenJDK8 と sbt がインストール済み
    • Gatling という負荷テストツールを利用する想定
    • amazon-corretto のインストールで良い方法が見つからなかったので OpenJDK にしています

ユーザー作成

まず、SSHログインするためのユーザーアカウントを作成します。ログインするために公開鍵を登録するというのがポイントになります。cloud-init の users 設定で行います。

#cloud-config
cloud_final_modules:
    - [users-groups, always]
users:
    - name: takagi
      groups: [wheel]
      sudo: ["ALL=(ALL) NOPASSWD:ALL"]
      shell: /bin/bash
      ssh-authorized-keys:
          - ssh-rsa publickey # 公開鍵をセットする

この設定は以下資料を参考にしました。

aws.amazon.com

EC2インスタンス作成時に上記の設定内容をユーザーデータに渡しインスタンスが起動するとSSHログインできるようになります。踏み台サーバー経由でログインするために以下のような設定を行います。鍵は簡易的に踏み台サーバーと同じものを利用しています。諸々の設定が上手くいけば ssh working-server でログイン可能です。

# ~/.ssh/config
Host bastion # 踏み台サーバー
    HostName x.x.x.x # public IPアドレス
    User takagi
    IdentityFile /Users/takayuki_atkwsk/.ssh/id_rsa
Host working-server # 作業用サーバー
    HostName 192.168.2.73 # private IPアドレス
    User takagi
    IdentityFile /Users/takayuki_atkwsk/.ssh/id_rsa
    ProxyCommand ssh -W %h:%p bastion

パッケージのインストール

次に必要なパッケージをインストール済みの状態にします。上記でSSHログインできるようになった段階で yum install コマンドを打っても良いのですが、時間が空いて別の作業用インスタンスを起動したときに再度打つのも面倒くさいので cloud-init に任せてしまいます。今回は OpenJDK と sbt をインストールします。注意点としては、パッケージのインストールはインスタンスのライフサイクルで一度しか行われないため、上記の設定でインスタンスを起動した場合は一度終了(stop ではなく terminate)してパッケージの設定を追加した新しいインスタンスを作り直しましょう。

sbt に関しては以下のインストール方法に記されている方法の内、RPMレポジトリをパッケージマネージャに追加する方法で行います。

curl https://bintray.com/sbt/rpm/rpm | sudo tee /etc/yum.repos.d/bintray-sbt-rpm.repo
sudo yum install sbt

www.scala-sbt.org

cloud-init で対応するには yum_repos という設定を利用します。各設定値には上記の sbt RPM URLから得られるデータに含まれる値を使います。こちらがダウンロードしたデータです。

#bintray--sbt-rpm - packages by  from Bintray
[bintray--sbt-rpm]
name=bintray--sbt-rpm
baseurl=https://sbt.bintray.com/rpm
gpgcheck=0
repo_gpgcheck=0
enabled=1

それぞれの値を yum_repos に当てはめると以下の cloud-init 設定になります。これでパッケージマネージャにレポジトリを追加できます。後は yum install でインストールしたいパッケージ名を packages の値に書き込みます。

yum_repos:
    bintray--sbt-rpm:
        baseurl: https://sbt.bintray.com/rpm
        name: bintray--sbt-rpm
        enabled: true
        gpgcheck: false
packages:
    - java-1.8.0-openjdk-devel
    - sbt

yum_repos: https://cloudinit.readthedocs.io/en/latest/topics/modules.html#yum-add-repo

packages: https://cloudinit.readthedocs.io/en/latest/topics/modules.html#package-update-upgrade-install

この設定をユーザーデータに含めてインスタンスを起動すると、OpenJDK および sbt がインストールされた状態になっています。これで Gatling シミュレーションを含んだソースコードをローカルから scp すれば実行できるようになります。

[takagi@ip-192-168-2-73 ~]$ which java
/usr/bin/java
[takagi@ip-192-168-2-73 ~]$ which sbt
/usr/bin/sbt
[takagi@ip-192-168-2-73 ~]$ java -version
openjdk version "1.8.0_242"
OpenJDK Runtime Environment (build 1.8.0_242-b08)
OpenJDK 64-Bit Server VM (build 25.242-b08, mixed mode)

まとめ

用意した cloud-init 設定全体を以下に示します。今回は単発でEC2インスタンスを利用する(=定常的に稼働しないまたは他の人が利用しない)用途だったのでこのくらいの簡潔さが丁度良いなと感じました。組織でEC2インスタンスの構成管理を行いたい場合になると Chef や Ansible などのツールを使う方が上手く運用できるのかもしれません。

#cloud-config
cloud_final_modules:
    - [users-groups, always]
users:
    - name: takagi
      groups: [wheel]
      sudo: ["ALL=(ALL) NOPASSWD:ALL"]
      shell: /bin/bash
      ssh-authorized-keys:
          - ssh-rsa publickey # 公開鍵をセットする
yum_repos:
    bintray--sbt-rpm:
        baseurl: https://sbt.bintray.com/rpm
        name: bintray--sbt-rpm
        enabled: true
        gpgcheck: false
packages:
    - java-1.8.0-openjdk-devel
    - sbt

Kanazawa.rb meetup #91 に参加しました #kzrb

1月以来のKanazawa.rb meetupに参加しました。今回は昨今のCOVID-19の影響によりオンライン開催となりました。

kzrb.doorkeeper.jp

初のオンライン開催

Kanazawa.rb では史上初のオンライン開催となりました。Zoomを使って参加者はそれぞれの場所からログインして常時接続、発表以外のときはマイクも常時ONという状態でやっていました。上の写真は自分の環境(ITBP武蔵のサロンスペース)で、下の写真(by @kiyohara)はZoomの参加者集合写真です。ノートPCなので2画面無いと作業しながらかつ相手の様子を見ながら喋るのが大変そうだなと思いiPadをサブディスプレイにしていました。

f:id:TAKAyuki_atkwsk:20200324213354p:plain

雑に感想を並べていきます

  • 雑談する時間帯もあったし黙々と集中して作業する時間帯もあってよかった
  • オンライン開催ということで県外在住の人(確か東京から?)が参加していた
    • 遠方でもパッと参加できるのは良いね
  • 全員常時接続なので、peer to peer やグループ間の会話ができない構造になっている
    • 専用部屋みたいのを用意すればできなくはないけど準備が煩わしい
    • パッとこういう会話ができるのが現実のmeetupの良さかもしれない
  • 発表資料を手元で見れるのがよい(前の人と被って見えないとかが無い)
  • 画面共有は慣れが必要
  • 意図的にZoomの音を切ってもよいものか?
    • 音楽聞いて作業したいときどうするか?
  • 常時接続なのでネットワーク帯域が持ってかれる
    • 用事があったついでで外から参加していたので個人用のPocket WiFiを使ってたけど、次は家からやりたい...w
  • 他の人がはまりポイントを共有していて、それを聞いた他の人からアドバイスを貰って見事に解決していた
    • Slackでいろいろリンクを共有できててよかった
  • VTuber参加よさそう
  • 懇親会無いのは寂しい

もくもく内容

EC2のユーザーデータ(cloud-init)について調べていました。Gatlingという負荷テストツールがあってそれを単発でEC2上で動かすときに自分の公開鍵とか依存パッケージをいちいち持ってくるのが大変だな、という体験があってユーザーデータを使って楽にできないか、というのを調べていました。最後まで調査できなかったので詳細は別の記事で書く予定ですが、パッケージのインストールはある程度できるようになりました。この辺見ながら試していました。

cloudinit.readthedocs.io

来月もオンラインでのもくもく会となります。