👋 Hi there! I’m Keisei Kinjo (J.C.)

  • A Mandarin-Japanese-English trilingual DevOps Engineer base in Tokyo. 👨‍💻🗼
  • A basketball and fingerstyle guitar enthusiast. 🏀🎸
  • I hope you find something useful here. If you have any questions or comments, feel free to reach out to me via email. dtjp[@]tutanota.com

自作PCからUbuntu22.04開発環境構築してみた

更新履歴 2022/06/26: 初稿 2024/04/20: 起動時I/O error, dev sda, sector xxxxxxxxxxのエラーが発生した。smartctlで確認したところ、問題がなかったので、手順の最新化を行い再度インストールした アップルをはじめとして、最近スペックがそこそこ良いPCがわけわからないくらい高くなり、誰でも使える個人用のコンピュータというPersnal Computerの趣旨と乖離しています。独断と偏見ですが、せっかく数十万円でPCを購入したのにもかかわらず、 パーツ交換不可なので、数年後は電子ゴミになり、自然環境に優しくない 不要なソフトウェア・サービスが多い(たとえば、2022年なのに、バージョン管理非対応のクラウドサービスiCloudが大きなシェアを占めているっていう皮肉) なんとかStoreの通知がうるさい。利用するのにアカウント(個人情報)が必要 プライバシー侵害問題 … https://www.theguardian.com/world/2021/oct/15/apple-plan-scan-child-abuse-images-tears-heart-of-privacy 別にゲーマーではないですが、数十万払ったのに自由が奪われる感じがどうしても気に入らないので、自作PCからLinuxの開発環境を構築することにしました。 ハードウェア 秋葉原まで行く元気がなかったので、すべてのパーツはAmazonやメルカリから購入することにしました。また、PCパーツの価格変動が激しいのでkeepaのメール通知機能を活用すると簡単に低価格でお気に入りのパーツ狙えます。 https://keepa.com/ 最終的に以下のパーツを買いました。 Model Price Motherboard ASUS Intel B560M-A ¥10,563 CPU Intel Core i5 10400 ¥18,943 GPU ASUS GTX 1650-4G DUAL ¥21,500 Power 玄人志向 KRPW-BK 80PLUS Bronze 750W ¥5,535 Memory KLEVV DDR4 2666 PC4-21300 8GB*2 ¥7,002 Storage Crucial SSD 500GB MX500 ¥5,980 CPU Cooler CPUクーラー 虎徹 Mark II ¥3,400 Case SAMA JAX-03W (second hand) ¥4,480 LAN cable ¥945 Total ¥78,348 あくまで筆者の例ですが、他のパーツに替えても全然問題がありません。パーツ間の互換性と電源容量だけ気をつけてください...

April 20, 2024 · Me

打工人炒股的錯覺

趁着今天全球股市暴跌,來簡單聊聊打工人炒股的錯覺,以及我的策略。 打開推特好多人都在用中文聊炒股炒幣買房。最近跟公司同事去聚餐只要聊到炒股炒幣炒FX(拉槓桿炒外匯)或者買房,幾乎所有人都滔滔不絕,長篇大論發表觀點。 而一個簡單的事實是,長期來看經濟大餅越確實是在做越大,但短期的股市漲跌取決於市場對於經濟的預期(不是實際情況,只是預期)。牛市之下,大家都能輕鬆靠著炒股短期賺到錢,但牛市永遠不可能長久,短期投資個股或對於大多數打工人來說不見得是個好的策略。 炒股好像會給我們打工人一種錯覺,會讓我們覺得我們有那麼一瞬間我們從勞方變成了資方,有機會不依靠勞動僅僅靠著決策就能在短期內賺進鈔票。不可否認確實也有人是這樣成功的,但跟書店琳琅滿目的成功學書籍一樣完全不具有任何普遍性和可再現性。而且投資跟投機其實本質上並無差別,都是某種形式上的賭博,靠著承擔一定的風險來獲利。再者,炒股炒幣花費時間精力,最終的營收不僅反應在最後的數字上,還需要考慮到時間成本,精力成本,甚至是心理成本。算上這些看不到的無形成本,炒股的收益率估計也就不剩多少了。 但是,作為打工人能不炒股嗎? 顯然完全不炒股也不可取,就連長年通縮的日本也進入了通脹時代,不炒股就只能等著資產縮水。另外,日本政府從幾年前開始學習英國的ISA推出了名為NISA的投資稅收減免政策,其實意思就是說按照現在的少子高齡化進展,以後養老金很大可能會不夠用,所以政府也想鼓勵民眾加入資本市場的遊戲。 我個人的觀點是,我們首先需要承認並考慮清楚我們的現狀 我們多數打工人是凡人不夠聰明 沒有一手信息源 運氣不可能一直好 分析公司財報大多數情況是浪費時間 基於以上現實,用免稅額度長期定投風險相對較低的S&P500等優質ETF就完全足夠了,個股黃金期貨外匯加密貨幣一律不碰,甚至不買房(跟A Random Walk Down Wall Street書中的觀點類似)。把炒股看K線的時間用來多陪伴家人,或者打球,看書,寫碼,練琴等興趣愛好,甚至是刷推特都可能更加有意義。

April 19, 2024 · Me

NodeにTaintsがついている場合、Datadog DaemonSetにTolerationsを忘れないでね!

マネージド型k8sのDaemonSet EKSなどのKubernetesマネージドサービスは、DaemonSetを介してNodeにkube-proxy, ebs csi, cniなどのPodを適切に配置してくれます。 k8sドキュメントに記載している自動的に追加されるTolerations以外で、ワイルドカードのTolerationsもデフォルトで入っています。 tolerations: - operator: Exists EKS管轄外のDaemonSet しかし、DatadogなどEKS外でデプロイされたDaemonSet Podsを入れる際に、TaintsがついているNodeにPodがスケジューリングされないため、注意が必要です。 解決方法としては、ドキュメントに書かれているように https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/#taints-and-tolerations You can add your own tolerations to the Pods of a DaemonSet as well, by defining these in the Pod template of the DaemonSet. DaemonSetのPodテンプレートにtolerationsを定義することです。 tolerations: - operator: Exists また、このようなワイルドカードのTolerationsを追加するのは便利かもしれないですが、(EKSの場合)Fargateにスケジューリングされてしまうので、Affinityもちゃんと書きましょう affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: eks.amazonaws.com/compute-type operator: NotIn values: - fargat 余談ですが、同じくDaemonSet介してデプロイされるfluent bitでは、不必要なTolerationsによるバグが過去起きていました。 https://github.com/aws-samples/amazon-cloudwatch-container-insights/issues/61

January 15, 2024 · Me

潤日進階: 如何DIY歸化日籍🇯🇵

本文可以轉載,但請附上這個博客的URL 寫這篇文章的理由 用日文谷歌搜索「日本国籍帰化」結果多半是行政書士們用於營業推廣的文章,可能因為利益相關,多數不是很詳細整理的也不是很系統,另外信息也比相對較陳舊沒有一直更新。本文的目的是詳細描述DIY歸化日籍的整個過程,為後來人提供方便。 花幾十萬日圓找行政書士也以節約不少時間,但中國方面的資料依然還是需要自己獲取,大家可以看完這篇文章之後再權衡一下。 記得當時我DIY日本留學的時候也是在知乎(當年的知乎)上查到一個叫蘇菲的前輩寫的文章,然後自己將文中的內容付諸實踐,最後沒有經過語言學校大學畢業後直接旅遊簽證考試然後入學修士。因爲我是小鎮做題家而且家庭條件也完全談不上好,那篇文章可以說是改變了我的人生軌跡。現在我想做的是把我微不足道的經驗分享給想要知道的人。 前提 本文主要針對於來自中國且已經持有長期簽證在日本留學或者工作並且想要歸化的朋友。如果人還在中國的話,建議首先參考有名的潤學項目的其他文章再來閱讀此文 本文只談方法論,關於要不要「潤」以及日本適不適合潤等話題本文不做討論 本文內容全部基於筆者自身2022-23年(或者更早)的經驗,可能會過時或者跟你的情況有所偏差,如果有事實性錯誤歡迎提出issue, PR 也歡迎其他形式的PR 歸化所需要的材料因人而異,作爲補充整理到了cases裏,請對比閱讀 歸化的條件 日本的國籍法第五條是這樣寫的, 居住条件(国籍法第5条1項1号) 引き続き5年以上日本に住所を有すること 能力条件(国籍法第5条1項2号) 20歳以上で本国法によって行為能力を有すること 素行条件(国籍法第5条1項3号) 素行が善良であること 生計条件(国籍法第5条1項4号) 自己又は生計を一にする配偶者その他の親族の資産又は技能によって生計を営むことができること 重国籍防止条件(国籍法第5条1項5号) 国籍を有せず、又は日本の国籍の取得によってその国籍を失うべきこと。 不法団体条件(国籍法第5条1項6号) 日本国憲法又はその下に成立した政府を暴力で破壊することを企て、若しくは主張し、又はこれを企て、若しくは主張する政党その他の団体を結成し、若しくはこれに加入したことがないこと 挑選出其中的一部分稍微詳細說明一下。以下都是慣例沒有明文規定,或者說從官方的資料查不到相應的內容,但在申請的過程中可以瞭解到。 首先關於「居住條件」,說的是5年但按照一般經驗上來講,我申請過程中瞭解到其中的至少3年必須要工作並且正常納稅,也就是單單來日本留學念了5年書並不能申請。另外這個「引き続き」的定義也值得注意,跟申請用住類似,一年之內離開日本超過150天或者單次超過90天過去的話通常會從0開始計算。也就是有大半年或者有過長時間離開日本的經歷會被判定為將來不想在日本長居。 關於「素行條件」,就是說你不能偷稅漏稅(包括保險年金)或者過去有案底 。只要自己遵守規則準時繳納了稅金跟社保完全不是問題,如果就職於正規的公司的話每個月稅跟社保都會直接從工資扣除因此完全不需要擔心。過去就算有過輕微的交通事故,在申請的時候詳細說明情況問題應該也不大。 「生計條件」就是說你得有個穩定的工作能養活你自己跟你的家人,沒有硬性規定收入多少而且我個人覺得不是很嚴格。 「重国籍防止条件」這點就更好理解了,日本也不承認雙重國籍也就是說取得日籍之後必須放棄原來的國籍,這對持有中國國籍的人來說應該沒有任何影響,因為中國也不承認雙重國籍。準確來說在中國如果你不是鐮刀應該不可能擁有多本護照。 下面介紹幾個在申請過程中我所瞭解到的隱藏條件。 日語水平法律沒有明確要求但至少要有小學低年級水平,面談的時候即便你有N1證書也還是會測試你的日語能力 如果你剛剛跳槽在新公司未滿一年,通常不會讓你申請,在他們看來頻繁換工作意味着不穩定。在一家公司至少買一年後才能夠申請 如果有同居人(這裏指的是還沒有結婚的男女朋友),同居人的身份證明跟納稅的材料也需要提交 時間線 下面整理一下歸化的時間線 (滿足上述條件之前半年)第一次面談 (滿足條件之前兩個月)第二次面談 (滿足條件的當月)第三次面談 (滿足條件的當月)提交申請 (申請三個月後)法務局面試 (面試三個月後)法務局來電 (兩週後)歸化結果通知 (一週後)放棄中國國籍拿到歸化相關的證明書 (一週後)辦理戶籍相關的手續 整個過程前後接近1年半,需要有點耐心。還有就是上述時間線是我綜合幾個朋友的平均結果,樣本數很少應該會有不小的偏差,僅供參考。 歸化的通過率很高,走完這個漫長的過程基本上就成功了。換句話來說只要法務局讓你提交申請,成功率就已經在90%以上了。數據來自日本政府官方的統計 乍看很難,如果把歸化看作一個項目,分階段完成的話其實難度也不大。整個過程中你還會發現日本各個行政部門之間儘管做事方式落後缺少互相交流且效率低下,但卻都很很認真能把整件事情事無鉅細地全部辦完,還挺有意思的,扯太遠了,回到主題。 需要打交道的實體 歸化涉及到的材料很多,並且日本跟中國的材料都需要。並且如果有配偶小孩,或者有工資以外的收入則需要的材料會更多。獲取這些材料需要跟以下實體打交道。 中國 中國戶籍所在地的公證處 在老家的父母 中國駐日大使館領事部 日本 法務局 区・市役所 警察局 年金事務所 就職的公司 大學 整個過程至少需要去6次法務局,2次中國大使館領事部,2次居住地的区・市役所,1次中國國內的公證處。別的因人而異,具體需要什麼材料以及如何獲取會在後面的詳細步驟中說明。請行政書士可以減少你去法務局的次數,有沒有價值這裏不做判斷。 舉例說明 羅列了一遍時間線跟需要打交道的實體可能還是有點不太好理解,我舉兩個相對比較普遍的例子儘量解釋詳細一點。 例1 有日本留學經歷 周樹人,於2016年10月來到日本念語言學校,其間他順利考上早稻田大學的修士,與2018年4月入學 2020年3月畢業之後從2020年4月起開始在株式会社XYZ工作。 他想在法律層面上儘快脫離中國,因此想要在滿足條件之後立馬就進行申請。 按照上面講的至少五年居住其中三年納稅的原則,周樹人最早可以於2023年4月滿足條件進行歸化申請。然而第一次面談可以提前半年左右,也就是2022年10月他其實就可以去法務局面談,但想要面談的人很多而且需要提前預約,大概2022年6月左右就可以提前預約同年10月的歸化面談。...

November 29, 2023 · Me

自作プロキシサーバで海外のサービスを利用しよう

本記事に書かれていることを実践する際は自己責任でお願いします。不都合などが生じた場合、責任を負いかねます。 背景 日本のインターネット環境は比較的自由ですが、海外のサービスを利用際には大人の諸事情によってサイトがリダイレクトされて利用できない場合があります。 制限されるのはあまり気持ちよく感じないのとWeb閲覧時自分のプライバシーを保護するため、 先日自作プロキシサーバを自作しました。 本記事では主にHowに焦点を当てて紹介します。関連技術のWhatとWhyについては深く言及しないので、公式ドキュメントまたは他の解説記事をご参照ください。 雑なアーキテクチャ図 利用技術・サービス AWS Lightsail 仮想プライベートサーバ 3ヶ月無料 $3.5/月 ムームードメイン 3000~4000円/年(申請するドメインによる) gost OSS Webサービスを装うために使う Cloudflare gostを使うのに必要 無料プランで十分 SwitchyOmega OSS クライアント側の設定 あくまでも一例で最適解ではないです。 事前準備 VPS(仮想プライベートサーバ)を契約 今回は、AWSが提供しているLightsailという軽量仮想プライベートサーバのサービスを利用しますが、EC2やHerokuなど他のサービスを利用する場合もまったく問題ありません。リージョンは日本以外(例えばUS)に設定しておきます。AWSのCLIを利用する場合、AWS IAMなどを設定する必要がありますが、今回は基本的にいじらなくても良いです。 Lightsailでサーバを立ち上げたら、AWS CloudShellからサーバにアクセスできます。ローカルに慣れている方はキーをダウンロードして、sshでアクセスしても構いません。 念のため、 curl ipinfo.io を実行して、設定しているリージョンの住所と一致しているか確認します。 また、HTTPSを利用するため、Networking -> IPv4 FirewallからHTTPSを追加しておきます。 ドメインを取得 昨今の円安の影響で海外のドメインレジスターサービス(例えばGoDaddy)がかなり高くなっているため、国内サービスムームードメインを利用してドメインを取得しました。 Cloudflareアカウントを作成 WebサービスでもないなのになぜわざわざCloudflare使う理由 簡単に言えば、VPSのIPがブロックされる可能性はゼロではないのとプロバイダ側にIPアドレスを変更してくれないケースが多いためです。CloudflareなどのCDNサービスを挟むことでわずかな遅延が発生するかもしれませんが、可用性を向上させることができます。また、Cloudflareは無料枠を提供しており、WebSocketプロトコル (gostを使うのに必要なもの)に対応しているため、今回ユースケースに適しています。 ログインした後ガイダンスにしたがってネームサーバを設定します。 続いて、ムームードメインからデアフォルトのネームサーバを変更します。 詳細はネームサーバのセットアップ方法(GMOペパボ以外のサービス)にご参照ください。 最後はサブドメインのレコードを追加して、立ち上げたサーバのIPアドレスと紐付けます。 IPv4 FirewallにHTTPSを追加しておかないと動かないので気をつけてください。 https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-subdomain/ 事前準備が完了したので、いよいよサーバ側を設定を始めます。 サーバ側の設定 Dockerエンジンをインストール Docker公式ドキュメントを参考にしてDockerエンジンをインストールします。 # Add Docker's official GPG key: sudo apt-get update sudo apt-get install ca-certificates curl gnupg sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download....

October 17, 2023 · Me

GCS composeで32以上のオブジェクトをまとめる方法

先日の記事にてパーティション化されたCSVオブジェクトをCloudSQLにimportする方法を紹介しました。 SDKを利用して32より多いオブジェクトをまとめる場合、GCPのコミュニティのチュートリアルのコードをそのまま使っていました。(2023.8.10にアーカイブされ済み) https://github.com/GoogleCloudPlatform/community/blob/master/archived/cloud-storage-infinite-compose/index.md 文章最後に書いてあるように This code is offered for demonstration purposes only, and should not be considered production-ready. Applying it to your production workloads is up to you! コードはデモ用途のため、そのまま本番環境で使うのはで推奨しないです。先日この文を見逃して自分の環境にデプロイし、平常運転1ヶ月後、パーティション化されたCSVオブジェクトの数が増えたらバグが出ました。 事象 起きていた事象は、composeによって作られた中間オブジェクトが消されず残り続け、最終的に数TBのとてつもなく大きいオブジェクトが作成されてしまいました。一つのオブジェクトは5TiBまでというGCSの上限を超えてしまうため、処理が失敗しました。 どこがバグ 問題は関数compose_and_cleanupから呼び出している関数delete_objects_concurrentにあります。オブジェクトをまとめた後、毎回中間オブジェクトを削除していますが、そのdelete処理自体が非同期処理ですべての処理が終了するのを待たずに次のblob.composeの実行が始まります。 The delete_objects_concurrent function is very simple, using fire-and-forget delete tasks in an executor. A more robust implementation might check the futures from the submitted tasks. チュートリアルの中にちゃんと書いてあります。(もっとロバスト性のある実装は、submit済みのタスクのfuturesをチェックするとのこと) まとめようとするオブジェクトの数が少ない場合はほとんど問題がないですが、1000オブジェクトあたりを超えるとdeleteがcompose処理より遅くなるため、next_chunkが永遠に存在しているままwhileループから脱出できない状態になります。 delete処理自体は特に制限ないようですが、数百のオブジェクトを削除する場合時間かかるとドキュメントに記載されています。 https://cloud.google.com/storage/docs/deleting-objects#delete-objects-in-bulk 解決方法 最初に試したことは、記事に書いてあるようにsubmit済みのタスクのfuturesをwait処理でチェックします。つまりすべてのdelete処理が終わるまでに、compose処理を行いません。 (python並行処理の詳細は公式ドキュメントまたは他の記事をご覧ください) from concurrent.futures import ALL_COMPLETED, ThreadPoolExecutor, wait def delete_objects_concurrent(blobs, executor, client) -> None: """Delete Cloud Storage objects concurrently....

August 17, 2023 · Me

パーティション化されたCSVファイルをCloudSQLにimportする方法

問題 パーティション化されたCSVファイルをCloudSQLにimportする場面は時々あると思います。 残念ながらCloudSQLはBigQueryのようにwildcardsによるimportを対応していません。需要はあるようですが↓ https://issuetracker.google.com/issues/132058570?pli=1 ファイルごとにimportするとオーバーヘッドが毎回発生するため、速度的に実用性があまりないと思います。一方、importはオペレーションの1種なので、並列処理はできません。 https://cloud.google.com/sql/docs/troubleshooting#import-export HTTP Error 409: Operation failed because another operation was already in progress. There is already a pending operation for your instance. Only one operation is allowed at a time. Try your request after the current operation is complete. なので、ファイルを結合してimportするのはより現実的な解決策だと思います。 gsutil compose gsutil composeを利用すると、GCSにある複数のファイルを結合できます。 cliのみならず、SDK(google.cloud.storage.Blob.compose)も同じ機能が提供されています。 https://cloud.google.com/storage/docs/composing-objects#create-composite-client-libraries https://cloud.google.com/storage/docs/gsutil/commands/compose ただし、結合できるファイルは最大32個という制約があります。 There is a limit (currently 32) to the number of components that can be composed in a single operation....

August 16, 2023 · Me

AirflowからDataformにdata_interval_endなどのcontext変数を渡す方法

先日GCPのDataformがGAリリースされました。 せっかくなので、まずAirflowにある既存ワークフローの一部をDataformで書き換えようと思いました。 AirflowからDataformをトリッガーする ドキュメントを調べると、AirflowからDataformをトリッガーするoperatorはすでに存在しています。 https://cloud.google.com/dataform/docs/schedule-executions-composer#create_an_airflow_dag_that_schedules_workflow_invocations 簡単にまとめると DataformCreateCompilationResultOperator: sqlxをsqlにコンパイルする DataformCreateWorkflowInvocationOperator: sqlを実行する しかし、どのようにAirflowからDataformへ変数を渡すかについてはドキュメントに記載されていません。 Dataformに変数を渡す まず、Dataformの設定ファイルdataform.jsonに変数varsを追加しておきましょう。 { "defaultSchema": "dataform", "assertionSchema": "dataform_assertions", "warehouse": "bigquery", "defaultDatabase": "project-stg", "defaultLocation": "asia-northeast1", "vars": { "bq_suffix": "_stg", "execution_date": "2023-05-24" } } DataformCreateCompilationResultOperatorのソースを調べてみたところ、compilation_resultという引数があることを発見しました。 https://github.com/apache/airflow/blob/739e6b5d775412f987a3ff5fb71c51fbb7051a89/airflow/providers/google/cloud/operators/dataform.py#LL73C29-L73C46 compilation_resultの中身を確認するため、APIの詳細を調べました。 https://cloud.google.com/dataform/reference/rest/v1beta1/CodeCompilationConfig CodeCompilationConfig内にvarsという変数を指定できるようです。 { "defaultDatabase": string, "defaultSchema": string, "defaultLocation": string, "assertionSchema": string, "vars": { string: string, ... }, "databaseSuffix": string, "schemaSuffix": string, "tablePrefix": string } BigQueryのsuffixをcode_compilation_configのvarsへ渡してみたら問題なく実行できました。ちなみに、Dataform側からはdataform.projectConfig.vars.bq_suffixで変数を呼び出せます。 DataformCreateCompilationResultOperator( task_id="create_compilation_result", project_id=PROJECT_ID, region=REGION, repository_id=REPOSITORY_ID, compilation_result={ "git_commitish": GIT_COMMITISH, "code_compilation_config": { "vars": { "bq_suffix": "_stg", } }, }, ) Dataformにcontext変数を渡す 増分処理する際によくdata_interval_endなどのcontext変数を利用して当日の差分だけ取り入れます。 しかし、DataformCreateCompilationResultOperatorではtemplate_fieldsが実装されていないため、直接{{ data_interval_end }}のようなjinjaテンプレートを渡すことはできません。...

May 24, 2023 · Me