nginxのログをjsonでStackdriver Loggingに送る
Stackdriver Loggingは構造化ロギングをサポートしており、jsonPayloadの特定フィールドに構造を追加できる。
refs: https://cloud.google.com/logging/docs/structured-logging?hl=ja
GKEからStackdriver Loggingに送る場合、ロギングを有効化しているとDaemonsetのFluentdがstackdriverに送ってくれるけど、こいつは例に載っているようなparserを自由にかけるわけではない。 なので、nginxの出力そのものを構造化ロギングに対応させておく必要がある。
自分の場合、各サービスのnginxには以下のような設定を書いている。
log_format stackdriver escape=json '{"severity":"INFO",' '"timestamp":"$time_iso8601",' '"httpRequest":{' '"requestMethod":"$request_method",' '"requestUrl":"$request_uri",' '"requestSize":$request_length,' '"status":$status,' '"responseSize":$bytes_sent,' '"userAgent":"$http_user_agent",' '"remoteIp":"$remote_addr",' '"serverIp":"$server_addr",' '"referer":"$http_referer",' '"latency":"${request_time}s",' '"protocol":"$server_protocol"' '},' '"uri":"$uri",' '"queryString":"$query_string",' '"upstreamResponseTime":"${upstream_response_time}s",' '"forwardedFor":"$http_x_forwarded_for",' '"requestId":"$sent_http_x_request_id",' '"userId":"$sent_http_x_user_id",' '"pod":"$hostname",' '"host":"$http_host"}'; access_log /dev/stdout stackdriver;
上記の設定でハマりがちなのはlatencyの部分を "${request_time}s"
といった表記にしないといけないところ。
これはstackdriverの仕様としてsecondsの意味のsを付ける必要があるため。
あとはアプリ側でuser_idをresponse headerで返すようにして、userIdとしてログに載せるようにしている。 この辺は問い合わせが来たときにどういう経路で何をしたのかを探るときに使ったりする。
上記の設定で以下のような感じで見れる。
生のnginxログでも一応拾えるのは拾えるが検索フィルタもまともに使えないので構造化しておくと色々と便利。 デフォルトでは以下のようなクエリを使っている。
resource.type="k8s_container" resource.labels.project_id="project-id" resource.labels.location="region" resource.labels.cluster_name="cluster-name" resource.labels.namespace_name="ingress" labels.k8s-pod/app="nginx-ingress" labels.k8s-pod/component="controller" labels.k8s-pod/release="prod-nginx" httpRequest.status!=318
自分のクラスタの場合、1つのnginx-ingress-controllerを経由して各サービスのnginx->appという経路でアクセスしに行くため、 nginx-ingress-controllerのログを表示しておくだけでクラスタ全体のアクセスログが見れる。 nginx-ingress-controller側のアクセスログを上のstackdriverフォーマットにするために以下のようなvalues.yamlを定義している。
controller: config: log-format-upstream: '{"serverity":"INFO","timestamp":"$time_iso8601","requestId":"$sent_http_x_request_id","userId":"$sent_http_x_user_id","forwardedFor":"$proxy_add_x_forwarded_for","host":"$host","uri":"$uri","requestQuery":"$query_string","cacheStatus":"$sent_http_x_cache_status","httpRequest":{"requestMethod":"$request_method","requestUrl":"$request_uri","requestSize":$request_length,"status":$status,"responseSize":$bytes_sent,"userAgent":"$http_user_agent","remoteIp":"$remote_addr","serverIp":"$server_addr","referer":"$http_referer","latency":"${request_time}s","protocol":"$server_protocol"}}'
またbotのcralwer対策として、318のstatus codeを返すようにしている*1のでそういったアクセスは httpRequest.status!=318
でフィルタされる。
botの判定は気まぐれに手動でやっていて、大体はモーダルに対して新規リンクを求めてRails側でActonViewの例外が発生し、sentryに通知が来たのをトリガーにbotフィルターを追加している。
if ($http_user_agent ~* (360spider)) { return 318; } if ($http_user_agent ~* (MJ12bot)) { return 318; } if ($http_user_agent ~* (bingbot)) { return 318; } if ($http_user_agent ~* (SemrushBot)) { return 318; } if ($http_user_agent ~* (AhrefsBot)) { return 318; } if ($http_user_agent ~* (YandexBot)) { return 318; } if ($http_user_agent ~* (DotBot)) { return 318; } if ($http_user_agent ~* (BLEXBot)) { return 318; }
robots.txtでGoogleのbot以外は拒否しているので、それでもアクセスが来る行儀の悪いcrawler対策として記述している。 GKE+helmで管理しているが、各サービスの使い回す設定部分はvalues.yamlに記載しておき、それを各所で呼ぶ出す方式をとっているので、values.yamlのbotフィルターを追加してサービスをデプロイすると各サービスでフィルターが有効化されるような構成になっている。
# values.yaml blockBotConf: |- if ($http_user_agent ~* (360spider)) { return 318; } --- # service-a-configmap.yaml nginx.conf: | server { ... access_log /dev/stdout stackdriver; ... {{ .Values.nginx.blockBotConf | indent 6 }} ...
stackdriverの書式等も同じ方法で管理しているため、formatを全部のサービスで共通化しやすくていい感じに管理できる。
ログが整ってないと問題が起きたときに辛いことが多いので、あんまり使わなくてもとりあえず揃えておくのが良いなーと思う。
*1:最初は418のI'm a teapotを返していたが、grafanaの集計でエラーレートが高まってしまうので318にした
JIRA CloudとGitHubを連携する
Jira の価格 - 1 ユーザーあたりの月間および年間サブスクリプション料金 | Atlassian
JIRA Cloudがちょっと前に無料で使えるようになりました。
無料になったときからすぐに試していたのですが、そのときにはGitHubのcommit/PRなどがJIRAの課題と紐付かず移行を断念したのですが、
紐付けることができたので移行することにしました。
公式ドキュメント通りに行っても紐付けが行えず、レビューでもバグってると報告されまくっている連携方法で、 自分も紐付けが行えるまで長かったです…。
結論から言うと同期するリポジトリをAllからSelectedにすることでJIRAに紐付けが生成されるようになりました。 自分の場合、200個弱のリポジトリがあったので単に同期が遅いだけだったのかもしれませんが、 ステータスがCOMPLETEDになっても全く紐づく気配がなかったのでAppの不具合なのではないかと思っています。
GitHub for Jira | Atlassian Marketplace をinstallし、GitHub側でもAppをinstallします。
その後同期するリポジトリをAllからSelectedに変更すると紐づくようになりました。
GitHub側のAppは Jira Software + GitHub · GitHub Marketplace · GitHub です。
試行錯誤している最中にBitbucketアカウントも紐付けており、その際からJIRAに開発欄が表示されるようになったので、そちらも影響しているかもしれません。 もしSelectedにしてもまだ紐付かない人がいればそちらも試してみてください。
また、GitHubのAutolinkの機能も合わせて使うことをおすすめします。
Autolinked references and URLs - GitHub Docs
この機能ではリポジトリの状態に応じて課題ステータスも変更できるのでそちらも行うとより便利です。 自分の場合は以下のようなフックを入れています。
- ブランチ作成
- Backlog -> Selected for Development
- PR作成
- Selected for Development -> In Progress
- PRマージ
- In Progress -> Done
これらの設定はワークフロー設定のトランジションを変更すると反映されます。 編集後に公開しないと反映されないため、注意してください。
EKS on FargateでALBからアプリにアクセスする
金額的に自分の趣味でEKSやFargateを使うことはないのですが、興味があったので少し触ってみました。
現時点ではドキュメントが揃っておらず、試行錯誤が必要だったので記事に残しておきます。
...と思ったのですが、AWS Advent Calendarが代わりに投稿できそうだったので7日目として投稿します。
qiita.com
この記事で紹介されていることは以下のリポジトリで簡潔に確認することができます。
GitHub - 8398a7/eks-on-fargate
書いてあること
今回紹介する内容のまとめです。
検証はmacOS上から行っています。
- 書いてあること
- ツールの準備
- クラスタの準備
- ALB Ingress Controllerのセットアップ
- target-type: ipの挙動
- hostの割当時間
- iam-for-pods
- ハマったポイント
- 所感
ツールの準備
下記のドキュメントを読んでaws-cli, kubectl, eksctlを利用できるようにしてください。
eksctl の開始方法 - Amazon EKS
eksctlが既に入っている場合でもfargateクラスタを作成するためには0.11以上が必要です。
必要に応じてbrew upgradeしてください。
$ > eksctl version [ℹ] version.Info{BuiltAt:"", GitCommit:"", GitTag:"0.11.1"}
クラスタの準備
eksctl create cluster poc --fargate
eksctlで作成するとそのクラスタで利用するVPCやsubnetの設定を行ってくれます。
下記で触れるドキュメントでsubnet tagにannotationをする手順が書かれていますが、eksctl経由で作成した場合は既に付与されているため不要な手順です。
具体的には以下の部分です。
Key Value
kubernetes.io/role/elb 1
kubernetes.io/role/internal-elb 1
クラスタの作成は割と時間がかかるので、とりあえず叩いて他事をするのがお勧めです。
クラスタが作成された直後はcorednsのpodが動いており、これらもFargateで動作しています。
$ > kubectl get po -A NAMESPACE NAME READY STATUS RESTARTS AGE kube-system coredns-6d75bbbf58-5vhpf 1/1 Running 0 5m18s kube-system coredns-6d75bbbf58-zttkt 1/1 Running 0 5m18s $ > kubectl get node NAME STATUS ROLES AGE VERSION fargate-ip-192-168-175-13.ap-northeast-1.compute.internal Ready <none> 5m1s v1.14.8-eks fargate-ip-192-168-179-161.ap-northeast-1.compute.internal Ready <none> 5m17s v1.14.8-eks
Fargateで動かすためにはnamespace単位で設定する必要がありますが、eksctlで作成した場合はdefault, kube-systemのpodがFargateで起動するようになっています。
上記以外のnamespaceでpodを動かす場合は現在はnodeが存在しないのでpendingのまま待たされる、といった挙動になります。
ALB Ingress Controllerのセットアップ
公式ドキュメントは ALB Ingress Controller on Amazon EKS - Amazon EKS ですが、EC2で動かす前提で書かれており、Fargateのみの構成では動きません。
具体的にはFargateのpodでIAMの権限を渡す方法がEC2の場合とFargateの場合で異なるのが原因です。
一旦簡易的な方法としてalb-ingress-controllerのDeploymentに直接key/secretを書く方法を紹介します。
prodでは推奨されていない方式なので、ちゃんと使う場合はiam-for-podsを利用しましょう。
refs: Authentication Issues On EKS Cluster with Fargate Policy · Issue #1092 · kubernetes-sigs/aws-alb-ingress-controller · GitHub
iam-for-podsを利用する方式は後述しますが、一旦key/secret方式で続けます。
以下の手順でkey/secretを取得します。
jqを利用しているので、予め brew install jq
を済ませておいてください。
# ALBを操作するためのpolicyを作成 curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.4/docs/examples/iam-policy.json policyArn=$(aws iam create-policy \ --policy-name ALBIngressControllerIAMPolicy \ --policy-document file://iam-policy.json | jq -r .Policy.Arn) rm iam-policy.json # ALBを操作するためのkey/secret払い出しユーザの作成 aws iam create-user --user-name pocUser # 先程作成したユーザにALBのpolicyを紐付け aws iam attach-user-policy --user-name pocUser --policy-arn $policyArn # ユーザのkey/secretを払い出す aws iam create-access-key --user-name pocUser
最後のコマンドで以下のような出力が得られるのでAccessKeyIdとSecretAccessKeyをメモしておいてください。
{ "AccessKey": { "UserName": "pocUser", "AccessKeyId": "key", "Status": "Active", "SecretAccessKey": "secret", "CreateDate": "2019-12-07T08:30:11Z" } }
ここまで整ったらrbac-roleとalb-ingress-controllerをdeployしていきます。
rbac-roleに関してはドキュメント通りの手順でdeployします。
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.4/docs/examples/rbac-role.yaml
alb-ingress-controllerに関しては以下のような修正をしたyamlを手元に用意しdeployしてください。 修正点は3点です。
- vpc_idの指定
- keyの指定
- secretの指定
apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/name: alb-ingress-controller name: alb-ingress-controller namespace: kube-system spec: selector: matchLabels: app.kubernetes.io/name: alb-ingress-controller template: metadata: labels: app.kubernetes.io/name: alb-ingress-controller spec: containers: - name: alb-ingress-controller image: docker.io/amazon/aws-alb-ingress-controller:v1.1.4 args: - --ingress-class=alb - --cluster-name=poc - --aws-region=ap-northeast-1 - --aws-vpc-id=vpc-xxxx # eksctlで作成されたVPCのid env: - name: AWS_ACCESS_KEY_ID value: # さっきメモしたkey - name: AWS_SECRET_ACCESS_KEY value: # さっきメモしたsecret resources: {} serviceAccountName: alb-ingress-controller
GitHub上ではv1.1.4タグでもv1.1.3のイメージを利用するようになっているので、v1.1.4に書き換えてあります。
修正できたら以下のコマンドでdeployし、alb-ingress-controllerがRunningになるまで待ちましょう。
kubectl apply -f alb-ingress-controller.yaml watch -n1 kubectl get po -n kube-system
次にnginxをALBからアクセスするためのyamlを記述します。
--- apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: nginx annotations: kubernetes.io/ingress.class: alb alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/target-type: ip labels: app: nginx spec: rules: - http: paths: - path: /* backend: serviceName: nginx servicePort: 80 --- apiVersion: apps/v1 kind: Deployment metadata: name: nginx spec: selector: matchLabels: app: nginx replicas: 1 template: metadata: labels: app: nginx spec: containers: - image: nginx name: nginx ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: nginx spec: ports: - port: 80 targetPort: 80 protocol: TCP type: ClusterIP selector: app: nginx
ポイントは alb.ingress.kubernetes.io/target-type: ip
のannotationsをつけることです。
ingressリソースが作られるとalb-ingress-controllerに以下のようなログが出ます。
ログは kubectl logs -n kube-system $(kubectl get po -n kube-system -o name | grep alb | cut -d/ -f2) -f
で確認してください。
default/nginx: granting inbound permissions to securityGroup sg-0c4ff2ae847363695: [{ FromPort: 80, IpProtocol: "tcp", IpRanges: [{ CidrIp: "0.0.0.0/0", Description: "Allow ingress on port 80 from 0.0.0.0/0" }], ToPort: 80 }] default/nginx: creating LoadBalancer 0d836fa6-default-nginx-ef8b
ingressの結果を確認してブラウザでアクセスしてみましょう。
$ > kubectl get ing NAME HOSTS ADDRESS PORTS AGE nginx * 0d836fa6-default-nginx-ef8b-28953798.ap-northeast-1.elb.amazonaws.com 80 4m2s $ > open http://$(kubectl get ing -o jsonpath='{.items[].status.loadBalancer.ingress[].hostname}')
nginxのページが表示できたら成功です。
ここまでで起動されたhost数は4台でした。
$ > kubectl get node NAME STATUS ROLES AGE VERSION fargate-ip-192-168-111-46.ap-northeast-1.compute.internal Ready <none> 9m26s v1.14.8-eks fargate-ip-192-168-126-238.ap-northeast-1.compute.internal Ready <none> 8m4s v1.14.8-eks fargate-ip-192-168-151-139.ap-northeast-1.compute.internal Ready <none> 16m v1.14.8-eks fargate-ip-192-168-170-198.ap-northeast-1.compute.internal Ready <none> 16m v1.14.8-eks
以下の手順でリソースを掃除してください。
kubectl delete -f app.yaml # nginxのサンプルアプリ kubectl delete -f https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.4/docs/examples/rbac-role.yaml kubectl delete -f https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.4/docs/examples/alb-ingress-controller.yaml eksctl delete cluster poc userId=$(aws sts get-caller-identity | jq -r .UserId) aws iam delete-policy --policy-arn arn:aws:iam::${userId}:policy/ALBIngressControllerIAMPolicy
pocUserに関してはaws consoleから手動で削除をお願いします。
target-type: ipの挙動
alb.ingress.kubernetes.io/target-type: ip
というannotationが初見だったので、どういう挙動なのか見てみました。
LBが作られた際にターゲットグループが種類: ipで作られてFargate hostのprivate ipがroutingされていました。
試しにdeploymentのreplicasを1->2に更新してみると以下のようにログが出て登録済みターゲットが自動的に更新されていました。
Adding targets to arn:aws:elasticloadbalancing:ap-northeast-1:xxx:targetgroup/yyy/zzz modifying rule 1 on arn:aws:elasticloadbalancing:ap-northeast-1:xxx:listener/app/yyy/zzz default/nginx: rule 1 modified with conditions [{ Field: "path-pattern", Values: ["/*"] }]
replicasを1に戻すとちゃんと外してくれます。
default/nginx: Removing targets from arn:aws:elasticloadbalancing:ap-northeast-1:xxx:targetgroup/yyy/zzz: 192.168.147.236:80, 192.168.106.177:80 default/nginx: modifying rule 1 on arn:aws:elasticloadbalancing:ap-northeast-1:xxx:listener/app/yyy/zzz default/nginx: rule 1 modified with conditions [{ Field: "path-pattern", Values: ["/*"] }]
この辺は当たり前とはいえば当たり前ですが、ちゃんとintegrationされてて良いですね。
実装を読んでいないですが、target-type: ipのannotationがついたingressをwatchしてsvc->deployまで辿ってreplicasを監視しているのでしょうか。
ターゲットグループ設定を見てみると、登録解除の遅延がデフォルト300秒で作られており、外されるまでの時間差が少し気になりました。
annotationで指定できるのかな、と調べてみたところドキュメントにちゃんと載っており、試してみると反映されていました。
default/nginx: Modifying TargetGroup arn:aws:elasticloadbalancing:ap-northeast-1:xxx:targetgroup/yyy/zzz attributes to [{ Key: "deregistration_delay.timeout_seconds", Value: "30" }]. default/nginx: modifying rule 1 on arn:aws:elasticloadbalancing:ap-northeast-1:xxx:listener/app/yyy/zzz default/nginx: rule 1 modified with conditions [{ Field: "path-pattern", Values: ["/*"] }]
alb.ingress.kubernetes.io/target-group-attributes: deregistration_delay.timeout_seconds=30
refs: Annotation - AWS ALB Ingress Controller
300秒は長すぎ、短すぎという場合もちゃんと設定できるようになってて良いですね。
ここでpodが消えるタイミングとLBから外されるタイミングは「いい感じ」になっているのかと思って調べてみました。
ここで言う「いい感じ」とは
- ターゲットグループから外されるまでpodのterminateが待機される
- ターゲットグループから外されたことを確認してpodのterminateが実行される
ということです。
実際試してみると、podが削除と同時にターゲットグループの削除処理が走るようになっていました。
これでは外されるまでデフォルトの300秒delayのときに正常に動作しないのでは?と確かめてみたところ、一瞬504 gateway timeoutが出る挙動を確認しました。
ただし一瞬だけですぐに200しか返ってこなくなりました。
ターゲットグループをあまり使ったことがないので推測になりますが、deregistrationが走るとアクセスが新規に来ることはないものの、
podの削除が先行して走り、LB側で外す前にアクセスを流されてしまうと504が出るケースがあるのではないかと思います。
HPAをしっかり使っているアクセスが多いサービスのケースだと504はそこそこ出てしまうかもしれません。
これは「ing->svc->deployのreplicas数が変更していたらターゲットグループ変更」という検知パターンと相性が悪そうだと思います。
検知パターンの周期の合間に入ってpodが削除される方が先になるケースは多々あると思うので、504は避けにくいです。
deployment定義の preStop
でalb-ingress-controller側が十分検知できる時間のsleepを挟んでpodを止めるようにする、などがワークアラウンドになるかもしれません。
十分に検証できていないポイントなのでもっと良い方法があればコメント等をもらえると嬉しいです。
hostの割当時間
大体30秒弱でステータスがPendingからContainerCreatingになります。
そこからイメージのpullが始まり、Runningになるまで大体1分弱といった感じでした。
今回はnginxイメージで非常に小さいサイズなのでpull時間があまり影響しませんでしたが、1GB+のイメージpullは少し時間がかかるかもしれません。
とはいっても、EKSというよりFargateの特性に由来するものなのでECSを使われている場合は既知かもしれませんが…。
iam-for-pods
先にkey/secretを使った方法を紹介しましたが、iam-for-podsを使った方法も紹介します。
もしもkey/secretを使う方式で試していたら一旦alb-ingress-controllerのリソースを念の為削除してください。
kubectl delete -f https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.4/docs/examples/rbac-role.yaml kubectl delete -f https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.4/docs/examples/alb-ingress-controller.yaml
クラスタに対してoidc providerを紐付けてからALBのIAM権限を付与します。
policyArnは上で作成したALBIngressControllerIAMPolicyが存在していればそれを流用してください。
eksctl utils associate-iam-oidc-provider --region=ap-northeast-1 --cluster=poc --approve curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.4/docs/examples/iam-policy.json policyArn=$(aws iam create-policy \ --policy-name ALBIngressControllerIAMPolicy \ --policy-document file://iam-policy.json | jq -r .Policy.Arn) eksctl create iamserviceaccount --name alb-ingress-controller \ --namespace kube-system \ --cluster poc \ --attach-policy-arn ${policyArn} \ --approve --override-existing-serviceaccounts
作成すると、以下のような情報が取れます。
$ > kubectl get sa -n kube-system alb-ingress-controller -o jsonpath="{.metadata.annotations['eks\.amazonaws\.com/role-arn']}" arn:aws:iam::xxx:role/eksctl-poc-addon-iamserviceaccount-ku-Role1-CBGA2Q1975Q9
次にalb-ingress-controller.yamlをデプロイします。
先ほどと違ってenvでkey/secretの指定を行いません。
apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/name: alb-ingress-controller name: alb-ingress-controller namespace: kube-system spec: selector: matchLabels: app.kubernetes.io/name: alb-ingress-controller template: metadata: labels: app.kubernetes.io/name: alb-ingress-controller spec: serviceAccountName: alb-ingress-controller containers: - name: alb-ingress-controller image: docker.io/amazon/aws-alb-ingress-controller:v1.1.4 args: - --ingress-class=alb - --cluster-name=poc - --aws-region=ap-northeast-1 - --aws-vpc-id=vpc-xxxx # eksctlで作成されたVPCのid resources: {}
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.4/docs/examples/rbac-role.yaml kubectl apply -f alb-ingress-controller.yaml
alb-ingress-controllerのpodが作成されたら上記で記載したnginxを動かすためのリソースをapplyしてください。
envでkey/secretを指定しない場合と同様にLBが作られ、アクセスできるようになっています。
最初はoidc id providerの概念がややこしそうだったので敬遠していたのですが、このあたりも割と楽に設定できるようになっていますね。
eksctlでiamserviceaccountを作ると裏側でCloudFormationが動いているのですが、中ではoidc id providerへの紐付けをやってくれているようです。
{ "AWSTemplateFormatVersion": "2010-09-09", "Description": "IAM role for serviceaccount \"kube-system/alb-ingress-controller\" [created and managed by eksctl]", "Resources": { "Role1": { "Type": "AWS::IAM::Role", "Properties": { "AssumeRolePolicyDocument": { "Statement": [ { "Action": [ "sts:AssumeRoleWithWebIdentity" ], "Condition": { "StringEquals": { "oidc.eks.ap-northeast-1.amazonaws.com/id/yyy:aud": "sts.amazonaws.com", "oidc.eks.ap-northeast-1.amazonaws.com/id/yyy:sub": "system:serviceaccount:kube-system:alb-ingress-controller" } }, "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::xxx:oidc-provider/oidc.eks.ap-northeast-1.amazonaws.com/id/yyy } } ], "Version": "2012-10-17" }, "ManagedPolicyArns": [ "arn:aws:iam::xxx:policy/ALBIngressControllerIAMPolicy" ] } } }, "Outputs": { "Role1": { "Value": { "Fn::GetAtt": "Role1.Arn" } } } }
eksctl経由で作成したSAはrbac-role.yamlをapplyすることによりannotationが消えるのではないか、と思っていましたが残っていました。
ハマったポイント
- v.1.1.4のタグでalb-ingress-controller.yamlをデプロイしたらv.1.1.3のイメージが使われるようになっている
- fargate profileのIAMにALB作成権限があればALBが作られると思ったら作られていない
- iam-for-pods or envにkey/secret指定する必要があると知る
- Authentication Issues On EKS Cluster with Fargate Policy · Issue #1092 · kubernetes-sigs/aws-alb-ingress-controller · GitHub
- eksctl delete clusterでcfnがコケて削除されない
- 推測ですが、自分でapplyしたリソースが残っているとfargate profile側でpodを削除->deployで作られるの繰り返しが起きるのではないかと...
- 手動で適当にVPCとかを消し始めてfargate profileもなかなか削除されない挙動になっており、頭を抱えました
- 20分ぐらい待ったらちゃんと削除されました
- リソースを全部削除してeksctl delete clusterを叩いてもVPCの削除でコケているのを確認
- リトライでも成功しないのでVPCは手動で消しました
- これっぽい=>eksctl resources not really deleted after deleting cluster · Issue #1651 · weaveworks/eksctl · GitHub
The vpc 'vpc-xxx' has dependencies and cannot be deleted. (Service: AmazonEC2; Status Code: 400; Error Code: DependencyViolation; Request ID: u-u-i-d-x)
と出る
所感
EC2を管理したくないという観点ではFargateで完結できるようになっているので良さそうです。
LBのターゲットグループからの削除処理とpodが消えるタイミングでエラーが出るのは現状ワークアラウンドが必要そうだと感じました。
実際全部Fargateにするかと言われるとコスパはあまり良くないように感じました。
alb ingress controllerを始めとしたk8sの中を整えるようなpodは1host 1podがオーバースペックなので、そういったpodはまとめて1つのnodeで動かしたいように感じます。
他の記事でも言及されていますが、Daemonsetでfluentdを動かしておく、みたいなこともできないのでログ収集をsidecarで配置する必要があるというのも実運用では手間になるかもしれません。