EKSコンソールからnodeやworkload情報を見れるようにする

AWSコンソールのEKS画面で

Your current user or role does not have access to Kubernetes objects on this EKS cluster
This may be due to the current user or role not having Kubernetes RBAC permissions to describe cluster resources or not having an entry in the cluster’s auth config map

と表示される場合は、権限設定が必要です。

例えばAWSコンソールにログインしているIAM Userが my-user なら以下のように aws-auth ConfigMapの mapUsers に追加します。

apiVersion: v1
kind: ConfigMap
data:
  mapRoles: |
    - rolearn: arn:aws:iam::1234567890:role/my-role
      username: system:node:{{EC2PrivateDNSName}}
      groups:
        - system:bootstrappers
        - system:nodes
  mapUsers: |
    - userarn: arn:aws:iam::1234567890:user/my-user
      username: my-user
      groups:
        - system:masters

権限を絞る

system:mastersだと 全てのリソースに対して全ての操作を許可してしまうので、権限を絞りたいというニーズが出てくるかもしれません。 その場合は、 https://docs.aws.amazon.com/eks/latest/userguide/add-user-role.html の 5 にある All Regions other than Beijing and Ningxia China のリンクからダウンロードできるyamlを使います。 そのyamlは以下のようになってます(2021/01/08時点)

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: eks-console-dashboard-full-access-clusterrole
rules:
- apiGroups:
  - ""
  resources:
  - nodes
  - namespaces
  - pods
  verbs:
  - get
  - list
- apiGroups:
  - apps
  resources:
  - deployments
  - daemonsets
  - statefulsets
  - replicasets
  verbs:
  - get
  - list
- apiGroups:
  - batch
  resources:
  - jobs
  verbs:
  - get
  - list
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: eks-console-dashboard-full-access-binding
subjects:
- kind: Group
  name: eks-console-dashboard-full-access-group
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: eks-console-dashboard-full-access-clusterrole
  apiGroup: rbac.authorization.k8s.io

で、このyamlをapplyし、以下のようにgroupsにeks-console-dashboard-full-access-groupを指定します。

group
  mapUsers: |
    - userarn: arn:aws:iam::1234567890:user/my-user
      username: my-user
      groups:
        - eks-console-dashboard-full-access-group

これでEKSコンソールからnodeやworkload情報を見るための最低限の権限に絞られます。

その他注意点

注意点としては、 usernameに system:node:{{EC2PrivateDNSName}}を指定してしまうと、以下のようなメッセージがでてnodeやworkload情報が見れません。

Your current user or role does not have access to Kubernetes objects on this EKS cluster
This may be due to the current user or role not having Kubernetes RBAC permissions to describe cluster resources or not having an entry in the cluster’s auth config map

また、以下のように

      groups:
        - system:bootstrappers
        - system:nodes

groupsにsystem:bootstrapperssystem:nodesを指定してしまうと、以下のようなメッセージがでてnodeやworkload情報が見れません。

namespaces is forbidden: User "my-user" cannot list resource "namespaces" in API group "" at the cluster scope

エンジニアキャリアラダーを作成する際に参考になるサイト

海外の公開されているキャリアラダー集 www.swyx.io

これが参考になった。

まずゼロからキャリアラダーを作成するのは非常に難易度が高い。どの等級にどんな役割を期待するのかを定義しそれを言語化していく作業は並大抵のことではない。 そこですでに公開されている他社の素晴らしいキャリアラダーを参考にするとかなり楽になる。 もちろんそのままコピペするのではキャリアラダーとして機能しないので、会社の組織が各等級に期待する役割に合わせて役割や表現を変えていく必要がある。

上記のサイトの中で参考にした会社のキャリアラダー

EKSのIAM roles for service accounts機能を使いたい場合の注意点

EKSのIAM roles for service accounts機能(サービスアカウントにIAM ロールを割り当てる機能)を使いたい場合の注意点です。

AWS SDKのバージョンを確認する

IAM roles for service accounts機能を使いたい場合、サポートされているバージョンでないと機能しません。
以下のページにサポートされているSDKバージョンが記載されているので確認しましょう。
サポートされる AWS SDK の使用 - Amazon EKS

私が試したとき使っているSDKのバージョンが古くて動かなく、無駄に時間を消費しました。。

コンテナのプロセスがroot権限以外で動いている場合、適切な権限を付与する

サービスアカウントにIAM ロールを割り当てる機能の仕組みは以下のブログがとても詳しいです。
EKSでの認証認可 〜aws-iam-authenticatorとIRSAのしくみ〜 - もうずっといなかぐらし

で、最終的にコンテナのプロセスが /var/run/secrets/eks.amazonaws.com/serviceaccount/tokenの Web Identity Token Fileを読み込む必要があるんですが、デフォルトではroot権限でしか読み込めません。
そのため、以下のようにsecurityContextのfsGroupを指定する必要があります。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: <my-app>
spec:
  template:
    metadata:
      labels:
        app: <my-app>
    spec:
      serviceAccountName: <my-app>
      containers:
      - name: <my-app>
        image: <my-app>:latest
      securityContext:
        fsGroup: 有効なグループID

詳しくは以下の記事内をfsGroupで検索して下さい。
サービスアカウントの技術概要の IAM ロール - Amazon EKS

Terraformのaws_iam_openid_connect_providerリソースのthumbprint_listに自動で値を入れる方法

この記事はterraform Advent Calendar 2020の19日目です。

TL; DR

tls_certificateリソースを使う

Terraformのaws_iam_openid_connect_providerリソースのthumbprint_listに自動で値を入れたい

EKSで IAM roles for service accounts機能(PodにIAMロールを割り当てる機能)を使おうと思って、OIDC ID プロバイダーをTerraformのaws_iam_openid_connect_providerリソースを使って作成しようと思った。

しかしaws_iam_openid_connect_providerリソースのthumbprint_listは必須項目でこれをどうやって自動で入れればいいか調べてみると、 手動で値を取得する方法shellを用いて自動的に値を入れる方法などが見つかったが、もっとスマートなやり方が見つかった。 それが、tls_certificateリソースを使うを方法だ。 使い方は簡単で以下のようにすればよい。

resource "aws_eks_cluster" "my_cluster" {
  name = "my_cluster"
}

data "tls_certificate" "my_certificate" {
  url = aws_eks_cluster.example.identity.0.oidc.0.issuer
}

resource "aws_iam_openid_connect_provider" "my_openid_connect_provider" {
  client_id_list  = ["sts.amazonaws.com"]
  thumbprint_list = [data.tls_certificate.my_certificate.certificates.0.sha1_fingerprint]
  url             = aws_eks_cluster.my_cluster.identity.0.oidc.0.issuer
}

注意点としては、以下のような問題がありterraform planすると毎回idに差分がでてしまう。 github.com このコメントをみると 0.14.2で解消されているらしい(私はまだ試してない)

Athenaのパーティション項目の型とパーティションプロジェクションの奇妙な関係

Athenaのパーティションプロジェクションを試していたらちょっとハマったのでメモしておく

パターン1

S3には /app_log/year=2020/month=06/day=05/hour=04/ のような場所にログをおいている

year, month, day, hourを Glueテーブル上の型で stringにする パーティションプロジェクション上の型はintegerにする(stringがないので) たとえば projection.month.type = "integer"

SELECT * FROM my_db.app_log
WHERE year = '2020' AND month = '06' AND day = '05' AND hour = '04'
LIMIT 10

のように検索するとヒットする。 しかし

SELECT * FROM my_db.app_log
WHERE year = '2020' AND month = '06'
LIMIT 10

はヒットしない!

パターン2

S3には /app_log/year=2020/month=06/day=05/hour=04/ のような場所にログをおいている

year, month, day, hourを Glueテーブル上の型で intにする
パーティションプロジェクション上の型はintegerにする(stringがないので)
たとえば projection.month.type = "integer"

SELECT * FROM my_db.app_log
WHERE year = 2020 AND month = 6 AND day = 5 AND hour = 4
LIMIT 10

のように検索するとヒットしない!

SELECT * FROM my_db.app_log
WHERE year = '2020' AND month = '06' AND day = '05' AND hour = '04'
LIMIT 10

のように検索してもヒットしない!

パターン3

S3には /app_log/year=2020/month=6/day=5/hour=4/ のような場所にログをおく。つまり 0 を抜いた

year, month, day, hourを Glueテーブル上の型で intにする
パーティションプロジェクション上の型はintegerにする
たとえば projection.month.type = "integer"

SELECT * FROM my_db.app_log
WHERE year = 2020 AND month = 6 AND day = 5 AND hour = 4
LIMIT 10

のように検索するとヒットする

SELECT * FROM my_db.app_log
WHERE year = 2020 AND month = 6
LIMIT 10

もヒットする。

つまり、S3のパーティションにあたる値が0がついていない数値でかつ、 Glueテーブルとパーティションプロジェクションの型が数値型でないといけない!!

じゃあ S3の ディレクトリを /app_log/year=2020/month=06/day=05/hour=04/ から /app_log/year=2020/month=6/day=5/hour=4/ に変更しようとしても、0抜き指定はfluentdのオプション上できない。https://docs.fluentd.org/v/0.12/output/file#time_slice_format
※追記
よくよく考えると、もしfluentdがTime#strftimeを使っているなら year=%Y/month=%-m/day=%-d/hour=%-H で0抜きができそう。

パターン4

S3には /app_log/dt=2020-06-05-04/ のような場所にログをおく 。
dt=YYYY-mm-dd-HHのような形式は https://docs.aws.amazon.com/athena/latest/ug/partitions.html でも記されているので公式に近い。

dtを Glueテーブル上の型で stringにする パーティションプロジェクション上の型はdateにする。 projection.dt.type = "date"

SELECT * FROM my_db.app_log
WHERE dt > '2020-06-05-04'
LIMIT 10

のように検索するとヒットする

SELECT * FROM my_db.app_log
WHERE dt > '2020-06'
LIMIT 10

でもヒットする

まとめ

パターン4が妥当かな

kustomize 2.1.0の変更点

kustomize 2.1.0で機能追加、変更点があったのでまとめる
kustomize/v2.1.0.md at master · kubernetes-sigs/kustomize · GitHub

プラグイン機構の導入

kustomize の generator / transformer の振る舞いを変えてみる | TECHSCORE BLOG に詳しく書かれているのでご参照ください

resources expanded, bases deprecated

basesがdeprecatedになり、代わりにresourcesを使うようになった。

今までは例えばoverlayes/production/kustomization.yaml の中で

bases:
- ../base
patches:
- cpu_count.yaml

のように書いていたのが、今後は以下のように書くことが推奨される

resources:
- ../base
patches:
- cpu_count.yaml

replicas field

deployment.yamlの中のreplicasの値を変更することはよくあるので、kustomization.yaml の中でreplicas数を指定できるようになった

今までは以下のようにpatchファイルを書いていたが

kind: Deployment
metadata:
  name: deployment-name
spec:
  replicas: 5

今後は kustomization.yaml の中で以下のように書けるようなった

replicas:
- name: deployment-name
  count: 5

envs field

環境変数が書かれたファイルからConfigmapやSecretを生成するために、 configMapGeneratorsecretGeneratorenvフィールドがあったがdeprecatedになった。代わりにenvsフィールドが追加された。

以前

configMapGenerator:
  - name: my-configmap
     env: env.txt

今後

configMapGenerator:
  - name: my-configmap
    envs:
      - env.txt

kustomize v3.4.0でenvを指定すると Error: json: unknown field "env"というエラーが出るので、envsに変える必要がある。

1000/02/29をRubyでinvalidな日付として扱う方法、もしくはRubyで1582年以前の暦をユリウス暦ではなくグレゴリオ暦で扱う方法

結論

RubyのDateクラスには startを引数に指定できるメソッドがある。 docs.ruby-lang.org startはグレゴリオ暦をつかい始めた日をあらわすユリウス日を表す。 引数のstartにDate::GREGORIANを指定すると、常にグレゴリオ暦で処理してくれる。

Date.valid_date?(1000, 2, 29, Date::GREGORIAN)
=> false

Date.parse('1000-2-29', true, Date::GREGORIAN)
=> ArgumentError (invalid date) 

経緯

MySQLは日付カラムに 1000-2-29 をいれるとinvalidな日付として扱われエラーになるが、RubyのDate#valid_date?メソッドを使って判定するとtrueが返ってくる。
これはMySQL先発グレゴリオ暦を使っているからだった*1

先発グレゴリオ暦とは、1582年から施行されたグレゴリオ暦暦法を、1582年以前にも適用したものである。

なのでユリウス暦だと1000-2-29 は存在するが、グレゴリオ暦だと 1000-2-29 は存在しないということらしい。

で、本題だが、Ruby1000-2-29をinvalidな日付として判定する方法がないか探してみたところ、上の結論に行きついた。

参考

MySQL :: MySQL 5.6 リファレンスマニュアル :: 12.8 MySQL で使用されるカレンダー

tech.furyu.jp

*1:標準SQLがそうなのでPostgreSQLも先発グレゴリオ暦を使っている