Posts for: #Dapr

dapr のアップグレード準備

1時に寝て7時に起きた。寝る前に閃光のハサウェイを見始めたら夜更ししてしまった。

dapr の Highly-available モードの検証

先週からテスト環境で dapr の Highly-available mode を試している。ついでに dapr の 1.8.x へのアップグレードも行う。Dapr v1.8 is now available をみると、一番上に書いてあるのだから pubsub サービスの Dead letter topics がもっとも注目すべき新機能と言えるのだろう。これは pubsub のミドルウェアすべての Dead letter topics の機能が実装されたことを言っている。うちは rabbitmq を使っていて、それは次の pr で v1.5 で追加されていて、うちの環境では v1.7 から実運用していた。rabbitmq は Dead letter topics 対応が始まった初期のうちに実装されたと言える。

現時点での dapr の最新の安定版は 1.8.5 になる。

Highly-available を有効にする設定ファイル values.yml の書き方は次になる。

global:
  ha:
    enabled: true

来週には本番環境への適用&アップグレード作業を行うので wiki の作業手順のドキュメントを書いてた。

helm リポジトリ設定の更新。

$ helm repo add dapr https://dapr.github.io/helm-charts/
$ helm repo update
$ helm search repo dapr --versions | grep 1.8.5
dapr/dapr	1.8.5        	1.8.5      	A Helm chart for Dapr on Kubernetes

任意の設定を施した values.yml を指定して dapr をアップグレードする。

$ helm upgrade dapr dapr/dapr --version 1.8.5 --namespace dapr-system --values ./values.yml --wait

dapr はデフォルトで dapr-system という名前空間を使う。アップグレードした helm のパッケージ情報を確認する。

$ helm list -n dapr-system

traceparent の生成

1時半に寝て7時半に起きた。ちょっと疲れてて寝坊した。

W3C Trace Context の traceparent ヘッダーの生成

前にお仕事で dapr の分散トレーシングを検証している ことについて書いた。

dapr の分散トレーシングは W3C Trace Context に準拠していて、dapr 経由のリクエストは自動的にこの情報が付与されるが、そうじゃないリクエストもトレーシングできるようにするためには http ヘッダーの traceparent をセットしないといけない。試しにサーバー側に traceparent を生成するのはどうやるのかを調べてみた。Implementations of Trace Context にある java ライブラリを調べていて、Jaeger クライアントは OpenTelemetry に移行したと書いてあって、OpenTracing と OpenCensus は OpenTelemetry に統合されたと書いてあって、どうやら OpenTelemetry を使うのがよさそうだとわかった。

やりたいことは traceparent を生成したいだけだが、OpenTelemetry の Manual Instrumentation を読んでも直接的なやり方は書いてなくて、open-telemetry/opentelemetry-java のテストコードなどもみながら実装した。細かいところの仕様をまだ理解できていないけど、ひとまずこれで生成できたので検証はできると思う。

public class W3cContextUtil {

    private static final String TRACE_PARENT_VERSION = "00";
    private static final OpenTelemetrySdk openTelemetry = OpenTelemetrySdk.builder()
            .setTracerProvider(SdkTracerProvider.builder().build())
            .setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance()))
            .buildAndRegisterGlobal();
    private static final Tracer tracer = openTelemetry.getTracer(
            "my-tracer", "1.0.0");

    public static String generateTraceParent() {
        Span span = tracer.spanBuilder("parent").startSpan();
        try {
            SpanContext sc = span.getSpanContext();
            return String.format("%s-%s-%s-%s",
                    TRACE_PARENT_VERSION,
                    sc.getTraceId(),
                    sc.getSpanId(),
                    sc.getTraceFlags().asHex());
        } finally {
            span.end();
        }
    }
}

大阪Python もくもく会

大阪Python もくもく会 #66 にオンライン参加した。コロナ禍前に大阪へ通勤していた頃はオフライン勉強会に何回か参加したことがある。主催者のやぎさんは一度 bizpy に参加してくれたこともある。11月からオフライン勉強会を再開したとのこと。久しぶりに参加してやぎさんと話していたら neosvr にも関心をもっているとのこと。私も少し前に oculus quest 2 を購入して触ってみた程度なのでメタバース関連で一緒に勉強会をしてもよいかもしれない。もくもく会では「アジャイル開発とスクラム 第2版」を読んでいて昨日の日記の記事がまさにその成果物。せっかくなので成果発表でこの本の紹介などをした。

2年目の創立記念日

0時半に寝て6時半に起きた。久しぶりに22時までお仕事やって区切りもよかったからそれからお惣菜を買って23時頃から晩ご飯を食べてた。生活が乱れるなぁ。

dapr の分散トレーシングと W3C trace context

お仕事で dapr の分散トレーシングを検証してた。知らない人は Dapr Advent Calendar 8日目 - DaprとZipkinで分散トレーシング のチュートリアルをお勧めする。dapr は W3C Trace Context を使って分散トレーシングを扱う。rest api では、具体的には traceparenttracestore という http ヘッダーにトレース用途の情報を付けて転送する。すごいところは pubsub のメッセージングを経由してもそれらの情報を転送できる。pubsub 間でこれらの情報は CloudEvents という標準化されたデータのフォーマットでやり取りされる。実際には CloudEvents の中に traceparenttracestore の値を含めて通信するけれど、外部からみたら http ヘッダーを転送できているようにみえる。しかし、http ヘッダーの任意の値を転送したい場合、それができない。tracestore はトレースのためのベンダー独自情報を付与できるとあったので、ここに任意の値をセットして送ってみたけど、http ヘッダーの付け替えは行われなかった。あとで dapr のソースを読んだら publish するときはそのまま送っているけど、subscribe するときに tracestore の仕様を満たしているか検証しながらパースしていて、任意の値を送っても仕様に沿っていなければ捨てられてしまうことがわかった。dapr の issue でも要望として登録されてた。誰もやってないならコントリビュートするチャンスかもしれない。

創立記念日

今日が会社の創立記念日。無事に2周年を迎えた。創立記念日をお休みにするしないを考えたのだけど、いま休日も普通に働いている状況で、且つ役員は勤怠管理をする必要はないので平日になんの意味もなく休むメリットが何もないということに行き着いた。創立記念日だから休むのではなく、いつでも必要なときに休めばいい。もっと言うと、休む理由がなければ働くという逆転現象が生じていて、休む理由は私用か疲労ぐらいしかなくて、基本的に疲れてない限りはずっと働くみたいな理屈になってしまっている。社員が増えて会社に余裕が出てから創立記念日は休みみたいな制度を作ればいい。それまではたぶん来年もそれ以降も普通に働いていると思う。

1年目は訳分からず働いていたから経営的なことは全くわからなかったけど、2年目は経営上の諸問題が出てきて、経営的な意思決定や考察も増えてきて、行政手続きも熟れて、会社の実績も増えていっていて、会社を育てるという意識もかなり出てきた。率直に言えば、いまの経営状態は可もなく不可もなくといったものなので何もアピールすることはない。しかし、経営したことない人間が経営というキャリアを積み重ねていることには大きな意義があって、自身のキャリアアップには確かな手応えも感じつつある。これからもがんばっていこう。

頭文字Dを読了

0時に寝て7時に起きてだらだらやってて午前中は 頭文字D のアニメをみてた。漫画 (アニメも?) はすでに完結しているのでいつか読もうと思いつつ最後まで読んでいない。ゴッドフットやゴッドアームが出てくるぐらいまでは読んだ気がする。その後どうなったのかを知らない。イニシャルDをみていると、ストーリーも絵も演出もまったく派手さはなくて普通なんだけど、なぜかおもしろくて続きをみてしまうという人間の娯楽の本質をついている気がしてくる。なんでなんだろうなぁ。

頭文字D

たまたま思い出したので夜に漫画喫茶行って頭文字Dを最後まで読んできた。全48巻で、31巻ぐらいから読み始めて3-4時間ぐらいで読み終えた。漫画なので仕方ないけど、対戦相手がどんどん強くなっていって勝ち方が玄人好みというのか、単純に抜いた・抜かれたの話しではなく、タイヤマネージメントがどうこうとか、恐怖に対する心理がどうこうとか、ドライバーと車のセッティングも含めた駆け引きが強くなっていって、どちらが速いかというよりは戦略通りの展開にもっていって最後はそれがうまくはまるみたいな、これまでもずっとそうだったんだけど、ここからはよりトップレベルのほんの僅かな差が勝敗を分けるといった描き方になっていったように思う。それはそれで現実に近い気はするけど、漫画的には派手な演出にならないので玄人好みなストーリーになっていった気がする。但し、そこまでやってきて最後の対戦相手だけは、個人的には納得感がなくて、ここまで緻密に作り上げてきた理論や個々のドライバーの修練の積み重ねが圧倒的天才の前にひれ伏すみたいな切り口が急展開していて、頭の切り替えができなかった感じがした。とはいえ、最後まで読み終えられてよかったし、作品としてはすごくおもしろかった。作者はモータースポーツが本当に好きなんだろうなというのが伝わってくる漫画だと思う。

ふるさと納税

あまり欲しいものもないし、ふるさと納税の行政手続きも一通り理解したから今年はやらなくてもいいかとも思っていた。しかし、paypayボーナスキャンペーン をみてやってみるかという気になった。paypay はいろんなものと連携していて見かけるたびにすごいなと思う。お得だからと必要もないものを買うことはないけど、ふるさと納税はやらなかったとしても、どのみち納税は必要なものなので還元があるということは節税につながるのかな?理屈はよくわからないけど、言いたいことは paypay はすごいという話でした。

dapr の api トークンを使った認証

Enable API token authentication in Dapr を一通り読んだ。内容はとくに難しくなく、こんな風に dapr の manifest を書けば JWT トークンを設定できますということを書いてある。私はずっとサーバーサイドばっかりやってきたからフロントエンドで使われる技術や仕組みに弱い。JWT トークンもその1つで、自分でちゃんと実装したことがないからちゃんとよく分かってない。これが OAuth2 なら provider を実装したこともあるからその仕組みも意図も理解できる。一度どこかで自分で JWT も実装してみないといけないのだろうな。

少し前にお仕事で kubernetes の secret の移行作業をやった。既存の secret にキーバリューを追加するときは patch を使う。

$ kubectl patch secret mydata -p='{"stringData":{"mykey": "myvalue"}}'

secret の内容を確認するときも2つのやり方がある。キーだけを確認するならこれでよい。

$ kubectl describe secrets mydata

キーに対応する値もデコードして確認するならこうする。但し、閲覧注意。

$ kubectl get secret mydata -o json | jq '.data | map_values(@base64d)'

師走入り

1時から1時間ほど仮眠をとって2時から4時過ぎまで作業して帰ってお風呂に入ってそのまま6時から 【三宮.dev オンライン】リモート朝活もくもく会 の朝活に参加した。30分ほど雑談して眠くなって7時過ぎから9時前まで寝てた。

dapr の pubsub の dead letter サポート

お仕事で dapr を触っている。pubsub で dead letter queue の仕組みを導入しようとしているが、PubSub’s DeadLetter Topic #2217 によると v1.6 (2022年1月20日リリース予定) のマイルストーンになっている。本当にその予定ならそろそろベータ版が実装されていて、開発ブランチあったらテストしようかと考えていた。調べてたら rabbitmq はすでに v1.5 で dead letter のサポートがマージされているのを発見した。

たまたま、いま使っている pubsub も rabbitmq だった。ドキュメントをみたら確かにその設定が追加されている。

dapr RabbitMQ

FieldRequiredDetailsExample
enableDeadLetterNEnable forwarding Messages that cannot be handled to a dead-letter topic. Defaults to “false”“true”, “false”
maxLenNThe maximum number of messages of a queue and its dead letter queue (if dead letter enabled). If both maxLen and maxLenBytes are set then both will apply; whichever limit is hit first will be enforced. Defaults to no limit.“1000”
maxLenBytesNMaximum length in bytes of a queue and its dead letter queue (if dead letter enabled). If both maxLen and maxLenBytes are set then both will apply; whichever limit is hit first will be enforced. Defaults to no limit.“1048576”

enableDeadLetter=true に設定して、適当にエラーが発生しそうなリクエストを作って dead letter にメッセージが入るかどうかを検証してた。ひとまず dead letter にメッセージが入ること自体は確認できた。

bizpy 勉強会

Python で Slack のインテグレーションをやってみる勉強会 #3 を開催した。月曜日から2時間もあればできる資料作成をだらだら先送りしていて夜中に作った。なんか体調を崩しているのかもしれない。たまたま勉強会の前にせらさんから激励のコメントをいただいて嬉しかった。

今日の分も含めコンテンツ拝見しましたが、素晴らしいですね

私見だけど、slack インテグレーションで調べものをしているとせらさんの記事や issue のやり取りをみかけることが多い。twitter で slack インテグレーションに関してつぶやくと100%せらさんからレスポンスがある (個人の経験談) 。過去に私は外資の ISV で働きたいと思って活動したこともあったけど、せらさんをみていて自分のレベルでは無理だったなと得心がいった。なにがすごいって、bizpy の勉強会のようなところにもわざわざやってきて、講師にコメントしたりアドバイスしてくれるんだからね。

2ヶ月に渡り、slack インテグレーションのチュートリアルレベルの記事を実際に設定してみて、サンプルコード書いてみて、動かしてみて、slack でどんなことができそうかの理解を深めることができた。今回の内容はビジネスパーソン向けではなかったのでちょっと敷居が高かったかもしれないが、全3回でやり切ることができてよかった。終わってから運営に新たにわたなべさんが加わったことを参加者に紹介しつつ、次回の企画について雑談していた。次回はわたなべさんから機械学習入門のような勉強会をしてもらうことに決まった。

調べものだらけ

1時半に寝て6時に起きた。昨日の夜はウォーキングして (朝活あるから) すぐに寝たんで早く起きた分、朝からストレッチをしてた。今週はバタバタしていてあまりストレッチできてない。

朝活: ミクロ経済学入門の入門

[金朝ツメトギ] 2021-11-05 AM 6 金曜朝6時開催のもくもく会 で第7章の独占と寡占を読んだ。用語を次にまとめる。

  • プライステイカー: 生産量を増やしたり減らしたりしても価格に影響を与えられない会社
  • 完全市場: すべての会社がプライステイカーである市場
  • 不完全市場: 完全市場ではない市場、プライステイカーではない会社がいる
  • 独占市場: 1つの独占企業だけが存在する市場
  • クルーノー寡占市場: 同じ財を生産する少数の会社の総生産量から市場の価格が決まる市場
    • 寡占: 少数の企業がいる市場
      • 複占: 企業が2つだけの市場

前に出てきた市場均衡の話から、供給量を下げると価格が上昇する。生産者余剰がが大きくなり、生産者は得をする。実際にあった事例として、2016年に石油輸出機構 (OPEC) が石油の減産に合意して価格が上昇した。2012年に豊作だった歳に値崩れが起きるのをおそれて、全国農業組合連合会は価格を上げるために農家に野菜の廃棄処分を要請した。

独占市場にいる会社は高い価格で高い利潤を得ることはできるが、やがて価格競争を仕掛けてくる新規参入者を招き、長期的な利益を低めてしまう懸念がある。一方で高品質な財を低い利潤で販売していると、新規参入者が現れずに長期的な利益を得られる可能性がある。一概にどちらが正しいとは言えない。こうした状況を端的に描く 展開型ゲーム を考えると、財を高値にするか安値にするかの思考実験ができるう。 ゲームツリー という図でこのゲームを表している。

A は安値を選び、B が参入しないという選択の組み合わせは、「自分がこう選択したら相手はこう選択してくる」とプレイヤーが予想して、そのうえで自分にとって最も利潤が高まる選択をする状況を表している。これを サブゲーム完全均衡 の結果と呼ぶ。また、このような推論のやり方を 逆向き帰納法 (バックワード・インダクション) と呼ぶ。サブゲーム完全均衡の結果は逆向き帰納法により求められる。

RabbitMQ の dead letter exchange の調査

昨日の続き。RabbitMQ には exchange という概念がある。私が過去に使ったメッセージキュー (Kafka, AWS SQS) にはない概念でトピックをグルーピングしたり、メッセージのルーティングを制御する仕組みになる。普通のメッセージキューではデッドレターキューと呼ばれるものが RabbitMQ だと Dead Letter Exchanges になる。ドキュメントの概要はこんな感じ。

次のイベントが発生したときに “デッドレター” とみなす。

  • consumer が basic.reject または requeue=false の basic.nack を ack で返したとき
  • メッセージの TTL の期限切れになったとき
  • queue の最大長さを超えてメッセージが drop されたとき

注意事項として queue の有効期限が切れても queue 内のメッセージはデッドレターとならない。

設定方法

デッドレター exchange (DLXs) は普通の exchange であり、普通に宣言して通常の種別をセットする。任意の queue に対して2通りの設定方法がある。

  • クライアント: queue の引数を使って定義する
  • サーバー: ポリシーを使って定義する

詳細は割愛。

ルーティング

デッドレターメッセージのルーティングは、次のどちらかで行われる。

  • デッドレターの queue に routingKey が設定されていればそれを使う
  • デッドレターの queue に routingKey が設定されていなければ、オリジナルのメッセージが publish されたときの routingKey を使う

例えば、foo という routingKey をもつ exchange にメッセージを publish して、そのメッセージがデッドレターになった場合、foo という routingKey をもつデッドレターの exchange に publish される。もしそのメッセージが x-dead-letter-routing-key を bar にセットした queue に届いた場合は、そのメッセージは bar という routingKey をもつデッドレター exchange に publish される。

queue に特定の routingKey が設定されていなかった場合、その queue のメッセージは、すべてオリジナルの routingKey でデッドレター化されることに注意してください。これには CC および BCC ヘッダによって追加された routingKey も含む (詳細は割愛) 。

デッドレターメッセージが循環する可能性がある。例えば、queue がデッドレター用のルーティングキーを指定せずに、デフォルトの exchange にメッセージをデッドレターした場合などに起こる。このとき同じ queue に2回届いたメッセージは no rejections in the entire cycle だった場合にドロップされる。

安全性

デッドレターメッセージは内部的に publisher confirm を行わずに re-publish される。クラスタ環境の rabbitmq でデッドレターキューを使ったとしても安全性は保証されない。メッセージはデッドレターキューの対象の queue に publish された後でオリジナルの queue からは削除される。このときに対象の queue が受け取れなければメッセージがなくなってしまう可能性がある。

デッドレターメッセージの副作用

デッドレターメッセージはヘッダーを変更する。

  • exchange の名前がデッドレター exchange の名前に置き換わる
  • routingKey がデッドレターキューの routingKey に置き換わる可能性がある
  • ↑ が起きると、CC ヘッダーが削除される
  • Sender-selected Distribution ごとに BCC ヘッダーは削除される

デッドレターの処理では x-death という名前の配列を、それぞれのデッドレタリングされたメッセージのヘッダに追加する。この配列には {queue, reason} のペアで識別される各デッドレタリングイベントのエントリが含まれる。詳細は割愛。

dapr の調査

dapr について調べた。dapr は分散システム (アプリケーション) の複雑さを解決することを目的としている。様々なミドルウェア (分散システム) とのやり取りを http/grpc の api 呼び出し経由にして、その詳細を隠蔽する。ミドルウェアの上位に抽象化レイヤーを設けて統合的なインターフェースを提供したり、それぞれのミドルウェアにおける設定や運用の面倒なことなどを簡略化してくれる。サイドカーパターンを採用しているので言語に依らず、アプリケーションに dapr のコードを書く必要もない。dapr cli をインストールして dapr init すると docker で dapr プロセスが動いて、それだけで dapr にリクエストできるようになる。使い始めの学習コストは低いし、デプロイも簡単だし、意図している目的もわかりやすい。マイクロソフト社がスポンサーしていてプロジェクトの運営も安定してそうだし、おもしろいツールだと思う。

k8s の調査

せっかくの機会なのでちゃんと勉強することにした。今日は minikubeGet Started! やっただけ。