TerraformでEKSを作成する

Terraform で EKS を作成してみたのでメモとして残しておきます。 サンプルは GitHub に置いてます。README 通りに進めればデプロイできます。不備があれば Issue や PR もらえると喜びます。

github.com

なぜeksctlじゃないのか

github.com

ざっと理由を挙げると以下です。

  • EKS Cluster に関連しない AWS リソースの管理が複雑となる
    • EKS Cluster 群は eksctl で、それ以外はマネコンや AWS CLI、Terraform とかとなると運用辛そう
  • 細かいパラメータの指定ができない
    • Security Group のルールとか Launch Templete のパラメータとか

誤っているとかあればブコメTwitter で教えてください。 念の為に書いておくと、僕は eksctl を dis るつもりは全く無く、なんなら今でも検証用途でサクッと EKS Cluster 作りたい時は eksctl でやっています。 プロダクションで eksctl 使ってるよって人がいればどういう運用をしているのか聞いてみたいです。

Managed Node Groupを利用しない

Managed Node Group は便利ですが、様々な制約があります。( 2020/06/07 現在

docs.aws.amazon.com

全ては網羅していませんが、代表的なものを挙げると以下です。

  • UserData がカスタムできない 1
  • Spot Instance が利用できない 2
  • Launch Template が指定できない 3

特に UserData がカスタムできない点が痛いです。Docker や kubelet の Config を修正することができないほか、 kubelet を起動する際に --register-with-taints オプションで Taints を割り当てることもできません。 Unmanaged Node Group の場合は UserData で bootstrap.sh の引数として --register-with-taints を渡すことが可能です。

その他の Issue については aws/containers-roadmap に挙がっていますので、これ欲しい!という機能があれば Issue を立てるか既存の Issue に +1 しましょう!

工夫したところとか

template_fileData Sourceの利用

Terraform の template_file Data Source を利用して Woker node の UserData を指定しました。

www.terraform.io

Worker node を作成した EKS Cluster に参加させる際に /etc/eks/bootstrap.sh の引数で EKS Cluster 名を指定する必要があり、そこで template_file を利用することで、ShellScript に EKS Cluster 名をハードコードせずとも動的に指定することが可能です。便利。

EKS最適化AMIのAMI IDをSSM Parameter Storeから取得

EKS 最適化 AMI の AMI ID は SSM Parameter Store に存在します。

docs.aws.amazon.com

以下の様に Data Source で SSM Parameter Store の情報を取得し、value を利用することが可能です。便利。

data "aws_ssm_parameter" "eks_optimized_ami_id" {
  name = "/aws/service/eks/optimized-ami/1.16/amazon-linux-2/recommended/image_id"
}

resource "aws_launch_template" "eks_worker_node_template" {
  .
  .
  .
  image_id = data.aws_ssm_parameter.eks_optimized_ami_id.value
  .
  .
  .
}

www.terraform.io

ハマったとことか

殆どドキュメントに記載されている内容です。

docs.aws.amazon.com

Worker nodeが認識されない

$ kubectl get nodes
No resources found in default namespace.

様々な問題が考えられますが、僕の場合は Security Group に問題がありました。 Terraform で Cluster 用の Security Group を作成していましたが、aws_eks_cluster Resource で security_group_ids を指定していなかったことが原因でした。 下記の様に security_group_ids を指定することで、EKS 上では Additional security groups として認識されます。

vpc_config {
  security_group_ids = [ aws_security_group.eks-cluster-sg-01.id ]
  subnet_ids         = [
    aws_subnet.public-a-01.id,
    aws_subnet.public-b-01.id,
    aws_subnet.protected-a-01.id,
    aws_subnet.protected-b-01.id
  ]
}

Additional security groups は EKS Cluster 作成後は更新できないため、注意しましょう。( 僕は Cluster 再作成しました...

aws-auth configMap のデプロイ漏れ

aws-auth configMap のデプロイし忘れで Worker node が認識されませんでした。

docs.aws.amazon.com

API server endpoint accessの設定不備

kubectlなどでローカルマシンから EKS の API server endpoint に対してリクエストを行う場合、接続元 IP アドレスを制限することが可能です。

docs.aws.amazon.com

ドキュメントにも記載されていますが、IP 制限を行う場合は API server endpoint access の設定で Private からも許可する設定を行うか、Worker node がインターネットへ出る時の Public IP も Public access source whitelist に追加する必要があります。つまり、下記の設定だと Worker node と EKS Cluster の Control Plane ( kube-apiserver ) 間の通信ができません。

f:id:enokawaa:20200606185601p:plain

なので僕は下記の様に設定しました。これで Worker node と Control Plane 間の通信が可能となりました。

f:id:enokawaa:20200606190914p:plain

次は

ALB Ingress Controllerについて書こうかと思います。

github.com

2019年振り返り

tl;dr

こんにちは。えのかわです。昨年に引き続き、2019年を振り返ります

blog.enokawa.co

2019年の目標

2018年振り返りでも書いているが改めて。

  1. 5 つの OSS にコントリビュートする
  2. Go 言語で 1 つ OSS を公開する
  3. コンテナを人に説明できるレベルまで理解する

結果的に達成できたのは 3 のみだった。コンテナ(主に Docker)について社内で勉強会を開催したり、コンテナ初心者に理解してもらえるように説明できたので、達成できたかなと思っている。

1 については、2 つの OSS にはコントリビュートできたが、あと 3 つ足りなかった。

github.com

github.com

2 については、みんGo(気づいたら改訂2版が出ていた)すら読んでいない。。Web ベースのチャットツールを遊びで作ってみたレベルなので未達。

github.com

2019年振り返り

本題の 2019 年振り返り。今年も仕事が忙しかった。慢性的に忙しかった。ただ忙しい中でもどうにか時間を作ってコンテナの勉強をしたり、社内で AWS 認定資格の勉強会を開催したり、Software Design に寄稿したりしてエンジニアとしての活動を維持できたかなと思っている。その甲斐もあってか、Japan APN Ambassador 2019 に選出いただいた。APN Ambassador 選出は、アイレットに入社して 5 年目で、ようやく自分が AWS エンジニアとして認められたと感じた。APN Ambassador 選出もあり、re:Invent 2019 へ行くこともできた(行かせてくれた会社に感謝!!)。入社して一番嬉しかった。

aws.amazon.com

一応 2019 年の output とか成果を纏めておく。

振り返ってみると、今年は色々やったなぁと。2018 年と比べると外に向けての output ができて良かった。

2020年どうする

目標は↓。

  1. Kubernetes を人に説明できるレベルまで理解する
  2. Go 言語で 1 つ OSS を公開する
  3. GCP を完全に理解する(ためにブログを5本以上書く)

Kubernetes はやるやる言って全然やってこなかったのでいい加減やる。Go については 2019 年の目標に引き続きやる。そもそも何一つプログラミング言語を修得していないことに大きなコンプレックスがある。のでみんGo を読んで写経した上で何かしらの Web サービスを作って OSS として公開したい。GCP は弊社アイレットでもパートナーとして認定されたのでやる。

3 つの目標に関わらず、ブログなどの output は 2019 年同様のペースで進めたい。

ということで

来年から本気だす。

CircleCIユーザーコミュニティミートアップ@福岡に登壇してきました #CircleCIJP

tl;dr

こんばんは。えのかわです。福岡で下記のイベントに登壇してきたのでレポートします。

circleci.connpass.com

会場提供は株式会社ヤマップさんです。かの有名(?)な「新・令和の間」に案内されました。 あと CircleCI さんから「チョットデキル」 Tシャツもらえて嬉しい。僕のレベルは「完全に理解した」ですがw

f:id:enokawaa:20191211213641j:plain

2019/12/13 追記

Togetter で纏められていたので追記。

togetter.com

CircleCI ユーザーコミュニティについて - YAMAP川原さん

CircleCI ユーザコミュニティについて説明いただきました。川原さんの前職が僕の現職なので、なんだか懐かしい気分になりました。福岡では東京とは違ってアットホーム感を出したいとのことでした。質問などもしやすい雰囲気なので良いですね。

f:id:enokawaa:20191211213716j:plain

YAMAP アプリの CI 環境のおはなし (iOS版) - YAMAP藤木さん

  • ビルド・テスト・リリース環境
    • タスク管理: Backlog
    • レポジトリ: GitHub
    • ビルドツール: fastlane
    • ビルド環境: CircleCI
    • リリース・テスト: TestFlight
  • Rakefile で Buildしている
  • CI でやらせることはシンプルに
    • 藤木さんが Jenkins 職人化(=属人化)してしまった経緯から
  • PR を作成した時に Build を走らせる
  • つらいところ
  • CircleCI に任せすぎて費用が跳ね上がってる
    • TestFlight へのアップロードに約 30 分
    • TestFlight を使うメリットが大きいのでしょうがない
    • CPU Usage 単位で課金できるといいな。。。

職人化(属人化)分かりすぎる。。

CircleCI Orbs にコントリビュートした話 - @enkw_

オレです。こちらのエントリの内容を深堀りしてお話しました。

enokawa.hatenablog.jp

資料は下記です。

speakerdeck.com

いくつか質問をいただいたので、メモとして残しておきます。

Q1. 他に利用している Orbs はあるか

はい。 コントリビュートしたのは circleci/aws-ecs ですが、Docker image の Build/Push のために circleci/aws-ecr も利用しています。

サンプルの .circleci/config.yml を Gist で公開したので、参考にしてもらえると。

CircleCI Orbs Sample · GitHub

Q2. 自前 Orbs として公開しなかった理由は?

本家 Orbs に PR 出して取り込まれた方がカッコいいと思ったからです。あとは、そこまで急ぎではない要件だったので自前 Orbs として公開しませんでした。

その後は、実際に CircleCI の画面を開いてデプロイされた結果とかを見たいとの要望があったので、画面に写したりしてました。これもアットホームな雰囲気だからこそできることですね。

Android Wear アプリを提供するの会社の CI 環境 (と多様化するビルド方法) (仮) - @rakuishi07さん

  • aad(Android App Bundle)
    • 各デバイスごとに最適化された apk を含む(イメージ)
    • apk を比較して配信サイズが 20MB → 13MB(40% 減)になった
  • Executor/Commands を利用
  • Slack Channel が汚染される問題
    • Slack orb を利用する

apk はなんとなく知ってましたが、aad というものがあるんですね。勉強になりました。

アットホームな雰囲気が心地よかった

都心のイベントとは違い、FAQ や懇親会なども終始アットホームな雰囲気で、自然と皆が話し合っているのがすごく良かったです。福岡、また来ます。あと高校一年生の方も参加されていて、でその方がすげー人で、日本の未来は明るいなぁと思いました(小並感

あと今日のハイライトは、CircleCI の中の人が教えてくれたのですが僕が出した PR のレビューをしてくれた lokst が、今日の僕の登壇を知ってすごくエキサイティングしていたことです。そのことを伝えて(教えて)くれた CircleCI の中の方には感謝しかありません。いつか会えるといいなぁ。

Nginxのmapモジュールを利用して特定パスのみBasic認証を有効化する

tl;dr

えのかわです。Nginx で特定パスのみ Basic 認証を有効化したい場面に遭遇したので備忘録として残します。前提として、Nginx の Backend には php-fpm が存在するものとします。

なぜmapか

ngx_http_map_module を利用することで、シンプルに条件を記述することが可能です。パス毎に location を記載するのも一つの手段ですが、期待する挙動とならずに苦戦してしまい map モジュールを使うことにしました。(おい

nginx.org

nginx.confにmapを定義

まずは /etc/nginx/nginx.conf に map を定義します。今回は /sample/ もしくは /admin/ 配下にリクエストがあった際に Basic 認証を有効化させるものとします。

map $request_uri $auth {
  default off;
  ~^/sample/.* "Basic Authentication";
  ~^/admin/.* "Basic Authentication";
}

~正規表現の利用を宣言しています。前述のドキュメントにも下記の様に正規表現の記載があります。

A regular expression should either start from the “~” symbol for a case-sensitive matching, or from the “~*” symbols (1.0.4) for case-insensitive matching. A regular expression can contain named and positional captures that can later be used in other directives along with the resulting variable.

ハマったのが、map を定義する conf です。/etc/nginx/conf.d/ 配下の default.conf に定義しようとすると、下記の様にエラーが発生しました。

2019/11/25 15:01:35 [emerg] 1#1: "map" directive is not allowed here in /etc/nginx/conf.d/default.conf:8
nginx: [emerg] "map" directive is not allowed here in /etc/nginx/conf.d/default.conf:8

こちらも前述のドキュメントに丁寧に Directives が記載されていますね。nginx.conf というよりは、http Directive に記載しましょう。が正しいですね。ちゃんとドキュメントを読みましょう。はい。(スミマセン

Syntax:  map string $variable { ... }
Default:    —
Context:    http

default.confauth_basicを定義

下記の様に Basic 認証の設定を記載します。

location ~ \.php$ {
    root           /var/www/html/public;
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    include        fastcgi_params;

+   auth_basic $auth;
+   auth_basic_user_file /etc/nginx/.htpasswd;
}

キモは auth_basic の値が $auth となっている点です。nginx.conf で定義した map の値を参照して振る舞います。ngx_http_auth_basic_module の仕様上、auth_basic の値が off の場合は Basic 認証をキャンセルします。先ほど定義した map には default off; と記載されているため、/sample/ もしくは /admin/ 配下へのリクエストがあった場合にのみ Basic 認証が有効化され、それ以外のパスへリクエストがあった場合は Basic 認証をキャンセル(off)します。

nginx.org

Enables validation of user name and password using the “HTTP Basic Authentication” protocol. The specified parameter is used as a realm. Parameter value can contain variables (1.3.10, 1.2.7). The special value off allows cancelling the effect of the auth_basic directive inherited from the previous configuration level.

余談

location Context で if を利用することが可能ですが、Nginx としては推奨していないようです。Nginx 公式が If Is Evil (if Directive は悪)と謳っていることから、信憑性は高いでしょう。Qiita やその他ブログを漁ったところ、map ではなく if で判定している内容もちらほら見られたので、気をつけようと思いました。

www.nginx.com

まとめ

ちゃんと公式ドキュメントは読みましょう。(戒め

CircleCI Orbsにコントリビュートしました

tl;dr

こんばんは。最近は Fargate づくしのえのかわです。 CircleCI から ECS に対して Blue/Green Deployment をしたい場面、ありますよね。CircleCI-Public/aws-ecs-orb を用いることで Rolling Update は可能だったのですが、Blue/Green Deployment はサポートしていなかったのでコントリビュートしてみました。その流れを記録としてこのエントリに残したいと思います。

続きを読む

Fargate containerにSession Managerでログインする

tl;dr

2022/02/17 追記: ECS Exec を利用しましょう。


こんばんは。ブログ書かなすぎてはてなブログ Pro を契約したえのかわです。
Fargate に対して SSH ログインしたい時ってありますよね。SSH プロセスを起動するのもアレなので ssm-agent を入れた運用用途の Task を起動してみました。

続きを読む