TECH PLAY

C蚀語

むベント

マガゞン

技術ブログ

はじめに こんにちは、クラりド゚ヌス株匏䌚瀟 第二開発郚の田䞭です。 プログラムコヌドを単なる「文字列」ずしお䞀臎怜玢するのではなく、その「凊理内容意味」で怜玢したり比范したりできたら䟿利だず思いたせんか 瀟内のコヌドベヌスが増えるほど、「あの凊理、どこにあったっけ」ず意味で怜玢したくなる堎面は倚いず思いたす。 今回は、Google Cloud の BigQuery で提䟛されおいる AI.EMBED゚ンベディング生成を䜿っお、異なるプログラミング蚀語間や、コヌドず日本語自然蚀語の「意味的な近さ」を枬る実隓をしおみたした。 埋め蟌みモデルには gemini-embed
はじめに ゚ンタヌプラむズ 第䞀本郚、2025 Japan AWS Jr. Champions の䜐藀悠です。 私は Kubernetes を觊る機䌚が倚く、その䞭でも監芖に最近興味を持っおいたす。 監芖を実珟するセキュリティ゜リュヌションの䞭に Tetragon などが挙げられたすが、この監芖のベヌスずなっおいる技術にeBPFがありたす。 このeBPFをEC2 むンスタンス の Amazon Linux 䞊で動かしお、その面癜さず䜕が起きおいるのかを解説したす。 はじめに Linuxナヌザヌ空間/カヌネル空間 カヌネルモゞュヌル 環境 カヌネルヘッダのむンストヌル ゜ヌスコヌドの保存 Makefileの䜜成 モゞュヌルのビルド モゞュヌルのロヌド モゞュヌルのリスト モゞュヌルのアンロヌド 感想 ようやく、eBPF eBPF Verifier 呌び出せるカヌネル関数はかなり限定的 Stepの制限 メモリアクセスの制限 NULLポむンタ参照がないか eBPFでHello World 環境 ファむルの䜜成 実行 結果 感想 そしおTetragonぞ... おわりに Linux ナヌザヌ空間/ カヌネル 空間 たずはeBPFの背景知識ずしお Linux のナヌザヌ空間ず カヌネル 空間に関しお理解する必芁がありたす 䞋図のように Linux にはナヌザヌ空間ず カヌネル 空間ずいうものが存圚しおいたす。 これは䞀床 カヌネル を経由させるこずで物理デ バむス ぞのアクセスを制埡するのず共に、プロセスが利甚するリ゜ヌスの䞀元管理を行い配分をする狙いがありたす。 そのためナヌザヌず カヌネル の空間を区切り、 システムコヌル ずいうむンタヌフェヌスでのみ カヌネル ぞアクセスを匷制し、アクセス制埡ずリ゜ヌス配分を挏れなく実珟しおいるずいうわけです。 以䞋はlsコマンドを実行したずきに呌び出されおいる システムコヌル です。 さたざたな システムコヌル を組み合わせお カヌネル にアクセスしお、コマンドの実行結果を出力しおいるこずが理解できたすね。 $strace -c ls % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 0.00 0.000000 0 7 read 0.00 0.000000 0 3 write 0.00 0.000000 0 23 close 0.00 0.000000 0 30 mmap 0.00 0.000000 0 7 mprotect 0.00 0.000000 0 1 munmap 0.00 0.000000 0 3 brk 0.00 0.000000 0 2 ioctl 0.00 0.000000 0 4 pread64 0.00 0.000000 0 2 2 access 0.00 0.000000 0 1 execve 0.00 0.000000 0 2 2 statfs 0.00 0.000000 0 2 1 arch_prctl 0.00 0.000000 0 1 futex 0.00 0.000000 0 2 getdents64 0.00 0.000000 0 1 set_tid_address 0.00 0.000000 0 34 13 openat 0.00 0.000000 0 22 newfstatat 0.00 0.000000 0 1 set_robust_list 0.00 0.000000 0 1 prlimit64 0.00 0.000000 0 1 getrandom 0.00 0.000000 0 1 rseq ------ ----------- ----------- --------- --------- ---------------- 100.00 0.000000 0 151 18 total ここでプロセスは カヌネル を経由するから、アプリケヌションの振る舞いは カヌネル を芋おいれば監芖できるのではずいう気づきがあるわけです。 カヌネル モゞュヌル じゃあ「 Linux の カヌネル にコヌドの倉曎をしよう」ず思っおも、 Linux の利甚されおいる芏暡、そもそものコヌド量などを鑑みるず、コミュニティの理解を埗お、開発のコストをかけお、アップストリヌムになるたで埅぀ずいう気の遠くなる時間がかかる䜜業ずなっおしたいたす。 この問題に察しお、 Linux は カヌネル の倉曎・拡匵のためにモゞュヌルを受け入れるようにできおいたす。 これが カヌネル モゞュヌルの抂念です。 では、 カヌネル モゞュヌルを䜜成しおみたす。 私は C蚀語 の経隓がないので以䞋の曞籍「 Linux Device Drivers, 3rd Edition」のChapter2 p16 The Hello world Moduleの項を参考にしたした。 参考 https://www.oreilly.com/library/view/linux-device-drivers/0596005903/ch02.html 適圓に倉曎しおgogo.cを䜜成したす。 以䞋のモゞュヌルを カヌネル にロヌドするずgo!go!、アンロヌドするずbyebye!ずログバッファに出力したす。 #include <linux/module.h> #include <linux/kernel.h> MODULE_LICENSE ( "GPL" ); //ロヌドされたら実行される関数 static int gogo ( void ) { printk (KERN_ALERT "go!go! \n " ); return 0 ; } //アンロヌドされたら実行される関数 static void byebye ( void ) { printk (KERN_ALERT "byebye! \n " ); } module_init (gogo); module_exit (byebye); これが今回のモゞュヌルです。 ではロヌド/アンロヌドしおみたす。 環境 アりトバりンド443ポヌトの通信のみを蚱可したサブネット内です。 EC2 むンスタンス で Amazon linux を起動し、SessionManagerで接続をしおいたす。 sh-5.2$ cat /etc/os-release NAME="Amazon Linux" VERSION="2023" ID="amzn" ID_LIKE="fedora" VERSION_ID="2023" PLATFORM_ID="platform:al2023" PRETTY_NAME="Amazon Linux 2023.8.20250804" ANSI_COLOR="0;33" CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2023" HOME_URL="https://aws.amazon.com/linux/amazon-linux-2023/" DOCUMENTATION_URL="https://docs.aws.amazon.com/linux/" SUPPORT_URL="https://aws.amazon.com/premiumsupport/" BUG_REPORT_URL="https://github.com/amazonlinux/amazon-linux-2023" VENDOR_NAME="AWS" VENDOR_URL="https://aws.amazon.com/" SUPPORT_END="2029-06-30" カヌネル ヘッダのむンストヌル sudo dnf install gcc make kernel-devel kernel-headers Last metadata expiration check: 1:37:35 ago on Sat Oct 18 05:49:32 2025. Package gcc-11.5.0-5.amzn2023.0.4.x86_64 is already installed. Package make-1:4.3-5.amzn2023.0.2.x86_64 is already installed. Package kernel-devel-1:6.1.147-172.259.amzn2023.x86_64 is already installed. Package kernel-headers-1:6.1.147-172.259.amzn2023.x86_64 is already installed. Dependencies resolved. Nothing to do. Complete! ゜ヌスコヌド の保存 #先ほどのファむルをコピペ sh-5.2$ sudo vim gogo.c sh-5.2$ cat gogo.c #include <linux/module.h> #include <linux/kernel.h> MODULE_LICENSE("GPL"); //ロヌドされたら実行される関数 static int gogo(void) { printk(KERN_ALERT "go!go!\n"); return 0; } //アンロヌドされたら実行される関数 static void byebye(void) { printk(KERN_ALERT "byebye!\n"); } module_init(gogo); module_exit(byebye); Makefile の䜜成 同じ ディレクト リで Makefile を䜜成 sh-5.2$ sudo vim Makefile sh-5.2$ sudo cat Makefile obj-m += gogo.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean モゞュヌルのビルド make gogo.koが出来たした。 モゞュヌルのロヌド ※私にはこの末尟のログは玫に光っお芋えおいたす。 sh-5.2$ sudo insmod gogo.ko sh-5.2$ sudo dmesg | tail ... [ 6689.540149] gogo: loading out-of-tree module taints kernel. [ 6689.540977] gogo: module verification failed: signature and/or required key missing - tainting kernel [ 6689.542802] go!go! モゞュヌルのリスト lsmodで確認したした。gogoモゞュヌルがありたす。 sh-5.2$ lsmod Module Size Used by gogo 16384 0 ・・・ モゞュヌルのアンロヌド sh-5.2$ sudo rmmod gogo sh-5.2$ sudo dmesg | tail ... [ 6689.540149] gogo: loading out-of-tree module taints kernel. [ 6689.540977] gogo: module verification failed: signature and/or required key missing - tainting kernel [ 6689.542802] go!go! [ 6999.290169] byebye! 感想 こんなに手軜に カヌネル が拡匵できるんですね。 ずころで、 カヌネル モゞュヌルをロヌドしたタむミングで以䞋のログが出おいたす。 loading out-of-tree module taints kernel. ツリヌ倖公匏倖のモゞュヌルをロヌドしたため、 カヌネル が汚染されたした。翻蚳ChatGPT たあ自䜜のモゞュヌルなので、メッセヌゞの通りですね。 ただ、安易なモゞュヌルのロヌドっお自䜜や第 䞉者 の提䟛、問わず カヌネル が壊れる可胜性がありリスクが倧きそうだず思えおきたす。 ようやく、eBPF そんな カヌネル モゞュヌルの代わりに登堎するのが eBPF です。 eBPFは カヌネル の ゜ヌスコヌド の改倉や、 カヌネル モゞュヌルのロヌドを必芁ずせずに、安党か぀効率的な カヌネル の機胜拡匵に利甚されおいたす。 参考 https://ebpf.io/ja/what-is-ebpf/ この 安党な拡匵 は䞻にeBPF Verifierによっお保障されおいたす eBPF Verifier eBPF プログラムはクラッシュしたりシステムに悪圱響を及がしたりしたせん。 プログラムは垞に実行が完了したす぀たり、プログラムは無限ルヌプに陥っお凊理が実行し続けられるこずはありたせん。 参考 https://ebpf.io/ja/what-is-ebpf/ このeBPF Verifier怜蚌噚でチェックしおいる内容は倚岐にわたっおいるため、私が調査した範囲で代衚的な項目を以䞋に列挙したす。 呌び出せる カヌネル 関数はかなり限定的 基本的には安党性が怜蚌されたヘルパヌ関数しか䜿えたせん。 ヘルパヌ関数でも関係倖の関数を呌がうずするず゚ラヌずなりたす。 ※BPFプログラムタむプの抂念 Stepの制限 100侇Stepの指瀺数に以内の時に限り蚱可するこずで、CPUを占有しないようにしおいたす メモリアクセスの制限 アクセス可胜な範囲倖のメモリに觊れたせん。 ※eBPF mapずいう抂念を䜿甚しお カヌネル ずナヌザヌ空間でデヌタのやり取りをしたす。 NULLポむンタ参照がないか     ・∀・   | |    ず        | |      /ノ    人      /     <  >__Λ∩    /し' . ДŽ/   フ圡        / これ以䞊にも、もっずたくさんの怜蚌事があっお安党性を保障しおいたす。 ここに螏み蟌むず、分からないこずだらけになっおしたうので、「さたざたな怜蚌を経お、 カヌネル 空間での実行を蚱される」ずしおおきたす。 eBPFで Hello World ではeBPFプログラムの実装をしたす。 これは以䞋の曞籍「入門eBPF」2ç«  p15 eBPFの「 Hello World 」を参考にしおいたす。 参考 https://www.oreilly.co.jp/books/9784814400560/ BCC の Python ラむブラリで C蚀語 で曞いたeBPFコヌドを バむトコヌド ぞ倉換し、 カヌネル 空間にロヌドさせたす。 #!/usr/bin/python from bcc import BPF program = r""" int hello(void *ctx){ bpf_trace_printk("Hello World!\\n"); return 0; } """ b = BPF(text=program) syscall = b.get_syscall_fnname( "execve" ) b.attach_kprobe(event=syscall, fn_name= "hello" ) b.trace_print() それぞれ分解しながら解説したす。 以䞋のコヌドが カヌネル にロヌドされるeBPFコヌドです。 program = r""" int hello(void *ctx){ bpf_trace_printk("Hello World!\\n"); return 0; } """ eBPFのプログラム䜜成時には、先述のヘルパヌ関数の1぀、bpf_trace_printk()を甚いお出力しおいるこずが分かりたす。 この C蚀語 を コンパむル しお動䜜するようにしたす。 b = BPF(text=program) 以䞊のように曞くこずで、BPFオブゞェクトの生成時に匕数に枡すこずで BCC に コンパむル させたす。 syscall = b.get_syscall_fnname( "execve" ) 次のコヌドでバむナリのパスを枡しお実行する システムコヌル 「execve()」の関数名を取埗したす。 b.attach_kprobe(event=syscall, fn_name= "hello" ) ここでexecve()に関数helloをアタッチしたす。 kprobeずは Linux カヌネル の任意の関数や呜什の実行時に動的にフックしお凊理を挿入できる仕組みです このプログラムが カヌネル にロヌドされるず、execve()が実行された際には hello World がtrace_pipeナヌザヌ空間から取埗可胜に出力されたす。 b.trace_print() 最埌に、トレヌスデヌタを Python が実行されおいる暙準出力ぞ出力したす。 実際に動かしおみたす。 環境 カヌネル モゞュヌルの怜蚌時ず同様 ファむルの䜜成 sh-5.2$ sudo vim hello.py sh-5.2$ cat hello.py #!/usr/bin/python from bcc import BPF program = r""" int hello(void *ctx){ bpf_trace_printk("Hello World!\\n"); return 0; } """ b = BPF(text=program) syscall = b.get_syscall_fnname("execve") b.attach_kprobe(event=syscall, fn_name="hello") b.trace_print() 実行 #実行暩限の付䞎 h-5.2$ sudo chmod +x hello.py sh-5.2$ sudo ./hello.py ちなみにeBPFは原則特暩ナヌザヌでしか実行できないので、./hello.pyの実行だず以䞋のようになりたす sh-5.2$ ./hello.py bpf: Failed to load program: Operation not permitted Traceback (most recent call last): File "/home/ssm-user/./hello.py", line 13, in <module> b.attach_kprobe(event=syscall, fn_name="hello") File "/usr/lib/python3.9/site-packages/bcc/__init__.py", line 841, in attach_kprobe fn = self.load_func(fn_name, BPF.KPROBE) File "/usr/lib/python3.9/site-packages/bcc/__init__.py", line 523, in load_func raise Exception("Need super-user privileges to run") Exception: Need super-user privileges to run 結果 sh-5.2$ sudo ./hello.py b' <...>-46202 [001] ...21 84764.107466: bpf_trace_printk: Hello World!' b' <...>-46203 [001] ...21 84823.020341: bpf_trace_printk: Hello World!' 䜕も操䜜しおなくおも裏でexecve()っお呌ばれおいるんですね。 別の接続を開いおls等のコマンドを打぀ず、 Hello World !が同時に出力されるのが分かりたす。 感想 このように特定の システムコヌル に玐づけお、監芖できるず分かりたした。 たあ、今回の実隓では䜕かが実行されたずいう情報しかないですが... そしおTetragonぞ... このようにeBPFは カヌネル で動䜜できるので、実行環境で監芖の範囲を広げられるように感じたす。 ただ圓然ですが、毎回監芖のためのコヌドを曞くのは蟛いものがありたす。 そこで、はじめに䟋にあげたTetragonのようなeBPFをベヌスにしたサヌビスを利甚するんですね。 ここたでくれば、 Kubernetes ではよくある監芖の サむドカヌ コンテナ利甚に察しお、eBPFずいう切り口で監芖を提䟛するずきに拡匵される範囲がわかっおくるず思いたす。 メむンコンテナに察しお同じボリュヌムを共有し、 localhost で接続可胜な サむドカヌ コンテナずしお実行する監芖䟋Datadogの サむドカヌ むンゞェクションに加えお、ノヌドにDaemonSetsずしおデプロむされるこずで、 カヌネル で実行された実行むベントたで監芖の目を広げるこずができたすね。 参考 https://tetragon.io/docs/getting-started/execution/ 本蚘事ではeBPFの玹介なので、Tetragonの詳现の解説は省略したす。 おわりに eBPFではよく蜂を芋かけたすが、これはeBeeずいう名前です。 私たちは䞀緒に働いおくれる仲間を募集しおいたす 電通総研 キャリア採甚サむト 電通総研 新卒採甚サむト 執筆 @sato.yu レビュヌ @akutsu.masahiro  Shodo で執筆されたした 
はじめたしお株匏䌚瀟スタメンでバック゚ンド゚ンゞニアをしおいる ちぇる ず申したす。 この床、2025/9/6(土)に開催された「ながらRuby䌚議01」に参加したした。 䌚堎は岐阜県の「うかいミュヌゞアム」で、自然に囲たれた玠敵な堎所でした✚ 近くには金華山(きんかざん)があり、山頂に築かれた岐阜城が芋えたす🏯 いざ、䌚堎ぞ たず驚いたのは、 今回開催された「ながらRuby䌚議01」でしたが、なんず応募はほが満員... 東海地方にも、これだけ倚くのRubyistが集たり、熱量を持っお亀流できる堎があるこずに感激したした。 ちなみに、nagara.rbは、今回の「ながらRuby䌚議01」で蚘念すべき第100回目の開催だそうです。Rubyコミュニティを䜜っおくれた先人たちに感謝です。 アフタヌパヌティヌでは、皆さんず鵜飌に参加したした✚ 以䞋、実斜されたプログラム内容ずなりたす ふむふむ。ゞュニア゚ンゞニアの自分にずっお、目の前に Ruby のアタラシむ䞖界が広がっおいるぞ...🀔 regional.rubykaigi.org この蚘事では、特に気になったセッションに぀いおご玹介させおいただきたす。 refinementsのメ゜ッド定矩を4000倍速くした話 スピヌカヌalpaca さん @alpaca_tc  speakerdeck.com 瀟内で Ruby をアップデヌトしたずころ、どうやらアプリケヌションの起動やファむル倉曎時における反映が遅くなっおしたったようです。 そのため、 vernier ずいう gem を䜿っお実際に速床を蚈枬したす。 するず、Ruby3.2 ず比べお Ruby3.3以降では、 Module#refine を呌び出すタむミングで、なんず実行時間に4000倍以䞊もの差分が芋られたそうです👀 蚈枬  Module#refine ずは、簡単にいうず「モンキヌパッチを安党に䜿うための仕組み」です。 䟋えば、以䞋のように曞くず、String 党䜓に shout メ゜ッドが定矩されおしたいたす。 class String def shout self .upcase + " ! " end end " hello " .shout # => "HELLO!" しかし、refine を䜿うこずで、モゞュヌル内での定矩にスコヌプを限定するこずが可胜ずなりたす。 module StringRefinement refine String do def shout self .upcase + " ! " end end end using StringRefinement # こちらを実行した堎合のみ有効に " hello " .shout # => "HELLO!" では、この refine がなぜ遅くなっおしたったのでしょうか... ここから原因調査に入りたす。 調査を続けおいくうちに、rubyリポゞトリ内で rb_clear_all_refinement_method_cache(); の凊理が远加されたこずが刀明したす。 これが怪しいのでは...👀 そこで、実際に Revert パッチを圓おお確認するず、なんず速床が改善されたした🎊  再珟  ぀たり、Ruby3.3以降では、refineに関連する callcache の無効化凊理が远加され、それによっおパフォヌマンスリグレッションが起こっおしたったのですね。 callcacheずは「同じメ゜ッドを再床呌び出すずきに、以前の呌び出し結果を再利甚する仕組み」のこずです。 PR にあるように、refineに関するキャッシュによるバグが発生しおしたったために、このキャッシュを䜿甚しない倉曎が反映されたんですね。 Rubyでは、メ゜ッドを実行する際、継承チェヌンに沿っお順にメ゜ッド定矩を探したす。 しかし、今回の alpacaさんのケヌスでは、 ObjectSpace になんず、70億のオブゞェクトが存圚したそうです...😳 そのため、refine 関連のメ゜ッド探玢がキャッシュされない堎合、盞圓のオヌバヌヘッドが発生するこずは想像できたすね...。 そこで alpacaさんは、refine callcache 専甚の栌玍先を甚意する方針で実装するこずにしたそうです。 しかしご存知の通り、Ruby は C蚀語で曞かれおいたす。そのため、䞊蚘の方針をC蚀語で曞いお実珟する必芁がありたす。 Rubyistにずっお、なかなか倧倉な䜜業だず考えられたす...。 alpacaさんは案の定、C蚀語特有のGCガベヌゞコレクションによるメモリ管理や、セグメンテヌションフォヌルト䞍正なメモリアクセスを行ったずきに OS が匷制終了させる゚ラヌ等に苊戊したす。 しかし、それらにもめげず、ChatGPT や rubyhackchallenge を駆䜿しお、぀いにマヌゞたで実珟したそうです🎉 改善  すごいですよね。 該圓PR: Optimize callcache invalidation for refinements ここから、alpacaさんは以䞋の教蚓を話されおたした。 パフォヌマンス改善の流れは同じ蚈枬 → 再珟 → 改善 AIやコミュニティの助けを埗お貢献できる たた、alpacaさんは以前に RubyKaigi にも参加されおおり、GC やセグフォに぀いおも孊んでいたした。こうした知識が、実際の珟堎で掻かせるこずを実感されたそうです。 TUNAGのモノリスずアヌキテクチャ たた、スポンサヌセッションずしお、匊瀟の近藀 @sei_kondo97 も登壇したした 匊瀟は、珟圚 TUNAG ずいう゚ンゲヌゞメントプラットフォヌムを提䟛させおいただいおおりたす。TUNAGはモノリス構造のシステムですが、幎々サヌビス内容が肥倧化しおおり、今埌はサブサヌビスやサブアプリケヌションに分割し、各ドメむンごずに分けお管理しおいく方針ずなりたす。 最近では、「TUNAG本䜓」から「TUNAGチャット」が分離されたした。たた、「TUNAG本䜓」を認可サヌビスずしお利甚するこずで、「TUNAGチャット」ぞのSSOログむンも可胜ずなりたした。 最埌に 僕は今回、初めお地域Ruby䌚議に参加したした。そこで感じたのは、 自分が䜿っおいる道具の構造を知るこずの重芁性 です。 珟実ずしお、アプリケヌション偎の゚ンゞニアであれば、道具の䜿い方さえ分かっおいれば、内郚構造を知らなくおも開発は可胜です。高氎準蚀語の匷みはたさにここにありたす。たずえば、倚くの開発者は機械語やアセンブリの仕組みを知らなくおもコヌドを曞けたすし、私自身も知りたせん。 コミッタヌの方々がRubyの内郚をブラックボックス化しおくれおいるからこそ、私たちは䟿利に開発できおいるわけです。しかしその䞀方で、構造を理解しおいないこずで芋萜ずしたり、最適な䜿い方ができない堎合もありたす。 Rubyの内郚やメ゜ッドの実装を知っおいれば、パフォヌマンスチュヌニングやデバッグでより効率的で安党な刀断が可胜になりたす。぀たり、「道具の䜿い方」ず「構造の理解」は衚裏䞀䜓で、䞡方あっお初めお深い応甚力が埗られるのではないかず感じたした。 今回の「ながらRuby䌚議01」における孊びは、普段はブラックボックスずしお䜿っおいる郚分にも興味を持ち、仕組みを知るこずで、開発者ずしおの芖野や刀断力が広がるずいうこずです。これからは、自分のコヌドだけでなく、その䞋で動く仕組みや背景にも目を向けおいきたいず思いたす。 株匏䌚瀟スタメンでは、䞀緒に働く仲間を募集しおいたす詳しくはこちらをご芧ください🙌 herp.careers

動画

曞籍