まっしろけっけ

めもてきなやーつ

リモートワークが長くなったのでマンションを買った

はじめに

完全に出落ち感あるタイトル...タイトルは完全に釣りでリモートワークが長くなったからではなくタイミング的にそんな感じになっただけです。

なぜ購入したか?

以前住んでいたマンションの契約更新時期が今年(2020 年) 9 月末だったのだけれど、もう少し広いところに住んで飼っている犬を家の中で走り回らせたいなぁと思い出したのが昨年の夏くらい。

そこから 2LDK で職場にある程度近い賃貸を探してみたのだけれど、 20 万以上/月という感じで出せなくはないが高いなぁ...という感じだった。

そこで買ったらどうなるん?と思いつき調べたらローンだけなら 15 万/月もかからないじゃんということがわかり買うかとなった。

購入時期的には 2020 年はオリンピックがある(はずだった)ので開催中に探すのは色々大変だろうなというのがあったので開催前に買うのが良いかという感じでこのタイミングになったのだった。(コロナの影響で結局オリンピックは延期になったわけだが...)

購入までの流れ

物件調査

昨年の夏 ~ 今年の 1, 2 月まで主にインターネットで自分の条件に合う物件を探していた。
cowcamo/SUUMO/HOME'S あたりをよくみていた気がする。

内見

今年に入って実際に見てみるか〜となって 2 月末 ~ 3 月中旬は十数件の物件を内見してみた。

内見するとこの平米数ならこのくらいの広さなのか〜ふむふむとなり平米数で言うなら最低このくらい欲しいなというのも決まり良かった。

物件決定

そんなこんなで 3 月中旬に内見した今の家がほぼ全ての条件をクリアしていたので購入することを決定した。
この段階でローンの事前審査をした気がする。

諸々契約

それ以降 は大量の書類に個人情報とハンコを押しまくっていた気がする。

ローンの事前審査が通ったら、そのマンション買いますよ的な申し込みをしつつローンの本審査を行った気がする。
ローンの審査は 1 週間ほどで終わるはずで本審査が無事通ったので売買契約の締結やローンの契約/支払いなどを 3 月末 ~ 4 月中旬に終わらせて購入完了となった。

その後

その後は前の家の退去申請などをやったり引っ越しの手配やら荷造り、新居で買うものを決めたりなどこれは賃貸だろうと購入しようとあまり差は無さそう。

そんなこんなで GW 前に無事に引っ越しができ GW 中は新居用に買った様々なものが届いたのでそれの配置など行って過ごしていた。

最後に

当初の目的通り、引っ越し後は犬が家の中を走り回っていて可愛い。

これは床暖が好きになっている様子
www.instagram.com


また第二の目的だった書斎も出来た。
f:id:shiro-16:20200508114126j:plain

ということで最後にアレです。
www.amazon.co.jp

kubeval を CI に組み込んで kubernetes の yaml をチェックする

はじめに

kubeval is これ
github.com

1 年くらい前に kubernetesyaml の形式が正しいのか?を CI とかでチェックしたいな〜という気持ちになり色々なツールを調べはしたんですが、
その時はいまいちしっくりこなかった(記憶が曖昧)で導入を見送ったのですが下記の資料を見てイケるやんと思ったので導入した。

speakerdeck.com

資料にもある通り kubectl apply --dry-run とかで似たようなことができるが、CI から cluster に接続とかするのがめんどくさかったというのもあり --dry-run も採用しておらず kustomize build が正常に終了するということだけを test していました。

しかもこの資料見る前日にまさに数字と文字列の違いで apply に失敗ということが実際に起きてたので入れとこってなった。

CI に組み込む

今回は kustomize build した結果を kubeval に送って validation をしてもらう

まずは Dockerfile

kustomize と kubeval が使える Dockerfile を用意する

FROM golang:1.12-alpine
RUN apk add git gcc g++ libc-dev && \
    wget  https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/v3.2.3/kustomize_kustomize.v3.2.3_linux_amd64 && \
    chmod +x ./kustomize_kustomize.v3.2.3_linux_amd64 && \
    mv kustomize_kustomize.v3.2.3_linux_amd64 /usr/local/bin/kustomize && \
    wget https://github.com/instrumenta/kubeval/releases/latest/download/kubeval-linux-amd64.tar.gz && \
    tar xf kubeval-linux-amd64.tar.gz && \
    cp kubeval /usr/local/bin

version とかはまぁいい感じに

drone.yaml

社では drone を使っているので drone.yaml を書いていく

---
clone:
  depth: 1
build:
  image: xxxxxxxxxx # 上記の Dockerfile を build した image を指定
  auth_config: &auth_config
    username: xxxx
    password: xxxxxxx
    email: xxxxxx
  commands:
    - for env in `ls "overlays"` ; do # env 毎に kustomize build を行ってチェックしたい
        kustomize build "overlays/${env}" | kubeval;
      done

あとは branch を push した際に CI が走るように設定を行えば終わり.

最後

skip-kinds のオプションを使えば特定のリソースを除外することもできたりします。
そこらへんは docs に書いてあるので参考にすると良いかと

EKS で Auto Scale 導入した後のトラブルを解消する

はじめに

shiro-16.hatenablog.com

Auto Scale 導入に関しては上記を参照。

今回のトラブルとは

Auto Scale によって workernode 自体は増えたのにその workernode に pod が作られた時に IP が の状態のままで pod が起動しないというもの。

調査をする

正常に pod が起動する workernode と正常に pod が起動しない workernode を比べると後者は セカンダリプライベート IP の欄に IP がない事がわかった。さらにその workernode のサブネットをみると 利用可能な IPv4 アドレス が 0 になっているというのが確認できた。

数時間後にそのサブネットの 利用可能な IPv4 アドレス をみると数字が増えていることわかった。

つまり workernode の セカンダリプライベート IP に割り当てられた IP が workernode が Auto Scale によって削除された後に再利用可能になるまでに時間がかかり過ぎて IP が足らなくなるという現象ということを突き止めた。

対応する

利用可能な IPv4 アドレス を増やす

上記の現象を AWS の中の人に共有した際に「もともと大量の IP を用意して使うものなので...」(意訳)ということを言われて、ですよね〜となったので単純に workernode に割り当てられるサブネットの IPv4 CIDR を変更して利用可能な IPv4 アドレス を増やすということをやった。

これで上記のトラブルは発生しなくなった。がしかし仮に今後アクセスが増えて workernode の数が大量に必要になった場合などに同じ現象に遭遇しないとも限らないということでもう一つ対応を行ってみた。

ネットワークインターフェイスを定期的に掃除する

workernode(というか EC2) の IP 周りはネットワークインターフェイスを見る事によって現在の status を確認できる。

status が available のものは定期的に削除されている模様というのがわかった。がしかしこの間隔が長すぎるので上記の問題が発生する

という事でこちら側で短い間隔でネットワークインターフェイスを掃除するという対応を行った。

Kubernetes の CronJob でやって貰った。

ネットワークインターフェイスを掃除するスクリプト

まずは AWS SDK for Ruby | AWS を使用してネットワークインターフェイスを掃除するスクリプトを作成

require 'aws-sdk'

ec2 = Aws::EC2::Client.new()
filters = {
  filters: [
    {
      name: :status,
      values: [:available]
    },
    {
      name: :description,
      values: ["aws-K8S-i-*"] # 今回は workernode 用に作成されたものだけ削除する
    }
  ]
}
ec2.describe_network_interfaces(filters).network_interfaces.each do |network|
  ec2.delete_network_interface({network_interface_id: network.network_interface_id})
end

これだけ

CronJob の yaml を用意する


15 分ごとに上記のスクリプトを実行する CronJob を用意する。
aws-sdk の install が遅いので aws-sdk 入りの image を用意しても良いと思います。(自分はそうしている)

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: network-interface-releaser
spec:
  failedJobsHistoryLimit: 1
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - command:
            - gem
            - install
            - aws-sdk
            - &&
            - ruby
            - network-interface-releaser.rb
            env:
            - name: AWS_REGION
              value: ap-northeast-1
            image: ruby:2.7.0
            name: network-interface-releaser
          restartPolicy: Never
  schedule: '*/15 * * * *'
アクセス権限周りの設定

下記のアクセス権限を持つユーザを追加して アクセスキー ID などを kubernetes の Secret にして使う(この場合上記の yaml に env などの追記が必要)か workernode の IAM に追加すると CronJob からネットワークインターフェイスの操作が可能になる。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ec2:DeleteNetworkInterface",
                "ec2:DescribeNetworkInterfaces"
            ],
            "Resource": "*"
        }
    ]
}
最後に CronJob の yaml を apply する

EKS の cluster に yaml を apply すれば定期的に CronJob がネットワークインターフェイスを掃除してくれて綺麗な状態を保ってくれるようになる。

さいごに

個人の見解ですが、調査する時に正常に動作しているものと正常に動作していないものが既に両方存在してると勝ったなって思いますよね。

AWS SAM CLI を使って AWS Lambda をいい感じに管理する

はじめに

github.com
今回使うのは上記

Lambda 環境をローカルで動かしたり出来るので動作確認とかがすごく便利になるやーつ

実際に使う

インストール

今回は mac にインストールする

$ brew tap aws/tap
$ brew install aws-sam-cli
$ sam --version
SAM CLI, version 0.41.0

サンプルのアプリを作ってみる

今回は sam-app という名前のアプリを Golang で作成します。

$ sam init --name sam-app --runtime go1.x
$ cd sam-app
$ tree ./
├── Makefile
├── README.md
├── hello-world
│   ├── main.go
│   └── main_test.go
└── template.yaml

ローカルで動作確認

まずはローカルで動作確認をしてみる

$ GOOS=linux GOARCH=amd64 go build -o hello-world/hello-world ./hello-world # まずは build
$ sam local start-api
Mounting HelloWorldFunction at http://127.0.0.1:3000/hello [GET]
# http://127.0.0.1:3000/hello にアクセスするとレスポンスが返ってくる
# 初回は Image の DL が走るので時間がかかる

デプロイする

$ sam deploy -g # 初回は対話式で色々入力したいので -g をつける
# 色々な IAM 周りの権限を作ってくれる
# samconfig.toml というファイルが作られる
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
OutputKey-Description                                                                                OutputValue
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
HelloWorldFunctionIamRole - Implicit IAM Role created for Hello World function                       arn:aws:iam::0000:role/sam-app-HelloWorldFunctionRole-xxxxx
HelloWorldAPI - API Gateway endpoint URL for Prod environment for First Function                     https://xxxxx.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/
HelloWorldFunction - First Lambda Function ARN                                                       arn:aws:lambda:ap-northeast-1:0000:function:sam-app-HelloWorldFunction-xxxx
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
$ sam deploy # 2 回目以降

コレで deploy が完了するので上記の HelloWorldAPI - API Gateway endpoint URL for Prod environment for First Function に記載されている URL にアクセスするとレスポンスが返ってきます。

/hello/ をやめてみる

endpoint 変更したいなって気持ちなので変更してみる

$ git diff
diff --git a/template.yaml b/template.yaml
--- a/template.yaml
+++ b/template.yaml
@@ -22,7 +22,7 @@ Resources:
         CatchAll:
           Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
           Properties:
-            Path: /hello
+            Path: /
             Method: GET
       Environment: # More info about Env Vars: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#environment-object
         Variables:
@@ -34,7 +34,7 @@ Outputs:
   # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
   HelloWorldAPI:
     Description: "API Gateway endpoint URL for Prod environment for First Function"
-    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
+    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/"
   HelloWorldFunction:
     Description: "First Lambda Function ARN"
     Value: !GetAtt HelloWorldFunction.Arn
$ sam deploy 
------------------------------------------------------------------------------------------------------------------------------------------------------------------------OutputKey-Description                                                                                OutputValue
------------------------------------------------------------------------------------------------------------------------------------------------------------------------HelloWorldFunctionIamRole - Implicit IAM Role created for Hello World function                       arn:aws:iam::0000:role/sam-app-HelloWorldFunctionRole-xxxxx
HelloWorldAPI - API Gateway endpoint URL for Prod environment for First Function                     https://xxxxx.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/
HelloWorldFunction - First Lambda Function ARN                                                       arn:aws:lambda:ap-northeast-1:0000:function:sam-app-HelloWorldFunction-xxxx
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
$ curl https://xxxx.execute-api.ap-northeast-1.amazonaws.com/Prod
Hello, 0.0.0.0

Golang の場合はどのアプリが使われるのか?

Golang の場合は build されたアプリが使われるのか勝手に build されるのか?という部分が少し謎だったので調べてみた。

$ git diff hello-world/
diff --git a/hello-world/main.go b/hello-world/main.go
--- a/hello-world/main.go
+++ b/hello-world/main.go
@@ -41,7 +41,7 @@ func handler(request events.APIGatewayProxyRequest) (events.APIGatewayProxyRespo
        }

        return events.APIGatewayProxyResponse{
-               Body:       fmt.Sprintf("Hello, %v", string(ip)),
+               Body:       fmt.Sprintf("Hello, %v", string("test")),
                StatusCode: 200,
        }, nil
 }
$ sam deploy 
$ curl https://xxxx.execute-api.ap-northeast-1.amazonaws.com/Prod
Hello, 0.0.0.0 # 変わってない
$ GOOS=linux GOARCH=amd64 go build -o hello-world/hello-world ./hello-world
$ sam deploy 
$ curl https://xxxx.execute-api.ap-northeast-1.amazonaws.com/Prod
Hello, test # 変わった

ということはどこかで build 後のバイナリを指定してるんだろうなと思って template.yaml を覗いてみたら Handler: hello-world と記述された部分があったのでもう少し実験

$ mv hello-world/hello-world hello-world/hoge
$ git diff template.yaml
diff --git a/template.yaml b/template.yaml
--- a/template.yaml
+++ b/template.yaml
@@ -15,14 +15,14 @@ Resources:
     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: hello-world
+      Handler: hoge
       Runtime: go1.x
$ sam deploy
$ curl https://xxxx.execute-api.ap-northeast-1.amazonaws.com/Prod
Hello, test # 動いてる

ということでバイナリの名前を変えて template.yaml 内で指定していた場所を書き換えたら、元どおりに動いているので推測通り Handler 部分で指定されているというのが確認できた。

最後に

まだ AWS SAM CLI について調べきれていないので触りながら動作を確認してみた。

最終的にやりたいことは example.com > CDN > Lambda といった感じで CDN を挟んでアクセスを Lambda に向けたいというものなのだけれど、CDN が CloudFront ならサクッと出来るが今回は諸々の事情から Akamai を使うので Akamai の設定でハマって進捗が悪くここまで...

続きは第二回のブログがあるかもしれない

BigQuery に入門したのでハマったことをメモする

はじめに

最近社で BigQuery にクエリ投げて結果を取得して、その結果をごにょごにょするというのをやり始めて BigQuery に入門したのだけれどそりゃそうですよねということでハマったのでメモとして残しておく。

基本的な処理

使うのは Rubygoogle-cloud-bigquery です。
README にも載ってますが基本的には下記のような感じで書きます。

$ gem install google-cloud-bigquery
$ irb
require "google/cloud/bigquery"

bigquery = Google::Cloud::Bigquery.new(
        project_id: "hogehoge",
        credentials: gcp_credential_path
      )

data = dataset.query "SELECT * FROM table"

data.each do |row|
  puts row[:hoge]
end

table が既に存在していればこんな感じで情報が取得できるわけですよ。

取得する件数が多い場合

今回ハマったのがこのパターンです。クエリで取得する件数が多い(100000件以上の)場合実は上記の方法では 100000 件しか取得できないのであった...
Treasure Data の workflow の結果取得する際は気にしなくてよかったのでハマったが limit かかるのは当然と言えば当然ですね...

data = dataset.query "SELECT * FROM table LIMIT 1000000"

data.count
=> 100000

table に 100000 件以上のデータがあった場合上記のような結果になってしまいます。
なのでお手軽に全件取りたい場合は下記のようにする必要があります

data = dataset.query "SELECT * FROM table LIMIT 1000000"

begin
 puts data.count
end until (data = data.next).nil?

Google:: Cloud:: Bigquery::Job を使う場合は下記のような感じ

dataset = bigquery.dataset("dataset_name")
job = dataset.query_job "SELECT * FROM table LIMIT 1000000"
job.wait_until_done!

data = job.data
begin
 puts data.count
end until (data = data.next).nil?

さいごに

BigQuery なんか色々便利そうなのでちゃんと情報収集しなければ...となっている

Github Projects を使ってドラッカー風エクササイズをやった

はじめに

ドラッカー風エクササイズとは

ドラッカー風エクササイズとはというのは社のけんちゃんくんさんが書いてある下記の記事を参照してください

tech.pepabo.com

やるとなった経緯

僕が社に入社した直後のチームでドラッカー風エクササイズが開催され、入社したばかりの自分が周りに何を期待されているのか?や自分の強みはこれですというのを発表できる場があったのはとても良い機会だったという記憶があり、CTL を勤めている minne 事業部では今年から少しチーム体制の変更があったのでこれを機にやるかとなったのでした。

Github Projects を使った経緯

過去の経験からいくつか本質ではないところに気をつける必要があったという記憶がありそこを何とかしたいという思いがありました。

それが下記のようなものです。

  • (自身が)字が汚いので付箋に文字を丁寧に書くということに意識と時間を取られる
  • 記入後は付箋を見て物事が進んでいくのだが、付箋では小さくみんなで見づらい
  • 終わった後に振り返るには写真を撮るや付箋を保存するなどがあり振り返りづらい

これらがあったのですが、これまたけんちゃんくんさんに社のデザイナーが notion を使ってやってたというのを教えてもらいました。

それがこちら

speakerdeck.com

この資料を読んでたら notion でやることで先に挙げた懸念が解消されるし良いなとなったのですが、 notion のアカウントそもそも全員持ってないかもな?というのがあり閃いたのが Github Projects を使うという方法です。

Github Projects を選んだ理由は下記のようなものです。

  • 社では GitHub Enterprise を採用しており、全社員アカウントを持っている
  • 社の情報のほとんどが GitHub Enterprise 上に集まっている
  • 先で挙げた懸念も全て解消される

やり方

ここからは実際のやり方の説明です。

1. Project 作成

f:id:shiro-16:20200124142329p:plain

こんな感じで入力して作成

2. 参加者に自身の名前で column を作成してもらう

f:id:shiro-16:20200124142403p:plain

3. 自身に関しての質問を記述する

f:id:shiro-16:20200124142521p:plain

4. 検索窓に author:自身のアカウント でフィルターをかける

f:id:shiro-16:20200124142633p:plain

これによって誰のカラムに記入したか把握しやすくなる

5. 他人に関しての質問を記述する

f:id:shiro-16:20200124142733p:plain

これ以降は基本的には最初にあげた社のテックブログの内容と同じに進んでいきます。
今回は終わった後の感想も各位の column に書いてもらいました。

さいごに

Github Projects を使用することでより本質に意識を割くことが可能になったと感じます。

また、いつでも普段使っているリポジトリを見直せば振り返ることが可能になっているというのも便利ポイントかと思いました。

Kubernetes Meetup Tokyo #24 で登壇してきた #k8sjp

Kubernetes Meetup Tokyo とは

k8sjp.connpass.com

Kubernetesのことを詳しく聞く会とのこと

登壇経緯は青山さん(以下青)

青「次回○○って回なんですけどネタないですか?」
僕「〜って感じなら喋れますよ」
青「ではそれで」

雑にまとめるとこんな感じ

登壇内容

speakerdeck.com


minne の開発環境が kubernetes 導入したらこんな感じに変わりましたよって感じで、
導入以前に感じていた課題は解決したけど新しい課題が出てきたよという内容

twitter 眺めてると紹介したツール知らんかったというのもちらほら見かけたので、よかったかなと(普通にみんな知ってるんでは?意味あるのか?と不安になってた)

質問もいくつかもらったのと懇親会でも色々お話できたのでよかった.

資料内で紹介している telepresence に関しては下記の記事を参照してください
shiro-16.hatenablog.com

その他の内容

体調が無だったのでほぼ記憶がアレなのですが、カーネルの話があったりエフェメラルコンテナの話があったり(資料はインターネットを探してください...)