varu3/techBlog

IT infrastructure technology memo.

1ヶ月禁酒した

お酒がめちゃめちゃ好きだったんですが、思い立って(特に病気等ではなく)禁酒をしてみました。 1ヶ月ほど経過したので、覚書として思ったことなどを書いていこうと思います。

今までの飲酒歴

ざっと思い返してみるとこんな感じ。

  • 週に4日ほど。週末の金土日はいずれか(もしくは全日)で必ず飲んでいた
  • 最近は酩酊して寝るまで飲み、深酒しがちだった
  • 基本的に家飲みだけど、友人に誘われて酒を飲みに行く機会も多かった(月に2、3回)

特に今年に入ってから、日に日に飲酒の量が激しくなっていっているというのは自覚していて、 なんとかしないとなあ(でも酒を飲む)みたいな状態が続いていました。

どうして禁酒に至ったか

ある日、Twitterで流れてきたとあるツイートがきっかけで 「失踪日記2 アル中病棟(吾妻ひでお著)」と「現実逃避してたらボロボロになった話(永田カビ著)」を読んで見たところ、アルコールめちゃ怖…って言う気持ちになりました。折良くコロナの影響で リモートワークになり始めた時期で、このまま在宅勤務を始めて自宅にいるとなるとますます際限なく飲み続けてしまいそうだな…という危機感を持ったのがきっかけです。

ちなみに、どちらの漫画もアルコールに関してのエッセイ漫画でとても面白かったので是非とも一読することをお勧めします。読み終わった後、アルコールめっちゃ怖…という気持ちになること受け合い。

現実逃避してたらボロボロになった話

現実逃避してたらボロボロになった話

  • 作者:永田 カビ
  • 発売日: 2019/11/07
  • メディア: コミック

失踪日記2 アル中病棟

失踪日記2 アル中病棟

禁酒してどうだったか

特に離脱症状とかもなく、あっさり禁酒を達成できてしまいました。夜の晩酌がビールからノンアル飲料に変えたのですが、特に不満なく1ヶ月経ってしまいました。最近のノンアル飲料って普通に美味しく飲めるんですね。ノンアル飲料ありがとう。科学のチカラってすごい。体重も特に変化なかったんですが、晩酌の共につまみは普通に食べていたのでそれはそう、という感じです。

離脱症状で思い出したんですけど、禁カフェイン、禁煙、禁酒でどれが一番離脱症状がきつかったかと言われたら圧倒的に禁カフェインです。しばらく頭痛が止まらなくて大変でした。

3、4月は外で飲みに行くことも全くありませんでしたし、オンライン飲み会とかやっても一人だけ酒を飲んでいなくても何も言われないですし、ひとしきり盛り上がって寝たあとにスッキリと午前に目覚めた時は禁酒してて本当にヨカッターって心底思いました。休日の午前中を最悪な体調でスタートするということがなくなったのは嬉しいことですね。

続けてて一つ確信したのは「酒は薬物であり危険なもの」ということです。当たり前ですが、飲みすぎると依存症にもなるし体に悪影響がでる。たまたま法律では禁止されていないだけで、本来は大麻などの薬物と同じようなものなんだという認識に改まりました。用法用量を守って楽しく酒を飲む分には全然いいんですけどね。用法用量を守って楽しく飲酒したいですね。

でも、酒はまた飲み始めると思いますが、ひとまずこのままもう少し続けてみます。

awswakaran.tokyo #2@ドリコムでLTしました

開催記録はこちらの記事を参照。

www.awswakaran.tokyo

セッション内容

自分は「大規模障害から見えたAWSのバックエンド」というタイトルでショートセッション枠で発表させていただきました。

speakerdeck.com

ちょうど前のセッション「「なんとなく」使うクラウドから「ちゃんと」使うクラウドへの入門 #awswakaran_tokyo - Speaker Deck 」がクラウドの概要をまとめた入門的な記事で、AZ障害について言及されていたので、その内容を補完する形の内容であったため発表しやすかったです。内容としては、障害発生時にどのようなことが起きて、それがなぜ起こったのか、そしてその対策をまとめたものとなります。

補足

補足というかなんというかですが

  • マルチAZにしていれば障害は防げたのか?
    • セッションの内容の通りですが、マルチAZにしていても条件によっては障害が発生していました。WAF + ALBを使っている場合や、ALB自体が障害を起こしたゾーンへのリクエストを切り離せなかったこともあったそうです。

感想

勉強会って「できる人たちがある程度知識を持った人向けにやっている」モノが多いと思うですけど、そうなると初学者やこれから導入しようかなと思う人にとっては途端にハードルが高くなるんですよね。もちろんそういう勉強会は大変有意義でありがたいのですが。

「wakaran」と冠した勉強会はとてもキャッチーでわかりやすいですし、何よりみんなwakaranのだから行ってみようかなというハードルがグッと下がってとても参加しやすいと思いました。

LTする機会を作ってくださった運営の皆様、参加された方々、ありがとうございました。とても楽しい勉強会だったので、また次回も参加したいっすね。

技術書典7に本を出しました。【Drecom Tech Inside 正誤表・本文訂正】

前回の記事でお伝えした通り技術書典7にて本を出させていただきました。当日のブースでは多くの方々にご購入いただき誠にありがとうございました。

自分の書いた章では「GCP Cloud Run ではじめるGitOps ⼊⾨」 というタイトルで、GCP Cloud Runと各リソースを使ってGItOps環境を構築するチュートリアル記事を書かせていただきました。

f:id:varu3:20190924132414j:plain:w500
kawaii necochan!! no hyoushi

慌ただしく入稿したものだったので、見直しに十分に時間が割けず一部本文に必要な箇所が抜けおりました。購入していただいた方々には大変申し訳なく思います。

以下に正誤表を掲載させていただきます。

場所
P.68 下から2行目 以下の制限があることは (空白)
P.74 5.11 Backendアプリケーション 2行目 (空白) git cloneコマンド(後述)
P.81 5.15 Cloud SQL のセットアップ 2行目 (空白) Cloud SQLセットアップコマンド(後述)

git clone コマンド

$ git clone https://github.com/xesina/golang-echo-realworld-example-app

CloudSQL セットアップコマンド

gcloud sql instances create db-01
   --database-version=POSTGRES_9_6 \
   --tier db-f1-micro \
   --no-backup \
   --authorized-networks 0.0.0.0/0  \
   --availability-type ZONAL \
   --zone asia-northeast1-a

重要なコマンドを2つも消してしまっていました。

振り返ってみて

初めて技術書典に本を出してみた感想ですが、文章を書いて売るのってこんなに辛いんだ!っていう気持ちでした。文章を書く行為自体はとても楽しいのですが、本という形で金銭のやりとりが発生し人に読まれるということに余計なプレッシャーを感じてしまったのかもしれません。技術書典に並んでいる他のサークルの本を手にとってみて、もっと気楽に(そしてより楽しみながら)書けばよかったと少し後悔しています。 とはいえ、当日は会場の熱量と自分が書いた本が知らない人の手に渡っていくのを間近にみて、脳内アドレナリンがダバダバと出るような不思議な感覚がありました。振り返ってみるととてつもなく楽しい時間でした。

文章を書いてアウトプットするという行為はITエンジニアにとって必要不可欠な行為だと思います。会場内に「アウトプットしないのは知的な便秘」と書かれたTシャツを着た方がいらっしゃいましたが、フフッとなったものの最近アウトプットできてないな、便秘気味だなと反省しました。本を書いて売るというハードルに比べるとブログを書くという行為はグッとハードルが低くなります。なので順番が逆かもしれませんが、もっと気軽に発信しようという気持ちになっています。(どこまで続くかわかりませんが)

というわけで、技術書典に携わった運営の皆様、サークル出典された方々、参加された方々、大変お疲れ様でした。とても楽しい時間をありがとうございました。

技術書典7に出す本で、GCP Cloud Run について書きました。

告知となりますが、2019/9/22(日)@池袋サンシャインシティ 展示ホールC/D にて行われる技術書典7にて本を頒布します。弊社のエンジニアの有志が持ち寄った内容を好き勝手書くという本で、僕はその中でGCP Cloud Runを使ってGitOpsをやってみよう!というような内容をざっと書いてみました。

詳細

ブースの場所はい59Cとなります。

f:id:varu3:20190917141912p:plain

その他の詳細は次のURLを参照してください。

techbookfest.org

内容

手を動かせばGCPの各種リソースを駆使して次の画像のようなGitOpsな環境ができる、というチュートリアル形式になっています。

f:id:varu3:20190917000608p:plain:w600

普段、AWSしか触っていなくてGCP興味あるけどどこから触ろうか・・・?ってなっている方に読んでいただいて、Google Cloud RunとGCPのリソースを組み合わせれば、とてつもなく簡単にアプリケーションを公開することができるということを知っていただきたいです。

目次はこんな感じ。

f:id:varu3:20190916232003p:plain:w600
index

できるだけ文章も短くして、コマンドや操作だけに注力して書いたので、難しい内容ではないのでぜひとも手にとって読んでみてください。

当日は売り子もやっているので、遊びに来た際にはぜひともよろしくおねがいします!

Kubernetesをうまく扱うためのエンジニアチーム

すっかり年が明けて2ヶ月ほど経とうとしていて、年始に決意した今年はブログ頑張るぞという気持ちは雲散してしまったような気がするのでブログを書きます。

弊社のエンジニア勉強会で話そうと思ったけど内容がまとまらなかったネタを元にした怪文書になります。 マイクロサービスとk8sについてまとめた内容ですが、オチは特にありません。

続きを読む

Kopsでcalico-nodeがCrashLoopBackOffになる事象

ちょくちょくとKubernetes関連の記事を上げていっています。今回もちょっとしたトラブルの覚書です。

事象

Kopsでcalicoを使っていると、Node立ち上げ時にcalico-nodeがCrashLoopBackOffになることがある。エラーが出たcalico-nodeと同じnodeのpodから外部への接続が一切できなくなってしまいました。(ping, 名前解決ともにできなくなる。)

2018-MM-DD HH:MM:SS.207 [INFO][9] startup.go 467: Using autodetected IPv4 address on interface eth0: XX.XX.XX.XX/24
2018-MM-DD HH:MM:SS.207 [INFO][9] startup.go 338: Node IPv4 changed, will check for conflicts
2018-MM-DD HH:MM:SS.626[WARNING][9] startup.go 718: Calico node '<ホスト名>' is already using the IPv4 address XX.XX.XX.XX.
2018-MM-DD HH:MM:SS.626 [WARNING][9] startup.go 915: Terminating
Calico node failed to start

ログをみてみると、Calico node '[ホスト名]' is already using the IPv4 address <IP Addresess>.というエラーが出力されていました。

原因

前提としてKubernetesのMasterにはETCDというKVSがバックエンドとして存在していて、そこにノードの情報などが格納されています。

$ kubectl exec -it etcd-server-ip-XX-XX-XX-XX.XX.compute.internal -n kube-system -- /bin/sh
/ # etcdctl ls /calico/v1/host
/calico/v1/host/<ホスト名>
...

こんな感じで。どうやらNodeが削除されてもここのKVが残り続け、新規で立ち上げたNodeとIPアドレスが被ってしまった場合、上記のエラーが出力されるようです。

解決方法

Nodeが削除される時に同時にETCDからも削除されれば解決しそうです。調べてみると、calico-nodeを管理するcalico-kube-controllersにNode controllerという機能がありました。Node controllreNode削除時にetcdのホスト情報を一緒に削除してくれるというもので、これを使えば解決しそうですね。この機能はデフォルトでは無効化されているので、有効化する手順をまとめます。

$ kops version
Version 1.8.1 (git-94ef202)

まず、deploymentのcalico-kube-controllersにENABLED_CONTROLLERSという環境変数を設定します。

$ kubectl get deployment -n kube-system
NAME                       DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
calico-kube-controllers    1         1         1            1           20d
$ kubectl edit deployment calico-kube-controllers -n kube-system
  ....
    spec:
      containers:
      - env:
      + - name: ENABLED_CONTROLLERS
      +   value: policy,profile,workloadendpoint,node
        - name: ETCD_ENDPOINTS
          valueFrom:
            configMapKeyRef:
              key: etcd_endpoints
              name: calico-config
        image: quay.io/calico/kube-controllers:v1.0.3
        imagePullPolicy: IfNotPresent
        name: calico-kube-controllers
        resources:
          requests:
            cpu: 10m
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
  .....

続いてcalico-nodeのdaemonsetにCALICO_K8S_NODE_REFという環境変数を設定します。

$ kubectl get daemonset -n kube-system
NAME          DESIRED   CURRENT   READY     UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
calico-node   2         2         2         1            2           <none>          20d

$ kubectl edit daemonset calico-node -n kube-system 
  ....
    spec:
      containers:
      - env:
        - name: ETCD_ENDPOINTS
          valueFrom:
            configMapKeyRef:
              key: etcd_endpoints
              name: calico-config
        - name: CALICO_NETWORKING_BACKEND
          valueFrom:
            configMapKeyRef:
              key: calico_backend
              name: calico-config
        - name: CALICO_IPV4POOL_CIDR
          value: XX.XX.XX.XX/11
        - name: CALICO_IPV4POOL_IPIP
          value: cross-subnet
        - name: CLUSTER_TYPE
          value: kops,bgp
        - name: CALICO_DISABLE_FILE_LOGGING
          value: "true"
        - name: IP
        - name: FELIX_IPV6SUPPORT
          value: "false"
        - name: FELIX_LOGSEVERITYSCREEN
          value: info
        - name: FELIX_HEALTHENABLED
          value: "true"
      + - name: CALICO_K8S_NODE_REF
      +   valueFrom:
      +     fieldRef:
      +       apiVersion: v1
      +       fieldPath: spec.nodeName
        image: quay.io/calico/node:v2.6.6
  ....

これでNode controllerが有効化されました。

確認

実際に確認してみます。Masterのetcd serverに入ってetcdctlコマンドで確認します。

nodesを増やす前

# etcdctl ls /calico/v1/host | wc -l
2

nodesを増やしてみる。その後

# etcdctl ls /calico/v1/host | wc -l
5

nodesを消した後

# etcdctl ls /calico/v1/host | wc -l
2

とノードの数と合わせてcalicoのホストも増減していることがわかります。

既存のホストはどうするか

これでノードの増減とcalicoのホストも合わせて増減することができましたが、calico-node-controllerを有効化する前にできた余分なホストは削除してくれないので、これは自分で削除する必要があります。手動でちまちまと消していくのはとてもダルイのでRubyスクリプトを書きましたが、そこまで数が多いのなら作り直してしまった方が早いかもしれません。

ということで、こんな感じの簡単な備忘録でした。

Kopsでnodesが64つ以上認識しない問題

Kopsを使うに当たって、少しレアなケースに遭遇しましたので残しておきます。事象としては、いざKubernetesのノードを増台するぞ!となった時に64つ以上認識されないという問題。

$ kubectl get nodes | grep Ready | wc -l
64

あれ、100つくらい指定したはずなのにな、おかしいなと思って各ノードのログを見てみると以下のようにエラーが吐かれ続けていました。

sudo journalctl -b -f
I05XX XX:XX:XX.497565    9194 glogger.go:31] ->[XX.XX.XX.XX:3999] error during connection attempt: Connection limit reached (64)

Connection limit reached!!!!つまりKopsで立ち上がるのには64つ以上はつなげられないよ、ということらしい。この時点でかなり焦りましたが、落ち着いてコードを読みます。

kops/gossip.go at master · kubernetes/kops · GitHub

func NewMeshGossiper(listen string, channelName string, nodeName string, password []byte, seeds gossip.SeedProvider) (*MeshGossiper, error) {
    meshConfig := mesh.Config{
        ProtocolMinVersion: mesh.ProtocolMinVersion,
        Password:           password,
        ConnLimit:          64,
        PeerDiscovery:      true,
        //TrustedSubnets:     []*net.IPNet{},
    }

今回、構成したクラスタはゴシッププロトコルを使っていました。その場合のConnLimitが確かに64にハードコーディングされていることがわかります。

さらにkopsのリポジトリを漁ってみると、これに関するPRも送られているようでした。

というわけなんですが、どうやらこれらはまだMergeされていない様子。どうしようか考えあぐねた挙句、Mergeされるのを待つよりはこれを自前でBuildして使うことにしました。

protokube

kopsではkopsコマンドで立ち上がったnodeがnodeupという独自のプロビジョニングツールが起動して、protokubeというkubernetes関連のデーモンをよしなに起動してくれるプロセスが立ち上がります。

ドキュメントはこちら

Kopsではゴシッププロトコルでマスターをクラスタリングしていたのですがが、その制御もこのprotokubeがやってくれているとのこと。

独自のkops(protokube)をbuildする手順

それではこのprotokubeをビルドしてみます。kopsはgoで書かれているので、Goとビルドするためのdockerがインストールされている必要があります。今回はAWSのS3上にbuildしたバイナリを配置して、ノードが立ち上がる際はそこを参照して持ってくるというようにします。

mkdir ~/kops
cd ~/kops
export GOPATH=`pwd`
go get -d k8s.io/kops
cd ${GOPATH}/src/k8s.io/kops/
export S3_BUCKET_NAME={{保存したいS3バケット名}}
export KOPS_STATE_STORE=s3://${S3_BUCKET_NAME}
export KOPS_BASE_URL=https://${S3_BUCKET_NAME}.s3.amazonaws.com/kops/{バージョン名}/
make kops-install upload S3_BUCKET=s3://${S3_BUCKET_NAME} VERSION={バージョン名}

kopsとprotokube, nodeupのビルドが実行され、正常に完了したらS3にアップロードされます。

aws s3 ls s3://{指定したバケット名}/kops/{VERSION名}/images/                           2018-XX-XX XX:XX:XX   75691605 protokube.tar.gz
2018-XX-XX XX:XX:XX         41 protokube.tar.gz.sha1

protokubeがアップロードされていることがわかりますね。 続いて、これを使うためにはkopsが実行できるサーバで以下の環境変数を用意する必要があります。

export PROTOKUBE_IMAGE=https://${S3_BUCKET_NAME}.s3.amazonaws.com/kops/{バージョン名}/images/protokube.tar.gz
export PROTOKUBE_VERSION={VERSION名}

上記のコマンドで環境変数を設定した状態で、'kops update cluster'を実行します。すると、LaunchConfigurationが編集されて、指定したS3のバケットが指定されていることがわかると思います。既存のマスターが存在している場合は、kops update後にkops rolling-update clusterを実行しますので、マスターが再作成されます。

これで独自のkops(protokube)を指定しての構築が可能です。

protokubeのGOSSIP_DNS_CONN_LIMITを設定する。

上記のMRでは、独自にGOSSIP_DNS_CONN_LIMITを設定する必要がありますので、マスターに入って以下のファイルに変数を書き込みます。

/etc/environment
GOSSIP_DNS_CONN_LIMIT=100

今回はLIMITを100に設定しました。その後、この設定を反映するために再度、プロビジョニングする必要があります。手動でプロビジョニングするためには以下のコマンドを実行します。

$ cd /var/cache/kubernetes-install
$ ./nodeup --conf=/var/cache/kubernetes-install/kube_env.yaml --v=8

コマンドが実行されて、ノードが100まで認識されるようになったはずです。

終わりに

 いざノードを増やすという時にこのエラーが発生したため、とても焦りました。ドキュメントにも記載がなかったため、手探りながらissueとか眺めながらこのように対応しました。おそらく、このPRがマージされたkops 1.10.Xではこのような問題は起こらなるとは思うので、備忘録的にこの手順を残しておきます。