AWS EKS にてno endpoints available for service kubernetes-dashboardのエラー対応

エラーの出た場面

AWSのチュートリアル: Kubernetes ダッシュボード (ウェブ UI) のデプロイをやっている時に、
「ウェブブラウザで以下のリンクを開いて、ダッシュボードエンドポイントにアクセスします。」という段階で下記urlにアクセスすると
http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/#!/login

下記のエラーが画面に表示されダッシュボードエンドポイントにアクセスできなかった。

1
2
3
4
5
6
7
8
9
{
kind: "Status",
apiVersion: "v1",
metadata: { },
status: "Failure",
message: "no endpoints available for service "kubernetes-dashboard"",
reason: "ServiceUnavailable",
code: 503
}

対応方法

下記のコマンドを打って、Namespace kubernetes-dashboard を対象とするFargateプロファイルを追加で作成する。

1
2
3
4
eksctl create fargateprofile \
--name fp-kubernetes-dashboard \
--namespace kubernetes-dashboard \
--cluster {クラスター名}

エラーの理由

https://dev.classmethod.jp/articles/fargate-for-eks-tutorial-kubernetes-dashboard/#toc-4
の「「Fargate for EKS」の場合に必要な追加手順」項目を参照

python moduleのimport fromのルートとなる起点を指定したい

実行スクリプトのディレクトリ階層に関係なくfrom importをさせたい

pythonを実行するスクリプトのディレクトリ階層によってfrom importが失敗することがあります。
実行するスクリプトのディレクトリ階層の位置に関係なくfrom importをできるようにする方法を調べました。

このようなディレクトリ構成で普段は、python main.pyからitem_service.py item.py が呼び出され実行される内容だとします。

1
2
3
4
5
├── main.py
├── models
│   └── item.py
└──services
   └── item_service.py

下記のようにitem_service.pyはmain.pyをルートとしてmodels/item.pyをfrom importしています。

1
2
3
4
5
6
7
8
9
10
item_service.py

from models.item import Item

class ItemServiceModel:
def search():
...

if __name__ == '__main__':
ItemServiceModel.search()

この場合に python item_service.py をすると
ModuleNotFoundError: No module named ‘models’
のようなエラーが出てimportに失敗します。

なぜ失敗するか

https://docs.python.org/ja/3/tutorial/modules.html
html#the-module-search-path
公式ドキュメントによると、「入力されたスクリプトのあるディレクトリ」がモジュールの探索パスになるということです。
python main.pyでは成功し、python item_service.pyでは失敗するようになることの理解はできました。

入力されたスクリプトのあるディレクトリ構成位置に関係なくfrom importさせたい

先程の公式ドキュメントの同じところに
「PYTHONPATH (ディレクトリ名のリスト。シェル変数の PATH と同じ構文)。」がモジュールの探索パス(import from の起点ルート)になると書いています。
なので、.zshrc や .bshrc に

1
export PYTHONPATH=$PYTHONPATH:{main.pyのあるディレクトリの絶対パス}

とすれば、python item_service.pyでもfrom importが成功するようになりました。

python リスト内の*について

1
2
3
4
5
6
7
8
9
10
def test(x):
return x * 2


a = [[3,2,1],[5,4,6],[5,4,6]]
a = [*map(lambda x: test(x), a)]
print(a)

# print出力
[[3, 2, 1, 3, 2, 1], [5, 4, 6, 5, 4, 6], [5, 4, 6, 5, 4, 6]]

このようなコードがあって、[*map(の部分が何をしているのか分からなかったので調べました。

結論

map()の返り値のリストを引数展開して、リストを定義している。

詳細

リストの前に*をつけると引数展開される

1
2
3
print(*[1, 2, 3])
# print出力
1 2 3

参考url

http://pixelbeat.jp/variable_length_arguments_and_argument_unpacking/

他の [ ]系 の変則的な書き方

Numpy Boolean Index

Numpy arrayのIndexにBooleanのリストを渡すと、リストのTrueの位置と一致する値だけにできる。

1
2
3
4
5
6
import numpy as np
test = np.array([1000, 2000, None])
print(test[[False, True, True]])

# print出力
[2000 None]

参考url

https://qiita.com/junjis0203/items/4136f9ae4f07c452ceb6#boolean-index%E3%81%A8%E5%80%A4%E8%A8%AD%E5%AE%9A

コマンドラインインターフェイスのオプションについて

コマンドラインでオプションの引数を指定する時に、半角スペース=を利用する違いについて気になったので調べました。

調査結果

オプションの引数が省略できる場合だと半角スペースが、オプション引数を省略した形かコマンドの引数か曖昧なので=の指定が必要。

詳細内容

コマンドラインアプリケーションごとに違いはありますので grep を基準にします。

まずファイルを作成します。

1
2
3
4
5
6
7
cat > test.txt
test
hoge
poyo
poke
111
control+d

man grep をすると、–after-context=num でnum行分を一致した行以降も表示しれくれるとなっています。

1
2
-A num, --after-context=num
Print num lines of trailing context after each match. See also the -B and -C options.
1
2
3
4
5
~/Desktop ❯❯❯ grep test test.txt --after-context=3
test
hoge
poyo
poke
1
2
3
4
5
~/Desktop ❯❯❯ grep test test.txt --after-context 3
test
hoge
poyo
poke

–after-context=num 、–after-contextnum のどちらでも受け付けてくれます。

man grep をすると、–colour=never で一致した箇所の色付けを消してくれるとなっています。[when]になっているのでオプションの引数は省略できます。

1
2
3
--colour=[when, --color=[when]]
Mark up the matching text with the expression stored in GREP_COLOR environment variable. The possible
values of when can be `never', `always' or `auto'.
1
2
~/Desktop ❯❯❯ grep test test.txt --colour=never
test
1
2
3
~/Desktop ❯❯❯ grep test test.txt --colour never
test.txt:test
grep: never: No such file or directory
1
2
~/Desktop ❯❯❯ grep test --colour test.txt
test

–colour=never は受け付けてくれますが、–colournever はneverがオプションの引数とは認識されずに検索対象のファイル名と認識されました。
確かにオプションの引数が省略できる場合だとそれが、オプションの引数かコマンドの引数か曖昧なので=の指定が必要なことは納得できますね。

参考url

http://docopt.org/ : -o --option の項目
https://qiita.com/rubytomato@github/items/2ee2fd4127eadc1f1193
https://qiita.com/aosho235/items/0f2b73d08eb645c05208

This version of ChromeDriver only supports Chrome version {vesion番号}

エラー This version of ChromeDriver only supports Chrome version 〇〇

SeleniumのWebdriverでChromeを動かしているとThis version of ChromeDriver only supports Chrome version 81とエラーメッセージが表示されました。
chromeのバージョンが自動アップデートされて、webdriverとchromeのバージョンが合わなくなったので表示されたようです。
ですので普段利用するchromeとは別に、seleniumで利用するchromeをインストールしてchromeの自動アップデートを無効にする方法を調べたのですが、個別にアップデートを抑制する方法が見つからず。

ChromiunだとChromeと同じ機能で自動アップデートされない

そんな時に、ChromiumだとChromeとほぼ同じ機能で自動アップデートされないという情報を見つけたので、
Webdriverのversionに対応する、Chromiumをダウンロードして解決しました。

Chromiumの過去バージョンのダウンロードurl

https://chromium.woolyss.com/

GoogleIME変換候補登録

GoogleIMEで「餘根津」という旧字体を含んでいたり特殊な名字を「よねず」から変換しようとしても
候補には「米津」とか「米酢」しかでてこないと思います。
それがよく利用する単語なのに変換ででてこないと面倒ですよね。
そんな時の解決方法としてGoogleIME単語登録があります。
変換候補の単語を登録すると、変換候補に出てくるようになります。

CQRSとマテリアライズドビュー

検索の一覧ページでパフォーマンスが問題になることがありますが、
マテリアライズドビューを利用することでパフォーマンス改善ができます。
mysqlではマテリアライズドビューの機能が無いので、
マテリアライズドビューのようなSQL結果を保存するテーブルを作成し、CQRSで更新をおこない利用することでパフォーマンスを改善することができます。

(例)SNSでユーザーに多くの投稿があって最新の投稿内容について検索内容が一致するユーザーを一覧で表示する場合に、
マテリアライズドビューをユーザーと最新の投稿の中間テーブルとすると
下記のような最新の投稿を特定するクエリが必要なくなることでパフォーマンス改善になる。

1
left join posts as p2 on posts.created_at < p2.created_at where p2.id is null

CQRS マテリアライズドビュー 更新フロー図
CQRSとマテリアライズドビューの更新フロー図

参考url

https://slideship.com/users/@miyake/presentations/2018/04/5JgW9hp3kHDDZi6zzDRxbm/?p=8
http://nippondanji.blogspot.com/2015/06/rdb.html
https://blog.spacemarket.com/code/room-search-speed/
https://docs.microsoft.com/ja-jp/azure/architecture/patterns/materialized-view
http://qcontokyo.com/data_2016/pdf/B-2_2_JunichiKato.pdf

https://docs.microsoft.com/ja-jp/azure/architecture/patterns/materialized-view

Laravel で参考のコードを書いてみました。

https://github.com/unamu1229/sampleapp/commit/948a6a6809ecf421629ddf18ca54bef44195e94c

処理の流れ

CommandSelectionエンティティ(コマンド用エンティティ)が CommandSelectionRepositoryリポジトリ(コマンド用リポジトリ)で永続化される

CommandSelectionRepositoryリポジトリがイベントを発生させる(新規作成時:PushCommandSelection 更新時:PutCommandSelection)
※ドメインイベントではないので、リポジトリでイベントを発生させてよいのではないかと思いました。
識別子からクエリ用のエンティティを作成する時も永続化されてからでなければ、最新の状態をとってこれないこともありますし。

リスナーでイベントを受ける(イベントPushCommandSelectionの場合、PushQuerySelection。イベントPutCommandSelectionの場合、PutQuerySelection。)

リスナーがQuerySelectionエンティティ(クエリ用のエンティティ)を作成し、QuerySelectionRepositoryリポジトリ(クエリ用リポジトリ)でマテリアライズドビュー的な永続化を行う。

amazonアフェリエイト 知り合いのリンクを通して購入すると知り合いは紹介料を貰えるのか?

推測:貰えるのではないか? → 結果:貰えません

アマゾンアフェリエイトの利用規約では、自己購入は禁止されていることは自明なのですが、知人からアフェリエイト購入した時に知人に紹介料金がつくことは禁止されていなさそうです。

Amazonアソシエイト・プログラム運営規約

https://affiliate.amazon.co.jp/help/operating/agreement

運営規約の紹介料の項目を見る限り、紹介料を支払いしない条件について知人や家族のために自己購入した場合は紹介料の発生はしないと明記されていますが、知人のリンクを通して購入することに関しては触れられていません。

乙自身、友人、親類その他の関係者のため乙が特別リンク経由で購入した商品など、乙によりまたは乙を代理して、特別リンク経由で購入された商品(例えば、個人的注文、乙自身の使用のための注文および他の個人もしくは企業のためまたはこれらを代理して、乙により発注された注文)。

補足

「乙」は、加入申込者を意味します。

結果

amazonから下記のメールが来てアフェリエイトアカウントが削除されました。
知人からアフェリエイト購入してあげることは規約違反になりました。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
いつもAmazon アソシエイト・プログラムをご利用いただき、誠にありがとうございます。

本日付で、お客様のアソシエイト・プログラムアカウントを閉鎖させていただきました。

お客様のアカウントが閉鎖となった理由:
Amazonアソシエイト・プログラムの継続的監視の一環として、当社はお客様のアカウントを再調査しました。
調査により、当社は、お客様が以下に記載の運営規約を遵守していないと判断しました。

Amazonアソシエイト・プログラム運営規約: <https://affiliate.amazon.co.jp/help/operating/agreement>

違反には以下が含まれます:

-貴殿のサイトの特別リンク経由で行われた購入は、個人的な使用、再販、商業的使用、または貴殿の友人、親戚、従業員、請負業者、ビジネス関係者によるものです。

お客様にご対応いただきたい内容:
お客様のサイト内にあるAmazonマークの使用を中止し、Amazonサイトへのすべてのリンクを速やかに削除しなければなりません。

運営規約違反と判断致しましたので、閉鎖されたアカウントの再開、および該当のアカウントについての紹介料の支払いは行われません。また、Amazonは、その裁量で予告なく、ご利用中の別アカウントまたは今後作成されるアカウントを閉鎖し、紹介料の支払いを停止する権利を留保します。

なお、限定的ではありますが、本閉鎖については不服申立が可能である場合がございます。詳細については、ここに記載の「不服申立」のヘルプを参照してください。<https://affiliate.amazon.co.jp/help/node/topic/GACDBRFKVDTXSPTH>.

Amazon.co.jp カスタマーサービス アソシエイト・プログラムスタッフ

何故プログラミングで小数の値がずれるのか

結論

小数に2進数で表現できないものが多くあるから。

どうして2進数で表現できない少数があるのか

例えば十進数で0.9の場合にそれを2進数で表現しようとすると、
小数点第一位 だと 1/2(0.5) 小数点第二位 だと 1/4(0.25) 小数点第三位 だと 1/8(0.125)と 少しずつ 0.5 + 0.25 + 0.125 = 0.875と0.9に寄っては行くが、
それをfloat型(単精度浮動小数点形式)の仮数部23回をおこなっても0.9と一致することはない。

検証JSコード

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var n = 0;
var nishinsu = 0.5;
var amari = 0.9;
var counter = 0;
while (n !== 0.9 && counter < 23) {
counter += 1;
if (amari >= nishinsu) {
n += nishinsu;
}
amari = amari % nishinsu;
nishinsu = nishinsu / 2

console.table({'counter':counter, 'number':n, 'amari':amari, 'nishinsu':nishinsu})
}

ビジネスロジックバリデーションの例外の種類

ビジネスロジックのバリデーションは DomainException を継承したものを投げる

バリューオブジェクトやエンティティやドメインサービスで投げられることの多いビジネスロジックのバリデーションの例外ですが、
その例外はphpstormのdocコメントにて@throwsが必要な(Exceptionをextendしたもの)で投げるべきかコメントが必要ないDomainExceptionを継承したもので投げるべきかを悩んでいたのですが、
DomainExceptionを継承したもので投げるべきだと私の中で答えがでました。

入力フォームなどでビジネスロジックのバリデーションの例外をキャッチして、Viewに表示したいことがあり、@throwsが必要な例外だとcatchすることが明示的なのでそっちかなと思ったのですが。
下記のスライドを見てビジネスロジックの例外を投げるクラスからしたら、システムを落とすように例外を投げることを推奨していたので DomainException を継承してビジネスロジックのバリデーションは投げるべきだなと決めました。
では、落とすように例外をなげたらそれをキャッチしてはいけないかというとそうではなくて、アーキテクチャ/フレームワーク等では逆に落とさないようにcatchすることを推奨しています。

https://speakerdeck.com/twada/php-conference-2016?slide=56
こちらのスライドである通り、

1
2
3
ミクロでは正当性を重視し、マクロでは堅牢性を重視する
個々のクラスは正当性を重視し、堅牢性はアーキテクチャ/フレームワーク等で保証するのがオススメ。
例:個々のクラスはfail fast原則で書き、Webフレームワークやグローバルハンドラがキャッチして500エラー画面等を出す責務を負う

とありました。
正当性と堅牢性とか意味が分からなければ、このページの5ページ前ぐらいから読むといいと思います。

また、Viewに表示したいから@throwsが必要な例外を投げるとかドメインがViewに配慮する考え方もおかしいですよね。

ビジネスロジックのエラーは例外的状況である

そもそもビジネスロジックのバリデーションで例外を投げるのはおかしい、
例外は例外的な状況にだけ利用するべきだと意見されたことがあるのですが、
それは、例外的な状況の縮小解釈です。
https://qiita.com/kata/items/bd129ba6113a61126389#%E9%A0%85%E7%9B%AE57-%E4%BE%8B%E5%A4%96%E7%9A%84%E7%8A%B6%E6%85%8B%E3%81%AB%E3%81%A0%E3%81%91%E4%BE%8B%E5%A4%96%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B
に書かれている通り、

1
ArrayIndexOutOfBoundsExceptionを使用して配列のループ処理の脱出するなどアホな事はしない

このレベルでの状況で例外を使うなということで、ビジネスロジックのバリデーションエラーについては例外的状況と捉えてよいと考えます。

また、こちらのスライドの14ページに
https://www.slideshare.net/t_wada/exception-design-by-contract

1
2
3
例外は例外的な状況にだけ利用するべき
例外は、その名が示す通り、例外的状況に対してのみ使用するべきです。
通常の制御フローにたいしては、決して使用すべきではありません。

とありますが、この通常の制御フローを示すものも前のページでのループを抜ける制御のレベルで使うなといっていますし。
15ページの

1
2
3
例外は例外的な問題のみに使用すること
「すべての例外ハンドラーを除去しても、このプログラムは動作することができるだろうか?」
答えが「ノー」であれば、例外では無い状況下で例外が使われている

についても、ビジネスロジックの例外のキャッチをすべて行わなくても動作することはできます。
29ページにて

1
2
技術的例外とビジネス例外を明確に区別する
技術的例外は貫通させてフレームワークに任せる。ビジネス例外は準正常系なので呼び出し側で対処する

ビジネスロジックのバリデーションの例外を準正常系として利用することを認めています。