<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Posts on meow.md</title><link>https://blog.uzimihsr.com/post/</link><description>Recent content in Posts on meow.md</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Fri, 01 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.uzimihsr.com/post/index.xml" rel="self" type="application/rss+xml"/><item><title>そとちゃん</title><link>https://blog.uzimihsr.com/post/2026-05-01-sotochan/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2026-05-01-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan.JPG" alt="Featured image of post そとちゃん" /&gt;&lt;h2 id="そとちゃん"&gt;そとちゃん
&lt;/h2&gt;&lt;h3 id="2025年11月14日"&gt;2025年11月14日
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://blog.uzimihsr.com/post/2026-02-08-sotochan/" target="_blank" rel="noopener"
 &gt;闘病生活&lt;/a&gt;が続く日のお昼。&lt;/p&gt;
&lt;p&gt;突然そとちゃんが荒い口呼吸をはじめた。&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;少しショッキングな映像なので折りたたみ&lt;/summary&gt;
&lt;div class="video-wrapper"&gt;
 &lt;iframe loading="lazy" 
 src="https://www.youtube.com/embed/aBDg13wWXJw" 
 allowfullscreen 
 title="YouTube Video"
 &gt;
 &lt;/iframe&gt;
&lt;/div&gt;

&lt;/details&gt;
&lt;p&gt;その時が来たか、と思った。&lt;br&gt;
(病院の先生からこういった症状が出ると危険だと聞いていた)&lt;/p&gt;
&lt;p&gt;ある程度覚悟はしていたが、&lt;br&gt;
1人だとおかしくなりそうだったのですぐに病院へ。&lt;/p&gt;
&lt;p&gt;病院に着く頃には呼吸が少し落ち着いており、&lt;br&gt;
検査してもらったが酸素飽和度に問題がないので苦しんではいないようだった。&lt;/p&gt;
&lt;p&gt;呼吸が乱れた原因が腫瘍によるものか分子標的薬の副作用かはもうわからないので、&lt;br&gt;
ひとまず投薬や給餌は中止、点滴のみやろうということになった。&lt;/p&gt;
&lt;p&gt;入院の選択肢もあったがこの日は一旦帰宅。&lt;/p&gt;
&lt;p&gt;帰宅すると急に動き出すそとちゃん。&lt;/p&gt;
&lt;p&gt;&lt;img alt="うろうろしだした" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan01_hu_9962fb8acec2d956.jpeg 800w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan01_hu_ef6e569866e6e7f5.jpeg 1600w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;さっきまでぐったりしていたのが嘘みたいに、&lt;br&gt;
家の中を動き回る。&lt;/p&gt;
&lt;p&gt;&lt;img alt="久しぶりにお風呂場まで行った" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan02_hu_c36a5886eefdc1df.jpeg 800w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan02_hu_14439f43980f1b92.jpeg 1600w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;今思えば、これがエンジェルタイムというものだったのだろう。&lt;/p&gt;
&lt;div class="video-wrapper"&gt;
 &lt;iframe loading="lazy" 
 src="https://www.youtube.com/embed/nRzuc8_v5qE" 
 allowfullscreen 
 title="YouTube Video"
 &gt;
 &lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;そとちゃんは夜までこちらが心配になるくらい活発に動き回った。&lt;/p&gt;
&lt;p&gt;ふらつきながら、でも力強く、&lt;br&gt;
自分のナワバリをしっかりと調べていた。&lt;/p&gt;
&lt;p&gt;夜になるとすこし落ち着いたが、&lt;br&gt;
また少し呼吸が荒くなってしまった。&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;少しショッキングな映像なので折りたたみ&lt;/summary&gt;
&lt;div class="video-wrapper"&gt;
 &lt;iframe loading="lazy" 
 src="https://www.youtube.com/embed/ef4A35qtd_E" 
 allowfullscreen 
 title="YouTube Video"
 &gt;
 &lt;/iframe&gt;
&lt;/div&gt;

&lt;/details&gt;
&lt;p&gt;たくさん撫でると少し呼吸も楽になって、&lt;br&gt;
お気に入りのベッドで安心した様子。&lt;/p&gt;
&lt;p&gt;「また明日元気になってたくさん遊ぼうね、おやすみ」&lt;br&gt;
日付がまわった朝2時半、そとちゃんに語りかけて俺は眠りについた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="寝る前最後に撮った写真" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan03_hu_a0ab17a2b699315f.jpeg 800w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan03_hu_c5d6870a0021c315.jpeg 1600w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan03.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="2025年11月15日"&gt;2025年11月15日
&lt;/h3&gt;&lt;p&gt;次の日の早朝5時。&lt;/p&gt;
&lt;p&gt;休日で普段ならまだ寝ているのに、&lt;br&gt;
この日はやけに早く目が覚めた。&lt;/p&gt;
&lt;p&gt;二度寝前に台所で水を一杯飲み、&lt;br&gt;
そとちゃんの様子を確認する。&lt;/p&gt;
&lt;p&gt;寝ているところに近づくとすぐ起きてしまうそとちゃんだが、&lt;br&gt;
この日は目覚めることがなかった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="最後まで生きた" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan04_hu_1a0ec9a715914801.jpeg 800w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan04_hu_6f3439ce97d60b61.jpeg 1600w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;涙がとまらなかった。&lt;/p&gt;
&lt;p&gt;たくさん感謝の言葉をかけた。&lt;/p&gt;
&lt;p&gt;謝罪の気持ちもあったけど、それよりも感謝を伝えたかった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="病院できれいにしてもらった" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan05_hu_e15277d4f44171ea.jpeg 800w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan05_hu_ecc5eec6de638573.jpeg 1600w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan05.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;少し落ち着いてから、&lt;br&gt;
正式な診断とその後の処置をしてもらうためにいつもの病院へ。&lt;/p&gt;
&lt;p&gt;早朝だったのでいつもと違う先生、看護師さんだったが、&lt;br&gt;
とても優しい言葉をかけていただいた。&lt;/p&gt;
&lt;p&gt;「最後まで本当に素敵なねこちゃんでしたね、がんばりましたね」&lt;br&gt;
そういった言葉でそとちゃんと自分をたくさん褒めてもらった。&lt;br&gt;
その度に涙が出た。&lt;/p&gt;
&lt;p&gt;自分を責めることがないように言葉を選んでくれたのだとは思うが、&lt;br&gt;
ただただ嬉しかった。&lt;/p&gt;
&lt;p&gt;亡くなる瞬間に立ち会えなかったのでこれは本当なのか先生の優しい嘘かはわからないが、&lt;br&gt;
状況から窒息ではなく体の機能がすーっと止まったような形で、&lt;br&gt;
最後も苦しまずに逝けたのではないか、とのことだった。&lt;/p&gt;
&lt;p&gt;それなら安心だし、そうであってほしい。&lt;/p&gt;
&lt;p&gt;2025年11月15日 朝5時 推定9歳6ヶ月&lt;br&gt;
そとちゃんは短い一生を生き切った。&lt;/p&gt;
&lt;h3 id="お別れ"&gt;お別れ
&lt;/h3&gt;&lt;p&gt;その後、&lt;br&gt;
たくさんの友人が手を合わせに来てくれた。&lt;/p&gt;
&lt;p&gt;たくさんの優しい言葉をいただいた。&lt;/p&gt;
&lt;p&gt;そとちゃんは本当に愛されていたんだな。&lt;br&gt;
そう実感するたびに涙が出た。&lt;/p&gt;
&lt;p&gt;&lt;img alt="みんなありがとう" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan06_hu_61d1fc1a00485a86.jpeg 800w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan06_hu_f232d2f4b8c7602.jpeg 1600w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan06.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;本当はそとちゃんの身体もずっとこのまま残しておきたかったが、&lt;br&gt;
腐ってしまうのはかわいそうなので火葬することにした。&lt;/p&gt;
&lt;p&gt;小さな、本当に小さなお葬式をした。&lt;/p&gt;
&lt;p&gt;&lt;img alt="たくさんのおやつとおもちゃと共に" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan08_hu_d08cdb2f5cbe8bf5.jpeg 800w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan08_hu_cc96c70ce93ae1c5.jpeg 1600w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan08.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;最後は体重2.3kgしかなかったが、元気な時でも最大4kgだったそとちゃん。&lt;br&gt;
棺も最小サイズだった。&lt;/p&gt;
&lt;p&gt;そとちゃんを炉に入れる直前はもう、 &lt;br&gt;
涙どころか鼻水もよだれも止まらなかった。&lt;/p&gt;
&lt;p&gt;あんなに人前で取り乱したことはないんじゃないかというくらい、&lt;br&gt;
どうしようもなくなってしまった。&lt;/p&gt;
&lt;p&gt;たくさん喚いて少し落ち着いたころ、&lt;br&gt;
そとちゃんのお骨が返ってきた。&lt;/p&gt;
&lt;p&gt;頭以外は健康そのものだったので状態は良く、&lt;br&gt;
立派な骨になって返ってきた。&lt;/p&gt;
&lt;p&gt;骨になってもかわいいなんて、&lt;br&gt;
やっぱりそとちゃんはすごいねこだ。&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;あまり大っぴらに見せるものでもないので折りたたみ&lt;/summary&gt;
&lt;p&gt;&lt;img alt="立派なお骨" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan09.jpeg" srcset="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan09_hu_dc20e96284b14ae6.jpeg 800w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan09_hu_ce1fb088d6da700c.jpeg 1600w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan09.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="やはり腫瘍で頭蓋骨の半分が溶けていた" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan10.jpeg" srcset="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan10_hu_33d2a4e25e9e2c9c.jpeg 800w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan10_hu_6ba7a5843f818598.jpeg 1600w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan10.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;/details&gt;
&lt;p&gt;式場の方にも優しい言葉をかけていただき再び号泣。&lt;/p&gt;
&lt;p&gt;本当に泣いてばかりだった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="かわいい写真が多すぎて遺影を選ぶのが大変だった" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan07_hu_e58350f8fb19fd18.jpeg 800w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan07_hu_cf65bead9239b443.jpeg 1600w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan07.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;お骨は埋葬せず、&lt;br&gt;
しばらくは家で一緒にいることにした。&lt;/p&gt;
&lt;p&gt;&lt;img alt="仏壇?になってるかはわからないがそとちゃんの好きなものをたくさん置いた" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan11.jpeg" srcset="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan11_hu_7b9fdf9953f18858.jpeg 800w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan11_hu_55d4433f4d2c9fb2.jpeg 1600w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan11.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="ふるさと"&gt;ふるさと
&lt;/h3&gt;&lt;p&gt;お葬式を終えてしばらく経ち、年も明けたころ。&lt;br&gt;
そとちゃんを保護してくださった群馬の保護主さんのところを尋ねた。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://www.larcenchat.com/" target="_blank" rel="noopener"
 &gt;https://www.larcenchat.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="素敵なカフェ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan12.jpeg" srcset="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan12_hu_c2df0afa648f665f.jpeg 800w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan12_hu_a84d30fcfac6bba8.jpeg 1600w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan12.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;保護主さんとお会いするのはそとちゃんがうちに来た日以来で、&lt;br&gt;
たくさんお話をさせていただいた。&lt;/p&gt;
&lt;p&gt;信じてそとちゃんを託してくれたのに長生きさせてあげられなかった、&lt;br&gt;
謝罪の気持ちを伝えたかったが、&lt;br&gt;
それよりも先にたくさんの優しい言葉をいただいた。&lt;/p&gt;
&lt;p&gt;言葉の一つ一つが本当に嬉しかった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="後輩たちにも素敵な出会いがあるといいな" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan13.jpeg" srcset="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan13_hu_c3ee3782e9afeab1.jpeg 800w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan13_hu_51ba8a705449485d.jpeg 1600w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan13.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;そとちゃんの後輩となる保護猫ちゃんたちとも遊ばせてもらった。&lt;/p&gt;
&lt;p&gt;ねこちゃんに触れるのも数ヶ月ぶりだったので、&lt;br&gt;
久しぶりに暖かい気持ちになれた。&lt;/p&gt;
&lt;p&gt;カフェで素敵な時間を過ごした後、&lt;br&gt;
そとちゃんが保護された場所を訪問した。&lt;/p&gt;
&lt;p&gt;&lt;img alt="そとちゃんのふるさと" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan19.jpeg" srcset="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan19_hu_d911368a9faeea26.jpeg 800w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan19_hu_34b9d722760e21a4.jpeg 1600w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan19.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;本当に静かで、のんびりとした場所だった。&lt;/p&gt;
&lt;p&gt;こういうところで生まれ育ったからあんなに優しいねこになったのかな、&lt;br&gt;
なんて考えたりした。&lt;/p&gt;
&lt;p&gt;そとちゃんはこの場所で、産気づいた状態で保護された。&lt;br&gt;
そとちゃんの子かはよくわかっていないが、保護される前は別の複数の子猫と一緒にいたところも目撃されていたらしい。&lt;br&gt;
(その後保護主さんのところで2匹出産している)&lt;/p&gt;
&lt;p&gt;そとちゃんはもういないけど、&lt;br&gt;
そとちゃんの生きた証はこの世界に残っている。&lt;br&gt;
そう考えると嬉しいし、少し寂しさが薄れた気がした。&lt;/p&gt;
&lt;h2 id="ありがとう"&gt;ありがとう
&lt;/h2&gt;&lt;p&gt;そとちゃんがうちに来てくれてからの6年半、&lt;br&gt;
本当に幸せな毎日だった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="うちに来て初日でいきなり枕を占拠" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan14.JPG" srcset="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan14_hu_ce106d4d6311804c.JPG 800w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan14_hu_eec161983676ded2.JPG 1600w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan14.JPG 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;結局一度も「シャーッ」「フーッ」と怒ることのなかった、心のやさしいねこだった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="このポーズがとくいわざ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan15.JPG" srcset="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan15_hu_12ca597e8fa71b94.JPG 800w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan15_hu_503befa8214f78bf.JPG 1600w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan15.JPG 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;おもちゃ遊びは好きだけど、&lt;br&gt;
それよりもごろごろするのが好きだった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="かわいいね" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan16.jpeg" srcset="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan16_hu_391b062ba3ffa9ef.jpeg 800w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan16_hu_c967494d7961249c.jpeg 1600w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan16.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;イタズラなんてほとんどしないおりこうさんで、&lt;br&gt;
人間よりも家をきれいに使ってくれた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="首輪をつけている時期もあった" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan18.JPG" srcset="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan18_hu_a4e46f9dfceeee5e.JPG 800w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan18_hu_10b584ea572f6a86.JPG 1600w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan18.JPG 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;一緒にいるとたのしくてあたたかくて、&lt;br&gt;
とにかく笑顔にさせてくれた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="袋が大好き" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan17.JPG" srcset="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan17_hu_4b9169d932cdeba7.JPG 800w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan17_hu_b08b1465559e77ba.JPG 1600w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan17.JPG 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;今もスマホのカメラロールを辿ればそとちゃんの姿がたくさん残っていて、&lt;br&gt;
一緒に過ごした日々を思い出して幸せな気持ちになれる。&lt;/p&gt;
&lt;p&gt;うちに来てくれてありがとう。&lt;/p&gt;
&lt;p&gt;ごはんの好き嫌いはあったけど、&lt;br&gt;
おいしそうにおやつを食べてくれてありがとう。&lt;/p&gt;
&lt;p&gt;ひざに乗ってくれてありがとう。&lt;br&gt;
一度乗ると全然動かないから脚がしびれたけど、幸せだった。&lt;/p&gt;
&lt;p&gt;撫でさせてくれてありがとう。&lt;br&gt;
ブラシが嫌いなのに毛並みはいつもきれいだった。&lt;/p&gt;
&lt;p&gt;たくさんおしゃべりしてくれてありがとう。&lt;br&gt;
俺はねこの言葉がわからないしそとちゃんも人間の言葉がわからないけど、&lt;br&gt;
毎朝2人でおしゃべりするのがたのしかった。&lt;/p&gt;
&lt;p&gt;自慢の長いしっぽを揺らしてくれてありがとう。&lt;br&gt;
ピンクの肉球を触らせてくれてありがとう。&lt;br&gt;
最後まで喉を鳴らしてくれてありがとう。&lt;/p&gt;
&lt;p&gt;初めて一緒に暮らしたねこがそとちゃんで本当によかった。　&lt;/p&gt;
&lt;p&gt;世界一の最高のねこでした。&lt;/p&gt;
&lt;p&gt;&lt;img alt="そとちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan_hu_f9b59c67010566d6.jpeg 800w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan_hu_1804c6b6cd50cb53.jpeg 1600w, https://blog.uzimihsr.com/post/2026-05-01-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>10月と11月のそとちゃん</title><link>https://blog.uzimihsr.com/post/2026-02-08-sotochan/</link><pubDate>Sun, 08 Feb 2026 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2026-02-08-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan.jpeg" alt="Featured image of post 10月と11月のそとちゃん" /&gt;&lt;h2 id="そとちゃん"&gt;そとちゃん
&lt;/h2&gt;&lt;h3 id="食欲不振"&gt;食欲不振
&lt;/h3&gt;&lt;p&gt;9月末ごろから食欲不振でごはんをあまり食べなくなったそとちゃん。&lt;/p&gt;
&lt;p&gt;10月に入ってからは好きだったおやつもほとんど食べなくなってしまった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="かにかま拒否" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan01_hu_bbbf09efacd74961.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan01_hu_e02c2621b158e0e8.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="ちゅーるも拒否" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan02_hu_62129f646993235d.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan02_hu_66ba867b7bb7b49f.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;お水は自分から飲んでくれるけど、&lt;br&gt;
食べ物には全然反応しない&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="なぜか風呂場のお水をご所望" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan03_hu_760d7999391041b4.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan03_hu_f85a81f344ce1698.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan03.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;何日か水しか飲まない状態が続き、&lt;br&gt;
お腹が空きすぎて吐く?ようなことがあったので再び病院へ。&lt;/p&gt;
&lt;p&gt;&lt;img alt="やっぱりキャリーバッグには自分から入る" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan04_hu_f40401c695ea1de1.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan04_hu_d79f3821f0669c95.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;当日の体重は2.9kg。&lt;/p&gt;
&lt;p&gt;1週前に病院で計ったときが3.22kgだったので、&lt;br&gt;
わずか7日で300g近く落ちてしまったことになる。&lt;/p&gt;
&lt;p&gt;超音波検査の結果、胃腸炎の疑いが出た。&lt;/p&gt;
&lt;p&gt;9月後半に追加した&lt;a class="link" href="https://www.vm.nval.go.jp/public/detail/14221" target="_blank" rel="noopener"
 &gt;ビクタス&lt;/a&gt;が少し強い薬なのでそれが影響した可能性が高いとのこと。&lt;/p&gt;
&lt;p&gt;さらに前回追加で行った細菌検査の結果が返ってきていて、&lt;br&gt;
弱い方の薬&lt;a class="link" href="https://www.vm.nval.go.jp/public/detail/14212" target="_blank" rel="noopener"
 &gt;リレキシペット&lt;/a&gt;がそとちゃんの耳漏から採取した菌に効果があることがわかった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="各行がお薬の種類とそれに対する細菌の反応(Sが効果あり) 13がリレキシ、19がビクタス" class="gallery-image" data-flex-basis="180px" data-flex-grow="75" height="1984" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan05_hu_ec160c45247248d8.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan05.jpeg 1488w" width="1488"&gt;&lt;/p&gt;
&lt;p&gt;胃が荒れる原因になっている可能性があり、&lt;br&gt;
弱い薬でも十分効く見込みがあるとのことで、&lt;br&gt;
吐き気止めのお薬を追加しビクタスは休薬することに。&lt;/p&gt;
&lt;p&gt;&lt;img alt="マロピタットが吐き気止め、ボミットバスターが整腸剤らしい" class="gallery-image" data-flex-basis="180px" data-flex-grow="75" height="1984" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan06_hu_5fa0e76ee1ddc13.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan06.jpeg 1488w" width="1488"&gt;&lt;/p&gt;
&lt;p&gt;胃腸炎の他に腎臓の悪化も影響しているかも?とのことなので、&lt;br&gt;
さらに点滴も入れてもらった。&lt;/p&gt;
&lt;p&gt;ひとまずこれで様子を見て、&lt;br&gt;
それでも改善しないようなら点滴の頻度を増やすことになった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="たくさん検査してつかれた" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan07_hu_bbc1e2c387ce2cfb.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan07_hu_8739ddbdf47518f4.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan07.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="強制給餌"&gt;強制給餌
&lt;/h3&gt;&lt;p&gt;病院から戻って数日経っても症状は改善せず&amp;hellip;&lt;/p&gt;
&lt;p&gt;吐くことはなかったが、&lt;br&gt;
相変わらずお水を飲むだけでごはんを全く食べない状態が続いた。&lt;/p&gt;
&lt;p&gt;なにもお腹に入らない状況は流石にまずいので、&lt;br&gt;
この頃から強制給餌を始めた。&lt;/p&gt;
&lt;p&gt;ドライフードを小さく割り、&lt;br&gt;
お薬の錠剤と同じ要領で上を向かせた状態で口を開けて飲み込ませる。&lt;/p&gt;
&lt;p&gt;&lt;img alt="こんな感じの姿勢 実際は頭の後ろから手を入れて指で無理やり口を開く" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan09.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan09_hu_73333bbfad5165bf.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan09_hu_e154d5ea0cea05e5.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan09.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;9月末からお薬はこの方法で飲ませていて、&lt;br&gt;
そとちゃんも俺も割と慣れていたのでスムーズに飲ませることができた。&lt;/p&gt;
&lt;p&gt;が、問題はその量。&lt;br&gt;
ドライフードを飲ませられる量は一回で高々1,2粒なので、&lt;br&gt;
必要なエネルギー(カロリー)は全然足りない。&lt;/p&gt;
&lt;p&gt;&lt;img alt="無理やり食べさせられてるのでねこは激おこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan08_hu_2bdbcb9c69596bb2.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan08_hu_95b19a8d2b0fe641.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan08.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;そとちゃんの負荷もしんどそうで、&lt;br&gt;
どうしよう&amp;hellip;となり、点滴も兼ねて再び病院へ。&lt;/p&gt;
&lt;h3 id="点滴"&gt;点滴
&lt;/h3&gt;&lt;p&gt;&lt;img alt="珍しくキャリーに入るの渋った" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan10.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan10_hu_16a3f6ed6bd3368b.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan10_hu_93f87e7f8d960b3a.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan10.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;この日は血液検査とエコー検査をしてもらった。&lt;/p&gt;
&lt;p&gt;血液検査の結果、&lt;br&gt;
腎臓の数値は9月に行った猫ドック時とあまり変わらず少し高めの数値で、&lt;br&gt;
悪くなってはいないが良くもなっていないという状況。&lt;/p&gt;
&lt;p&gt;エコー検査では強制給餌したドライフードがお腹の中でうまく消化できず残っていることが確認された。&lt;/p&gt;
&lt;p&gt;胃腸炎は治っていそうだが、&lt;br&gt;
何日間かごはんを食べていなかったのもあり、&lt;br&gt;
消化器自体の働きがあまりよくない様子。&lt;/p&gt;
&lt;p&gt;この日の体重は2.8kgで、&lt;br&gt;
たった数日で100gも落ちてしまっていた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="どんどん体重が落ちていく" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan11.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan11_hu_328ae2908bf38e0e.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan11_hu_af21ee820cbca3a.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan11.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;先生に強制給餌の件を相談し、&lt;br&gt;
より高カロリーで消化器への負担も少ない&lt;a class="link" href="https://www.royalcanin.com/jp/cats/products/vet-products/renal-liquid-cat-4951" target="_blank" rel="noopener"
 &gt;ロイヤルカナンの流動食&lt;/a&gt;を与えることになった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="これで命を繋いでいく" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan12.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan12_hu_d0c91cbc9c13d385.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan12_hu_ada6fec97e64e853.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan12.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;流動食を入れたシリンジを口の横から差し込み、&lt;br&gt;
吐かないように少しずつ入れていく。&lt;/p&gt;
&lt;p&gt;&lt;img alt="すごく嫌そう" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="957" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan13.png" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan13_hu_89556737aa55f387.png 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan13_hu_e96372c1227333d8.png 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan13.png 1701w" width="1701"&gt;&lt;/p&gt;
&lt;p&gt;嫌がるなのは変わらないが、&lt;br&gt;
ドライフードよりはあげやすそうになってよかった。&lt;/p&gt;
&lt;p&gt;とはいえ自力で食べてくれることが一番なので、&lt;br&gt;
この日は耳に塗る食欲増進剤を追加してもらい、&lt;br&gt;
さらに腎疾患の疑いを見て毎日点滴に通うことになった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="がんばりましょう…" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan14.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan14_hu_385b67a0b966f447.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan14_hu_f953ff5c7d3bd4b4.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan14.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="食欲復活"&gt;食欲復活
&lt;/h3&gt;&lt;p&gt;&amp;hellip;が。&lt;/p&gt;
&lt;p&gt;その日の夜にいつも通りダメ元でおやつを出したところ、&lt;br&gt;
急にガツガツ食べ始めた!&lt;/p&gt;
&lt;div class="video-wrapper"&gt;
 &lt;iframe loading="lazy" 
 src="https://www.youtube.com/embed/I-bcbCz5OXo" 
 allowfullscreen 
 title="YouTube Video"
 &gt;
 &lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;自分から食べるなんて本当に久しぶり。&lt;/p&gt;
&lt;p&gt;&lt;img alt="めっちゃ食うじゃん" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="1980" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan15.JPG" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan15_hu_e43e1bd5f5ffc4ba.JPG 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan15_hu_1673e0ad7e2d1b06.JPG 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan15_hu_19961b015ca0d314.JPG 2400w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan15.JPG 3520w" width="3520"&gt;&lt;/p&gt;
&lt;p&gt;その後は朝のおやつも完食。&lt;/p&gt;
&lt;p&gt;超えらい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="えらすぎる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan16.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan16_hu_4bdd30af5273966e.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan16_hu_4d43e2676a4862fd.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan16.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;点滴の効果が出るには早すぎるということで、&lt;br&gt;
おそらく食欲増進剤が効いたのか&amp;hellip;?&lt;/p&gt;
&lt;p&gt;とはいえ腎臓の数値は心配なので、&lt;br&gt;
先生とも相談して念の為毎日の点滴は継続。&lt;/p&gt;
&lt;h3 id="いいかんじ"&gt;いいかんじ
&lt;/h3&gt;&lt;p&gt;この頃のそとちゃんは絶好調。&lt;/p&gt;
&lt;p&gt;&lt;img alt="あきらかに調子が良い" class="gallery-image" data-flex-basis="355px" data-flex-grow="148" height="1267" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan17.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan17_hu_ec59fda0442df1f.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan17_hu_31960abbccc172ef.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan17.jpeg 1879w" width="1879"&gt;&lt;/p&gt;
&lt;p&gt;おやつメインではあるものの自分から食べてくれるようになり、&lt;br&gt;
強制給餌の割合も減っていった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="たまにドライフードも食べちゃう" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="1980" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan18.JPG" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan18_hu_e8cf300e5d4b06ec.JPG 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan18_hu_94fc50894045f390.JPG 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan18_hu_a116659f16db643c.JPG 2400w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan18.JPG 3520w" width="3520"&gt;&lt;/p&gt;
&lt;p&gt;たくさん食べたおかげで、体重も2.95kgまで復活。&lt;/p&gt;
&lt;p&gt;毎日の点滴通いもがんばってくれて、&lt;br&gt;
4日目には脱水症状もだいぶ改善していたので頻度を週1に減らせることになった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="体重増えた うれしいね" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan19.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan19_hu_ff226bbadc103ee8.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan19_hu_58b778a6d2d2687e.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan19.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="前庭疾患"&gt;前庭疾患
&lt;/h3&gt;&lt;p&gt;食事の問題は改善したものの、&lt;br&gt;
一番の問題である前庭疾患がなかなか良くならない。&lt;/p&gt;
&lt;p&gt;首の傾きはだんだん角度がきつくなっているように見えるし、&lt;br&gt;
やっぱり左耳が痛いのかな&amp;hellip;?&lt;/p&gt;
&lt;p&gt;&lt;img alt="首がやっぱり傾いちゃう" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan20.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan20_hu_befb89a0b65947fe.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan20_hu_c029f6c282c2ec35.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan20.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;この頃から鳴き声も少し変になってきた。&lt;/p&gt;
&lt;p&gt;前は高い声でかわいくおしゃべりしてくれていたのだが、&lt;br&gt;
若干低めでダミ声のような鳴き方をするようになった。&lt;/p&gt;
&lt;div class="video-wrapper"&gt;
 &lt;iframe loading="lazy" 
 src="https://www.youtube.com/embed/n2-hgwF3wEk" 
 allowfullscreen 
 title="YouTube Video"
 &gt;
 &lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;(近づくと爆音ゴロゴロするのは変わらず。かわいい)&lt;/p&gt;
&lt;p&gt;また、先生が診察中に気付いたのだが、&lt;br&gt;
顔面の左側(正面から見て右側)が麻痺しているようだった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="瞬膜が出っ放しで、物を眼に近づけても閉じない(反射がない)" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan21.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan21_hu_9cc8653e8c4a4cf3.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan21_hu_29d94e1d2337498.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan21.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;瞬膜がちゃんとひっこんでいることもあるのだが、&lt;br&gt;
出っ放しのときは見た目がかわいそうで、&lt;br&gt;
これが個人的にはかなりつらかった。&lt;/p&gt;
&lt;p&gt;流石に左目が見えづらいとそとちゃんも気になるのか、&lt;br&gt;
今まで目ヤニが出やすかったりで閉じがちだった右目が逆にぱっちり開くようになった。&lt;br&gt;
(諦めずに目薬を頑張ってきてよかったね&amp;hellip;)&lt;/p&gt;
&lt;p&gt;&lt;img alt="過去最大級に右目がぱっちり" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan22.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan22_hu_3602868e9dff9b5.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan22_hu_64dfd232e0ae3109.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan22.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;こんな感じで、&lt;br&gt;
前庭疾患の症状は良くなるどころか少しずつ悪くなっているようだった。&lt;/p&gt;
&lt;h3 id="二次診療"&gt;二次診療
&lt;/h3&gt;&lt;p&gt;そんなこんなで投薬と通院が続く中、&lt;br&gt;
先生から脳神経科での二次診療(CT/MRI)の打診をいただいた。&lt;/p&gt;
&lt;p&gt;食欲不振と脱水症状はかなり改善した。&lt;br&gt;
抗生剤も細菌検査を実施した上で1ヶ月以上続けている。&lt;br&gt;
なのに症状が改善しない。&lt;/p&gt;
&lt;p&gt;これは本当に細菌性の中耳炎なのだろうか？&lt;br&gt;
何か別の原因があって、耳漏や菌はその影響ではないだろうか？とのことだった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="やっぱり症状が改善しないし、少し元気がなくなってきた" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan23.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan23_hu_1f655a78042bb1dd.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan23_hu_4aa8eb28c2417df1.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan23.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;9月に最初の発作が出た時に実は「腫瘍性の問題も一応考えられる」というお話を受けていたが、&lt;br&gt;
症状から最も当てはまるのが中耳炎ということで先生も俺も治療を続けてきた。&lt;/p&gt;
&lt;p&gt;でもこの状況では抗生剤を続けても改善が見込めない。&lt;br&gt;
一度腫瘍性の問題を考え直すべきではないか。&lt;/p&gt;
&lt;p&gt;正直、考えたくなかった。&lt;/p&gt;
&lt;p&gt;抗生剤を続けていれば中耳炎は治り、&lt;br&gt;
元のそとちゃんに戻ると信じてお互い嫌な思いをしながら頑張ってきたのに。&lt;/p&gt;
&lt;p&gt;でも、このまま症状が治らずそとちゃんが居なくなる、なんてのはもっと嫌だった。&lt;br&gt;
今の治療で治る見込みが薄いなら、他にできることを見つけたい。&lt;/p&gt;
&lt;p&gt;そんな思いで、&lt;a class="link" href="https://jarmec.jp/" target="_blank" rel="noopener"
 &gt;日本動物高度医療センター(JARMeC)&lt;/a&gt;での検査を受けることにした。&lt;/p&gt;
&lt;p&gt;当日病院に着いて、まずはレントゲン検査と血液検査。&lt;/p&gt;
&lt;p&gt;レントゲン検査の結果はあまり良くなく、&lt;br&gt;
9月の猫ドックでも確認したように耳の奥の骨が溶けているのに加え、&lt;br&gt;
耳の穴から内耳までの経路が何か(膿?腫瘍?)で塞がれてしまっているようだった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="右下の経路が白く塞がっている" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan24.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan24_hu_3311009ff139ac40.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan24_hu_18cd2a470b4a8f22.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan24.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;血液検査の結果は腎臓の数値が基準値を超えていて、&lt;br&gt;
そとちゃんの体力が落ちていることを考慮すると全身麻酔をかけての検査にはかなりリスクがある状態。&lt;/p&gt;
&lt;p&gt;&lt;img alt="全身麻酔のたびにサインしてきたが、今回は重い" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan25.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan25_hu_7ea5784dd2583953.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan25_hu_a9eb3f65ff07add1.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan25.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;とはいえ、これは事前にかかりつけの先生とも相談した上で決めていたし、&lt;br&gt;
何よりもそとちゃんの生きる力を信じてサインすることにした。&lt;/p&gt;
&lt;p&gt;そとちゃんを預けて半日待機。&lt;br&gt;
あまり生きた心地はしなかった。&lt;br&gt;
「やっぱり中耳炎でした」となることだけを祈って待っていた。&lt;/p&gt;
&lt;p&gt;受け取りの時間が来て、&lt;br&gt;
そとちゃんは無事に麻酔から目が覚めていた。&lt;/p&gt;
&lt;p&gt;まずは無事に意識が戻ってよかった。&lt;br&gt;
ほんとうにがんばってくれて、すごいねこだ。&lt;/p&gt;
&lt;p&gt;CT検査の結果は、&lt;br&gt;
&lt;strong&gt;悪性腫瘍(がん)の疑いが強い&lt;/strong&gt;とのことだった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="丸で囲った箇所が病変で、頭蓋内にも広がっている" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan26.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan26_hu_9565f823b5d4e365.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan26_hu_e3a6304f1e91147f.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan26.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;耳から第一頚椎にかけて病変が広がっており、頭蓋骨も溶かして脳に到達しているような状態。&lt;br&gt;
中耳~前庭にかけて組織が広範囲に壊れていて、神経疾患の原因はこれで間違いない。&lt;/p&gt;
&lt;p&gt;実際の病変を採取して細胞診検査に回したが、&lt;br&gt;
この段階で確定はできないものの炎症や白血球の増大が見られないため、&lt;br&gt;
膿ではなく腫瘍の可能性が非常に高い。&lt;/p&gt;
&lt;p&gt;大きなくくりでの症状としては中耳炎+前庭疾患に違いないが、&lt;br&gt;
その原因が細菌性である可能性はほぼゼロ、ほぼ確実に腫瘍に由来するものだろう。&lt;/p&gt;
&lt;p&gt;細胞診検査の結果待ちではあるものの、&lt;br&gt;
悪性腫瘍であった場合はすでに脳の広範囲に広がっていることから、&lt;br&gt;
物理的な切除は難しい。&lt;/p&gt;
&lt;p&gt;余命は残り数ヶ月との宣告を受けた。&lt;/p&gt;
&lt;p&gt;無理やりメモから書き起こしてはいるが、&lt;br&gt;
このとき自分が何を考えていたか、あまり覚えていない。&lt;/p&gt;
&lt;p&gt;病院からの帰り道、十数年ぶりに声を上げて泣いたことだけは覚えている。&lt;/p&gt;
&lt;p&gt;&lt;img alt="落ち込むニンゲンをよそにおしりガン舐めするねこ(帰りにちょっと漏らした)" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan27.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan27_hu_aa6dd79f132fcb84.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan27_hu_d388bbdf8433484d.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan27.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="緩和ケア"&gt;緩和ケア
&lt;/h3&gt;&lt;p&gt;二次診療の結果を受けて、かかりつけの先生と相談。&lt;/p&gt;
&lt;p&gt;痛みと炎症緩和のため、ステロイド系のお薬を追加し、&lt;br&gt;
抗生剤の量は減らすことになった。&lt;/p&gt;
&lt;p&gt;リレキシペットは飲む回数が多く負担がかかるので、休薬していた一日一回のビクタスを再開。&lt;br&gt;
通院も負担がかかるので、これまで通いで行っていた点滴を家で実施。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ステロイド" class="gallery-image" data-flex-basis="180px" data-flex-grow="75" height="1984" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan31.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan31_hu_54c48bc26927d35d.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan31.jpeg 1488w" width="1488"&gt;&lt;/p&gt;
&lt;p&gt;とにかくそとちゃんが残りの時間を穏やかに過ごせるためにやっていこうということになった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="点滴セット 点滴はめっちゃとくい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan28.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan28_hu_4d6c9d713e11b7ee.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan28_hu_576ccf2d0b38e976.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan28.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;もう総合栄養食と一般食とかを気にする段階でもないので、&lt;br&gt;
食べられるうちは大好きなおやつをたくさん食べさせてOK。&lt;/p&gt;
&lt;p&gt;&lt;img alt="毎日ちゅーる食べ放題" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan29.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan29_hu_a65f312ea606cddc.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan29_hu_99771d9f00889de9.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan29.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="ジュレのおやつも食べ放題" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan30.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan30_hu_eae51226dedfbde1.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan30_hu_5ff8a05c550c78ed.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan30.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;ニンゲンは悲しいけど、ねこは嬉しいね&amp;hellip;&lt;/p&gt;
&lt;p&gt;歩行の衰えにも備えて、&lt;br&gt;
トイレを変えたり、ペット用ステップを追加したり。&lt;/p&gt;
&lt;p&gt;&lt;img alt="今までの高機能トイレからシンプルに入口が広くて入りやすいシンプルなものに" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan32.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan32_hu_e13bb9cf042cde5b.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan32_hu_fed4b8aa8c1d3ad6.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan32.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="大好きなソファに登れるようにステップを置いた" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan33.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan33_hu_c46b8c420cbebc35.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan33_hu_56f01eac070fa2cf.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan33.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;念の為つけていたペットサークルもそとちゃんが寂しい思いをしないように撤去。&lt;/p&gt;
&lt;p&gt;そとちゃんと一緒に過ごす時間を最優先にした。&lt;/p&gt;
&lt;p&gt;&lt;img alt="うんちしてめっちゃ褒められてとくいげ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan34.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan34_hu_71c295dc19988c1e.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan34_hu_56400b8f84c01f1a.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan34.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="強制給餌再び"&gt;強制給餌再び
&lt;/h3&gt;&lt;p&gt;そとちゃんの緩和ケアを始めて、11月になった頃。&lt;/p&gt;
&lt;p&gt;だんだんとおやつも残すことが増えてきて、&lt;br&gt;
ついにちゅーるすら食べなくなってしまった。&lt;/p&gt;
&lt;p&gt;これまで効果があった食欲増進剤を試しても効果が出ず、&lt;br&gt;
強制給餌を再開することになった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ロイヤルカナンの流動食、再び" class="gallery-image" data-flex-basis="180px" data-flex-grow="75" height="1984" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan35.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan35_hu_8a3a999139576e4a.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan35.jpeg 1488w" width="1488"&gt;&lt;/p&gt;
&lt;p&gt;神経症状で口をあけるのも辛くなってきたのか、&lt;br&gt;
以前よりも嫌がるように。&lt;/p&gt;
&lt;p&gt;頑張って飲んでくれるけど、その後は毎回ふきげん。&lt;/p&gt;
&lt;p&gt;&lt;img alt="しっぽビタンビタン" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan36.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan36_hu_96e6f7d89b6415e7.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan36_hu_183c373a3b9360cf.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan36.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;これまではごほうびのおやつでごまかせたけど、&lt;br&gt;
それができないのでどうやって機嫌を直したらいいかもわからない。&lt;/p&gt;
&lt;p&gt;&lt;img alt="嫌すぎて瞳孔開いてる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan37.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan37_hu_9b7058b0b6cf8fcd.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan37_hu_6f6fcc9c35383805.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan37.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;とにかく給餌の後はたくさん褒めて、&lt;br&gt;
逃げたときも無理に追わずに放置するようにした。&lt;/p&gt;
&lt;p&gt;&lt;img alt="逃走" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan38.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan38_hu_f786b1e6ee4f9491.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan38_hu_e6bd171040d126df.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan38.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;そとちゃんが嫌がっているのは明らかだったが、&lt;br&gt;
命を少しでも繋ぐために食べさせるしかなかった。&lt;/p&gt;
&lt;h3 id="細胞診検査の結果"&gt;細胞診検査の結果
&lt;/h3&gt;&lt;p&gt;強制給餌を再開して少したった頃、二次診療で行った細胞診検査の結果が届いた。&lt;/p&gt;
&lt;p&gt;確定診断の結果は&lt;strong&gt;悪性上皮性腫瘍&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;そとちゃんががんを患っていることが確定した。&lt;/p&gt;
&lt;p&gt;あまりにも広範囲に広がっているため、&lt;br&gt;
由来(耳垢腺がん/唾液腺がん/扁平上皮がん)の特定はできなかったそう。&lt;/p&gt;
&lt;p&gt;再度かかりつけの先生と相談。&lt;/p&gt;
&lt;p&gt;がんに対する治療をするのか、&lt;br&gt;
それはせずにこのままステロイドの投与を続けるのか。&lt;/p&gt;
&lt;p&gt;リスクを説明してもらった上で、&lt;br&gt;
自分は抗がん剤(分子標的薬)での治療を選択した。&lt;/p&gt;
&lt;p&gt;&lt;img alt="パラディア錠" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan39.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan39_hu_b2fe5c65426d1c53.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan39_hu_d7d2255e479c8600.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan39.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="副作用で下痢したときのために下痢止めも投与" class="gallery-image" data-flex-basis="180px" data-flex-grow="75" height="1984" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan40.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan40_hu_8f70334ce4677ef0.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan40.jpeg 1488w" width="1488"&gt;&lt;/p&gt;
&lt;p&gt;外科手術は不可能、放射線治療もそとちゃんの体力を考慮すると非現実的。&lt;br&gt;
そんな状態でも腫瘍による神経の圧迫や耳漏を少しでも和らげられれば&amp;hellip;と思っての判断だった。&lt;/p&gt;
&lt;p&gt;この時点でもう完治を目指すつもりはなく、&lt;br&gt;
あくまで楽にしてあげるための抗がん剤。&lt;/p&gt;
&lt;p&gt;分子標的薬は一般的な抗がん剤に比べると効果もリスクも抑えめとのこと。&lt;br&gt;
1,2回試してなにか苦しそうであればすぐやめてステロイドのみに切り替える。&lt;br&gt;
そう決めて投与することにした。&lt;/p&gt;
&lt;h3 id="抗がん剤"&gt;抗がん剤
&lt;/h3&gt;&lt;p&gt;1回目の投与。&lt;/p&gt;
&lt;p&gt;思ったよりも錠剤が大きく、&lt;br&gt;
飲ませるのが大変だった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="激おこだけど副作用はなさそう" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan41.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan41_hu_1cca257f839c68e1.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan41_hu_9ae6a28cc84dedb1.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan41.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;初回なので投与後は2日程度様子を見る。&lt;/p&gt;
&lt;p&gt;副作用が出た場合は下痢や嘔吐が出るはずだが、&lt;br&gt;
そのような兆候は見られなかった。&lt;/p&gt;
&lt;h3 id="残りの時間"&gt;残りの時間
&lt;/h3&gt;&lt;p&gt;そとちゃんは何を考えていただろうか。&lt;/p&gt;
&lt;p&gt;自分に残された時間を理解していたかはわからないが、&lt;/p&gt;
&lt;p&gt;強制給餌や抗がん剤治療が始まってからも毎日これまでと同じく、&lt;/p&gt;
&lt;p&gt;たくさん寝て、&lt;/p&gt;
&lt;p&gt;&lt;img alt="ふわふわのベッド" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan42.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan42_hu_ab5a7d753f2f91b0.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan42_hu_cdde3c51aa4521a.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan42.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;たまに起きて風呂場の水を飲み、&lt;/p&gt;
&lt;p&gt;&lt;img alt="お水飲むのとくい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan43.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan43_hu_ad14d062e77b3034.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan43_hu_bc6cff06905e380e.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan43.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;暖かいところを探してもうひと眠り。&lt;/p&gt;
&lt;p&gt;&lt;img alt="大好きなホットカーペットでひなたぼっこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan44.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan44_hu_a13498958d22f5d.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan44_hu_f86b50d789760eb2.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan44.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;また起きては爪を研ぎ、&lt;/p&gt;
&lt;p&gt;&lt;img alt="バリバリベッドも大好き" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan45.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan45_hu_b3990e32e83733a1.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan45_hu_93dd4398af6447b1.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan45.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;お気に入りの紙袋にもぐって過ごした。&lt;/p&gt;
&lt;p&gt;&lt;img alt="紙袋大好き" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan46.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan46_hu_fde0bef27a34df6e.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan46_hu_78d92106158a8751.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan46.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;毎日楽しく、好きなことをたくさんして1日1日を大切に過ごしていた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ニンゲンの膝の上が大好き" class="gallery-image" data-flex-basis="387px" data-flex-grow="161" height="972" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan47.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan47_hu_c40d5d9fe566070e.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan47.jpeg 1568w" width="1568"&gt;&lt;/p&gt;
&lt;p&gt;(つづく)&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="大好きなひなたぼっこでほかほかになるねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan_hu_3fde4c3aef450b72.jpeg 800w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan_hu_a3ca445b41b4441d.jpeg 1600w, https://blog.uzimihsr.com/post/2026-02-08-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>Dify Console APIをcURLで呼び出してみた(v1.9.2 CSRF Token対応)</title><link>https://blog.uzimihsr.com/post/2025-10-25-dify-console-api-curl/</link><pubDate>Sat, 25 Oct 2025 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2025-10-25-dify-console-api-curl/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2025-10-25-dify-console-api-curl/sotochan.jpeg" alt="Featured image of post Dify Console APIをcURLで呼び出してみた(v1.9.2 CSRF Token対応)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;セルフホスト版Dify(Community)で、非公開?のコンソールAPIがある&lt;/li&gt;
&lt;li&gt;v1.9.2から、ログイン時に取得できるトークンの扱いが変わった
&lt;ul&gt;
&lt;li&gt;トークンをこれまでのレスポンスボディでなくcookieに入れて返してくるのでそのまま使うのが良い&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# login API: https://github.com/langgenius/dify/blob/1.9.2/api/controllers/console/auth/login.py#L44&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;hogehoge@uzimihsr.com&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# Difyアカウントのメールアドレス&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;xxxxxxxx&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# Difyアカウントのパスワード&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;http://localhost&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# localhost以外で立ててる場合はそれに合わせて変更&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl -c cookie -X POST &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;base_url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/console/api/login&amp;#34;&lt;/span&gt; -H &lt;span class="s1"&gt;&amp;#39;Content-Type: application/json&amp;#39;&lt;/span&gt; -d &lt;span class="s2"&gt;&amp;#34;{\&amp;#34;email\&amp;#34;:\&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;email&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\&amp;#34;,\&amp;#34;password\&amp;#34;:\&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;password&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\&amp;#34;}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;csrf_token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;grep csrf_token cookie &lt;span class="p"&gt;|&lt;/span&gt; cut -f7&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#　profile API: https://github.com/langgenius/dify/blob/1.9.2/api/controllers/console/workspace/account.py#L97&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl -sSf -X GET -b cookie -H &lt;span class="s2"&gt;&amp;#34;X-CSRF-Token: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;csrf_token&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;base_url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/console/api/account/profile&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/langgenius/dify/tree/1.9.2" target="_blank" rel="noopener"
 &gt;Dify v1.9.2&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.dify.ai/en/getting-started/install-self-hosted/docker-compose" target="_blank" rel="noopener"
 &gt;docker compose&lt;/a&gt;で起動&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="経緯"&gt;経緯
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://docs.dify.ai/en/getting-started/install-self-hosted/readme" target="_blank" rel="noopener"
 &gt;Dify&lt;/a&gt;の管理用APIであるConsole APIは公式ドキュメントで公開されていないもののなかなかに便利で、&lt;br&gt;
ユーザー、ワークスペース、モデルプロバイダー、ツール、アプリなどの管理をUIでなくAPIで実行できるのでDify運用の自動化に使えそう。&lt;/p&gt;
&lt;p&gt;一応GitHubのリポジトリを確認すると、このあたりで各種APIの中身が確認できる。&lt;br&gt;
&lt;a class="link" href="https://github.com/langgenius/dify/tree/main/api/controllers/console" target="_blank" rel="noopener"
 &gt;https://github.com/langgenius/dify/tree/main/api/controllers/console&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;実際に使われている偉大な先駆者様達の例↓&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://zenn.dev/furunag/articles/dify-cli-onefile-bash" target="_blank" rel="noopener"
 &gt;https://zenn.dev/furunag/articles/dify-cli-onefile-bash&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://zenn.dev/zozotech/articles/42ddb735d9f3da" target="_blank" rel="noopener"
 &gt;https://zenn.dev/zozotech/articles/42ddb735d9f3da&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ところが、&lt;br&gt;
最近セルフホスト版Difyのバージョンを最新の&lt;strong&gt;1.9.2&lt;/strong&gt;に上げたところlogin API(POST &lt;code&gt;/console/api/login&lt;/code&gt;)でAPIを呼ぶためのトークンが取れなくなってしまった。&lt;br&gt;
(偉大な先駆者様達のコードも1.9.2ではおそらく動かなくなっている)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="c1"&gt;# login API: https://github.com/langgenius/dify/blob/1.9.2/api/controllers/console/auth/login.py#L44&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="c1"&gt;# アカウントのメールアドレス(email)とパスワード(password)をJSONでPOSTするとログインできる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nv"&gt;email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;hogehoge@uzimihsr.com&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# Difyアカウントのメールアドレス&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nv"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;xxxxxxxx&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# Difyアカウントのパスワード&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nv"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;http://localhost&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# localhost以外で立ててる場合はそれに合わせて変更&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -X POST &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;base_url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/console/api/login&amp;#34;&lt;/span&gt; -H &lt;span class="s1"&gt;&amp;#39;Content-Type: application/json&amp;#39;&lt;/span&gt; -d &lt;span class="s2"&gt;&amp;#34;{\&amp;#34;email\&amp;#34;:\&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;email&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\&amp;#34;,\&amp;#34;password\&amp;#34;:\&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;password&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\&amp;#34;}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;result&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;success&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="c1"&gt;# レスポンスボディにアクセストークンが入ってない!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;困ったのでちょっと調べてみた。&lt;/p&gt;
&lt;h2 id="ソースコード調査"&gt;ソースコード調査
&lt;/h2&gt;&lt;p&gt;結論から言うとこれ。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/langgenius/dify/releases/tag/1.9.2" target="_blank" rel="noopener"
 &gt;https://github.com/langgenius/dify/releases/tag/1.9.2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/langgenius/dify/pull/24365" target="_blank" rel="noopener"
 &gt;https://github.com/langgenius/dify/pull/24365&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;v1.9.1まではlogin APIがアクセストークンをレスポンスボディ(.data.access_token)で返していたのが、&lt;br&gt;
セキュリティ向上を目的にHttpOnly Cookieに埋め込んで返すようになったらしい。&lt;/p&gt;
&lt;p&gt;curlの&lt;code&gt;-v&lt;/code&gt;オプションで実際にCookieの中身を確認してみる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -v -X POST &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;base_url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/console/api/login&amp;#34;&lt;/span&gt; -H &lt;span class="s1"&gt;&amp;#39;Content-Type: application/json&amp;#39;&lt;/span&gt; -d &lt;span class="s2"&gt;&amp;#34;{\&amp;#34;email\&amp;#34;:\&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;email&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\&amp;#34;,\&amp;#34;password\&amp;#34;:\&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;password&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\&amp;#34;}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Note: Unnecessary use of -X or --request, POST is already inferred.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* Host localhost:80 was resolved.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* IPv6: ::1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* IPv4: 127.0.0.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* Trying &lt;span class="o"&gt;[&lt;/span&gt;::1&lt;span class="o"&gt;]&lt;/span&gt;:80...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* Connected to localhost &lt;span class="o"&gt;(&lt;/span&gt;::1&lt;span class="o"&gt;)&lt;/span&gt; port &lt;span class="m"&gt;80&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; POST /console/api/login HTTP/1.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; Host: localhost
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; User-Agent: curl/8.7.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; Accept: */*
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; Content-Type: application/json
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; Content-Length: &lt;span class="m"&gt;52&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* upload completely sent off: &lt;span class="m"&gt;52&lt;/span&gt; bytes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt; HTTP/1.1 &lt;span class="m"&gt;200&lt;/span&gt; OK
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt; Server: nginx/1.23.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt; Date: Sat, &lt;span class="m"&gt;25&lt;/span&gt; Oct &lt;span class="m"&gt;2025&lt;/span&gt; 07:30:12 GMT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt; Content-Type: application/json
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt; Content-Length: &lt;span class="m"&gt;20&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt; Connection: keep-alive
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt; Set-Cookie: &lt;span class="nv"&gt;access_token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;eyJhxxxxxxxxxxxx.eyJ1c2xxxxxxxxx.VzvJKdUxxxxxxxx&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;Expires&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Sat, &lt;span class="m"&gt;25&lt;/span&gt; Oct &lt;span class="m"&gt;2025&lt;/span&gt; 08:30:12 GMT&lt;span class="p"&gt;;&lt;/span&gt; Max-Age&lt;span class="o"&gt;=&lt;/span&gt;3600&lt;span class="p"&gt;;&lt;/span&gt; HttpOnly&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;Path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;SameSite&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Lax
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt; Set-Cookie: &lt;span class="nv"&gt;refresh_token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;a4ac94922exxxxxxxxxx&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;Expires&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Mon, &lt;span class="m"&gt;24&lt;/span&gt; Nov &lt;span class="m"&gt;2025&lt;/span&gt; 07:30:12 GMT&lt;span class="p"&gt;;&lt;/span&gt; Max-Age&lt;span class="o"&gt;=&lt;/span&gt;2592000&lt;span class="p"&gt;;&lt;/span&gt; HttpOnly&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;Path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;SameSite&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Lax
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt; Set-Cookie: &lt;span class="nv"&gt;csrf_token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;eyJhbxxxxxxxx.eyJleHAixxxxxxx.uSNFW3Fxxxxxxxx&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;Expires&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Sat, &lt;span class="m"&gt;25&lt;/span&gt; Oct &lt;span class="m"&gt;2025&lt;/span&gt; 08:30:12 GMT&lt;span class="p"&gt;;&lt;/span&gt; Max-Age&lt;span class="o"&gt;=&lt;/span&gt;3600&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;Path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;SameSite&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Lax
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt; X-Version: 1.9.2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt; X-Env: PRODUCTION
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* Connection &lt;span class="c1"&gt;#0 to host localhost left intact&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;result&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;success&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;たしかにHttpOnlyなCookie(access_token, refresh_token)にトークンが埋め込まれている。&lt;/p&gt;
&lt;h2 id="うまくいかない"&gt;うまくいかない
&lt;/h2&gt;&lt;p&gt;じゃあCookieを使えばいいじゃん、ということで&lt;code&gt;-c&lt;/code&gt;オプションでそのままCookieを保存して投げてみる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="c1"&gt;# cookieをファイルに保存&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -c cookie -X POST &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;base_url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/console/api/login&amp;#34;&lt;/span&gt; -H &lt;span class="s1"&gt;&amp;#39;Content-Type: application/json&amp;#39;&lt;/span&gt; -d &lt;span class="s2"&gt;&amp;#34;{\&amp;#34;email\&amp;#34;:\&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;email&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\&amp;#34;,\&amp;#34;password\&amp;#34;:\&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;password&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\&amp;#34;}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;result&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;success&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="c1"&gt;# profile API: https://github.com/langgenius/dify/blob/1.9.2/api/controllers/console/workspace/account.py#L97&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="c1"&gt;# 自分のアカウント情報を確認できる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -X GET -b cookie &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;base_url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/console/api/account/profile&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;code&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;unauthorized&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;message&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;CSRF token is missing or invalid.&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;status&amp;#34;&lt;/span&gt;:401&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="c1"&gt;# が、失敗...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;だめ。&lt;/p&gt;
&lt;h2 id="再挑戦"&gt;再挑戦
&lt;/h2&gt;&lt;p&gt;トークン周辺のコードをもう少し調べる。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/langgenius/dify/blob/1.9.2/api/libs/login.py#L79" target="_blank" rel="noopener"
 &gt;https://github.com/langgenius/dify/blob/1.9.2/api/libs/login.py#L79&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/langgenius/dify/blob/1.9.2/api/libs/token.py#L171" target="_blank" rel="noopener"
 &gt;https://github.com/langgenius/dify/blob/1.9.2/api/libs/token.py#L171&lt;/a&gt;&lt;br&gt;
どうやら&lt;strong&gt;X-CSRF-Token&lt;/strong&gt;ヘッダにcsrf_token Cookieを与えないとだめっぽい。&lt;br&gt;
(login APIが返すCookieのうち、これだけHttpOnlyじゃないのでJavaScriptでも触れる)&lt;br&gt;
CSRFトークンってこうなってんだね&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ということでもう一度試してみる。&lt;br&gt;
Cookieを直接触ってしまっているが、&lt;br&gt;
上記の通りcsrf_tokenに限りHttpOnlyじゃないのでこれは実際のUIの挙動と同じはず。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="c1"&gt;# cookieをファイルに保存&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -c cookie -X POST &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;base_url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/console/api/login&amp;#34;&lt;/span&gt; -H &lt;span class="s1"&gt;&amp;#39;Content-Type: application/json&amp;#39;&lt;/span&gt; -d &lt;span class="s2"&gt;&amp;#34;{\&amp;#34;email\&amp;#34;:\&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;email&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\&amp;#34;,\&amp;#34;password\&amp;#34;:\&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;password&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\&amp;#34;}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;result&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;success&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# cookieファイルの中のcsrf_token(not HttpOnly)の値を取得&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nv"&gt;csrf_token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;grep csrf_token cookie &lt;span class="p"&gt;|&lt;/span&gt; cut -f7&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="c1"&gt;#　profile API: https://github.com/langgenius/dify/blob/1.9.2/api/controllers/console/workspace/account.py#L97&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="c1"&gt;# 今度はX-CSRF-Tokenを添えて...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -sSf -X GET -b cookie -H &lt;span class="s2"&gt;&amp;#34;X-CSRF-Token: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;csrf_token&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;base_url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/console/api/account/profile&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; jq
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;932a9004-b67c-422d-b7aa-89b11d8e04b5&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;hogehoge&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;avatar&amp;#34;&lt;/span&gt;: null,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;avatar_url&amp;#34;&lt;/span&gt;: null,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;email&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;hogehoge@uzimihsr.com&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;is_password_set&amp;#34;&lt;/span&gt;: true,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;interface_language&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;en-US&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;interface_theme&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;light&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;timezone&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;America/New_York&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;last_login_at&amp;#34;&lt;/span&gt;: 1761380052,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;last_login_ip&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;172.30.0.1&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;created_at&amp;#34;&lt;/span&gt;: &lt;span class="m"&gt;1758760919&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="c1"&gt;# できた!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;やったぜ。&lt;br&gt;
DifyのConsole APIを呼び出して、ユーザー情報を取得することができた。&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;うまいこと使って、&lt;br&gt;
Difyで作ったアプリだけじゃなくてDify自体の管理も自動化できたらいいな〜。&lt;br&gt;
(というか公式でConsole API SDK出ないかな&amp;hellip;)&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="毛布大好きねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-10-25-dify-console-api-curl/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2025-10-25-dify-console-api-curl/sotochan_hu_2bbe480df5022f9f.jpeg 800w, https://blog.uzimihsr.com/post/2025-10-25-dify-console-api-curl/sotochan_hu_c4657e7bde91f1a6.jpeg 1600w, https://blog.uzimihsr.com/post/2025-10-25-dify-console-api-curl/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>PyPIで古いバージョンのwheelが削除されてないちゃった</title><link>https://blog.uzimihsr.com/post/2025-10-15-old-wheels-removed-from-pypi/</link><pubDate>Wed, 15 Oct 2025 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2025-10-15-old-wheels-removed-from-pypi/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2025-10-15-old-wheels-removed-from-pypi/sotochan.jpeg" alt="Featured image of post PyPIで古いバージョンのwheelが削除されてないちゃった" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;ある日PyPIからPyAV 10.0.0のwheelが消えてpip installがうまくいかないことがあった&lt;/li&gt;
&lt;li&gt;PyAVに限らず、PyPIで公開されているパッケージのwheelは削除されることがある&lt;/li&gt;
&lt;li&gt;どのパッケージも最新版はだいたいwheelが公開されているのでなるべく新しいバージョンを使おう!&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="昨日まで動いてたのに"&gt;昨日まで動いてたのに&amp;hellip;
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://pypi.org/project/av/" target="_blank" rel="noopener"
 &gt;PyAV&lt;/a&gt; 10.*系に依存しているプロジェクトを開発していて、&lt;br&gt;
ある日何気なく再インストール(&lt;code&gt;pip uninstall&lt;/code&gt; &amp;amp; &lt;code&gt;pip install&lt;/code&gt;)したらこれまでインストールできていたものが急に失敗してしまった。&lt;/p&gt;
&lt;p&gt;(DockerのPythonコンテナで実施: &lt;code&gt;docker container run --rm -it python:3.10.12 /bin/bash&lt;/code&gt;)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;(&lt;/span&gt;tutorial-env&lt;span class="o"&gt;)&lt;/span&gt; root@e199492ba090:/# pip install &lt;span class="nv"&gt;av&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;10.*
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Collecting &lt;span class="nv"&gt;av&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;10.*
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Downloading av-10.0.0.tar.gz &lt;span class="o"&gt;(&lt;/span&gt;2.4 MB&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.4/2.4 MB 17.7 MB/s 0:00:00
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Installing build dependencies ... &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Getting requirements to build wheel ... error
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; error: subprocess-exited-with-error
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; × Getting requirements to build wheel did not run successfully.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ &lt;span class="nb"&gt;exit&lt;/span&gt; code: &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ╰─&amp;gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;11&lt;/span&gt; lines of output&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Package libavformat was not found in the pkg-config search path.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Perhaps you should add the directory containing &lt;span class="sb"&gt;`&lt;/span&gt;libavformat.pc&lt;span class="s1"&gt;&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; to the PKG_CONFIG_PATH environment variable
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; Package &amp;#39;&lt;/span&gt;libavformat&lt;span class="s1"&gt;&amp;#39;, required by &amp;#39;&lt;/span&gt;virtual:world&lt;span class="s1"&gt;&amp;#39;, not found
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; Package &amp;#39;&lt;/span&gt;libavcodec&lt;span class="s1"&gt;&amp;#39;, required by &amp;#39;&lt;/span&gt;virtual:world&lt;span class="s1"&gt;&amp;#39;, not found
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; Package &amp;#39;&lt;/span&gt;libavdevice&lt;span class="s1"&gt;&amp;#39;, required by &amp;#39;&lt;/span&gt;virtual:world&lt;span class="s1"&gt;&amp;#39;, not found
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; Package &amp;#39;&lt;/span&gt;libavutil&lt;span class="s1"&gt;&amp;#39;, required by &amp;#39;&lt;/span&gt;virtual:world&lt;span class="s1"&gt;&amp;#39;, not found
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; Package &amp;#39;&lt;/span&gt;libavfilter&lt;span class="s1"&gt;&amp;#39;, required by &amp;#39;&lt;/span&gt;virtual:world&lt;span class="s1"&gt;&amp;#39;, not found
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; Package &amp;#39;&lt;/span&gt;libswscale&lt;span class="s1"&gt;&amp;#39;, required by &amp;#39;&lt;/span&gt;virtual:world&lt;span class="s1"&gt;&amp;#39;, not found
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; Package &amp;#39;&lt;/span&gt;libswresample&lt;span class="s1"&gt;&amp;#39;, required by &amp;#39;&lt;/span&gt;virtual:world&lt;span class="s1"&gt;&amp;#39;, not found
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; pkg-config could not find libraries [&amp;#39;&lt;/span&gt;avformat&lt;span class="s1"&gt;&amp;#39;, &amp;#39;&lt;/span&gt;avcodec&lt;span class="s1"&gt;&amp;#39;, &amp;#39;&lt;/span&gt;avdevice&lt;span class="s1"&gt;&amp;#39;, &amp;#39;&lt;/span&gt;avutil&lt;span class="s1"&gt;&amp;#39;, &amp;#39;&lt;/span&gt;avfilter&lt;span class="s1"&gt;&amp;#39;, &amp;#39;&lt;/span&gt;swscale&lt;span class="s1"&gt;&amp;#39;, &amp;#39;&lt;/span&gt;swresample&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;end of output&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; note: This error originates from a subprocess, and is likely not a problem with pip.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;error: subprocess-exited-with-error
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;× Getting requirements to build wheel did not run successfully.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ &lt;span class="nb"&gt;exit&lt;/span&gt; code: &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;╰─&amp;gt; See above &lt;span class="k"&gt;for&lt;/span&gt; output.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;note: This error originates from a subprocess, and is likely not a problem with pip.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;なんでやねん&amp;hellip;と思いながらもログを見てみると、&lt;br&gt;
なぜかsdist(&lt;code&gt;av-10.0.0.tar.gz&lt;/code&gt;)をダウンロードしてwheelをローカルでビルドしようとしている。&lt;br&gt;
(そして&lt;a class="link" href="https://pyav.basswood-io.com/docs/stable/overview/installation.html#bring-your-own-ffmpeg" target="_blank" rel="noopener"
 &gt;ビルドに必要なFFmpegのパッケージ&lt;/a&gt;が実行環境にないため失敗している)&lt;/p&gt;
&lt;h3 id="wheelはどこへ消えた"&gt;wheelはどこへ消えた?
&lt;/h3&gt;&lt;p&gt;Python Packaging User Guideにも説明がある通り、&lt;br&gt;
そもそもローカルでwheelをビルドしようとしているのはpipが対象のwheelを見つけられなかったからである。&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;When pip, the standard Python package installer, cannot find a wheel to install, it will fall back on downloading a source distribution, compiling a wheel from it, and installing the wheel.
&lt;a class="link" href="https://packaging.python.org/en/latest/discussions/package-formats/#what-is-a-source-distribution" target="_blank" rel="noopener"
 &gt;https://packaging.python.org/en/latest/discussions/package-formats/#what-is-a-source-distribution&lt;/a&gt;&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;ということは、これまではwheelが見つかる状態だったのにある日から対象のwheelが取得できなくなった？&lt;/p&gt;
&lt;p&gt;実際にPyPIでPyAV 10.0.0のFilesを確認すると、たしかにsdistだけ残っていてwheelが消えている。&lt;br&gt;
&lt;a class="link" href="https://pypi.org/project/av/10.0.0/#files" target="_blank" rel="noopener"
 &gt;https://pypi.org/project/av/10.0.0/#files&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="sdist(tar.gz)しかないやん" class="gallery-image" data-flex-basis="419px" data-flex-grow="174" height="1928" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-10-15-old-wheels-removed-from-pypi/sc01.png" srcset="https://blog.uzimihsr.com/post/2025-10-15-old-wheels-removed-from-pypi/sc01_hu_f6a3261f5d8b2c63.png 800w, https://blog.uzimihsr.com/post/2025-10-15-old-wheels-removed-from-pypi/sc01_hu_bf303496a84fecfa.png 1600w, https://blog.uzimihsr.com/post/2025-10-15-old-wheels-removed-from-pypi/sc01_hu_23299aef8fa07d18.png 2400w, https://blog.uzimihsr.com/post/2025-10-15-old-wheels-removed-from-pypi/sc01.png 3366w" width="3366"&gt;&lt;/p&gt;
&lt;p&gt;(ちなみに&lt;a class="link" href="https://web.archive.org/web/20250000000000*/https://pypi.org/project/av/10.0.0/#files" target="_blank" rel="noopener"
 &gt;Wayback Machine&lt;/a&gt;で過去のページをみるとwheelが公開されていた痕跡が&amp;hellip;)&lt;/p&gt;
&lt;p&gt;いきなりwheelが消えるなんて、そんなことある&amp;hellip;？&lt;/p&gt;
&lt;p&gt;&amp;hellip;&lt;/p&gt;
&lt;p&gt;ありました。&lt;/p&gt;
&lt;p&gt;「PyAV 9.2.0のwheelがPyPIから消えたんだけど！(意訳)」というissueでのコメント。&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;Old binary wheels were removed to have space for the 14.4.0 release.&lt;br&gt;
&lt;a class="link" href="https://github.com/PyAV-Org/PyAV/issues/1906#issuecomment-2899577746" target="_blank" rel="noopener"
 &gt;https://github.com/PyAV-Org/PyAV/issues/1906#issuecomment-2899577746&lt;/a&gt;&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;「古いwheelは新しいバージョン(14.4.0)リリースの領域を確保するために削除した(意訳)」&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;はえ〜&amp;hellip;&lt;br&gt;
そんなことあるんすね&amp;hellip;&lt;/p&gt;
&lt;p&gt;自分がPyPIに詳しくないので初めて知ったのだが、&lt;br&gt;
どうやらプロジェクトあたり最大10GBまでのサイズ上限があるらしい。&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;PyPI imposes storage limits on the size of individually uploaded files, as well as the total size of all files in a project.&lt;br&gt;
The current default limits are 100.0 MB for individual files and 10.0 GB for the entire project.
&lt;a class="link" href="https://docs.pypi.org/project-management/storage-limits/" target="_blank" rel="noopener"
 &gt;https://docs.pypi.org/project-management/storage-limits/&lt;/a&gt;&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;まあサイズ上限があるなら古いやつから消すよな&amp;hellip;&lt;br&gt;
ソース(sdist)さえあればビルドできないわけじゃないし&amp;hellip; &lt;del&gt;(自分の環境はダメだったが)&lt;/del&gt;&lt;/p&gt;
&lt;p&gt;ちなみに「重要なパッケージはたとえOwnerであってもPyPI上からの削除を制限した方が良いのでは?」的な議論もあるっぽい。&lt;br&gt;
自分も使う側の人間なので気持ちはわかるが、開発者に責任を押し付けすぎでは？とも思う。&lt;br&gt;
OSSむずかしい&amp;hellip;。&lt;br&gt;
&lt;a class="link" href="https://discuss.python.org/t/stop-allowing-deleting-things-from-pypi/" target="_blank" rel="noopener"
 &gt;https://discuss.python.org/t/stop-allowing-deleting-things-from-pypi/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;あとはPyPIから削除されたwheelをアーカイブしているサイトもいくつかあるようだが、&lt;br&gt;
非公式でメンテナンスは期待できないだろうし、&lt;br&gt;
なにかあった時に自己責任なのであんまり触りたくないな〜という気持ち。&lt;br&gt;
&lt;a class="link" href="https://dashboard.stablebuild.com/pypi-deleted-packages/" target="_blank" rel="noopener"
 &gt;https://dashboard.stablebuild.com/pypi-deleted-packages/&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="素直にバージョンを上げよう"&gt;素直にバージョンを上げよう
&lt;/h3&gt;&lt;p&gt;じゃあどうすんねんという話だが、&lt;br&gt;
古いバージョンへの依存をやめれば良い。&lt;/p&gt;
&lt;p&gt;バージョン縛りをなくしたところ、あっさり成功。&lt;br&gt;
&lt;a class="link" href="https://pypi.org/project/av/16.0.1/#files" target="_blank" rel="noopener"
 &gt;https://pypi.org/project/av/16.0.1/#files&lt;/a&gt; で公開されている最新版のwheelをダウンロード&amp;amp;インストールできた。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;(&lt;/span&gt;tutorial-env&lt;span class="o"&gt;)&lt;/span&gt; root@6673fc741395:/# pip install av
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Collecting av
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Downloading av-16.0.1-cp310-cp310-manylinux_2_28_aarch64.whl.metadata &lt;span class="o"&gt;(&lt;/span&gt;4.6 kB&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Downloading av-16.0.1-cp310-cp310-manylinux_2_28_aarch64.whl &lt;span class="o"&gt;(&lt;/span&gt;38.2 MB&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 38.2/38.2 MB 21.9 MB/s 0:00:01
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Installing collected packages: av
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Successfully installed av-16.0.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;(&lt;/span&gt;tutorial-env&lt;span class="o"&gt;)&lt;/span&gt; root@6673fc741395:/# python
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Python 3.10.12 &lt;span class="o"&gt;(&lt;/span&gt;main, Aug &lt;span class="m"&gt;16&lt;/span&gt; 2023, 08:07:04&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;GCC 12.2.0&lt;span class="o"&gt;]&lt;/span&gt; on linux
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Type &lt;span class="s2"&gt;&amp;#34;help&amp;#34;&lt;/span&gt;, &lt;span class="s2"&gt;&amp;#34;copyright&amp;#34;&lt;/span&gt;, &lt;span class="s2"&gt;&amp;#34;credits&amp;#34;&lt;/span&gt; or &lt;span class="s2"&gt;&amp;#34;license&amp;#34;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; more information.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt;&amp;gt;&amp;gt; import av
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;やったぜ。&lt;/p&gt;
&lt;p&gt;&amp;hellip;というより、そもそも3年前のバージョンに依存して使ってる方が悪いな、これ。&lt;br&gt;
完全に自業自得。&lt;br&gt;
これだけ古いと脆弱性も見つかってるだろうし、そこらへん自分で運用管理できてないのがバレバレ。&lt;br&gt;
自力でビルドもできないOSSフリーライダーはなにをやってもダメ。&lt;/p&gt;
&lt;p&gt;よいこのみんなはおとなしく提供元の意向にしたがって最新のバージョンを使いましょう。&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;Python弱者すぎてこんなので1日消耗してしまったので、備忘録として書いてみた。&lt;/p&gt;
&lt;p&gt;PyPIやpipについてあまり理解せずに使ってしまっていたので勉強になったが、&lt;br&gt;
そもそも古いバージョンに固定して放置している怠惰な自分が悪いわけで、&lt;br&gt;
おそらく大多数の人はひっかからない気がする。&lt;/p&gt;
&lt;p&gt;&lt;del&gt;他のパッケージでもpip install時のログで急にtar.gzをダウンロードしてるときはPyPIでwheelが配布されているか確認するとよさそう。&lt;/del&gt;&lt;br&gt;
弱者はおとなしく新しいバージョンを使おう!&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="ピンク肉球ガン見せねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-10-15-old-wheels-removed-from-pypi/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2025-10-15-old-wheels-removed-from-pypi/sotochan_hu_3cc644b5dc1c12be.jpeg 800w, https://blog.uzimihsr.com/post/2025-10-15-old-wheels-removed-from-pypi/sotochan_hu_b416a1de3400d50f.jpeg 1600w, https://blog.uzimihsr.com/post/2025-10-15-old-wheels-removed-from-pypi/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>9月のそとちゃん</title><link>https://blog.uzimihsr.com/post/2025-10-11-sotochan/</link><pubDate>Sat, 11 Oct 2025 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2025-10-11-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan.jpeg" alt="Featured image of post 9月のそとちゃん" /&gt;&lt;h2 id="そとちゃん"&gt;そとちゃん
&lt;/h2&gt;&lt;h3 id="発作"&gt;発作?
&lt;/h3&gt;&lt;p&gt;9月2日のお昼。&lt;/p&gt;
&lt;p&gt;いつも通り家で仕事をしていると、&lt;br&gt;
そとちゃんが居る居間から「ガタン」と大きな音とそとちゃんの鳴き声がした。&lt;/p&gt;
&lt;p&gt;様子を見に行くとバリバリベッドの横でそとちゃんが転がっていた。&lt;/p&gt;
&lt;p&gt;最初は寝ぼけて落ちたのかと思ったが、&lt;br&gt;
なにか様子がおかしい。&lt;/p&gt;
&lt;p&gt;よくみると黒目が左右に揺れている。&lt;/p&gt;
&lt;div class="video-wrapper"&gt;
 &lt;iframe loading="lazy" 
 src="https://www.youtube.com/embed/yaYjkEQGVYM" 
 allowfullscreen 
 title="YouTube Video"
 &gt;
 &lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;歩き方もふらついていて、&lt;br&gt;
至る所にぶつかってしまう。&lt;/p&gt;
&lt;div class="video-wrapper"&gt;
 &lt;iframe loading="lazy" 
 src="https://www.youtube.com/embed/lJO-pyQH6ow" 
 allowfullscreen 
 title="YouTube Video"
 &gt;
 &lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;おそらく発作のようなものが起きていて、&lt;br&gt;
明らかにいい状態ではないのですぐに病院へ。&lt;/p&gt;
&lt;p&gt;この時点では発作の原因は不明。&lt;/p&gt;
&lt;p&gt;血液検査では腎臓の数値が少し高めなこと以外は何も見つからず、&lt;br&gt;
身体検査も脚の神経反射は正常で、骨折などの怪我もなさそうだった。&lt;/p&gt;
&lt;p&gt;突発性の発作は高齢猫に起こりうるものなので、&lt;br&gt;
まずは様子を見て発作(のようなもの)が1日に何回も起きたり、&lt;br&gt;
5分以上の長い発作が出るようなら専門的な治療を検討するということになった。&lt;/p&gt;
&lt;p&gt;若干脱水気味だったので、&lt;br&gt;
この日は点滴だけ打って帰宅。&lt;/p&gt;
&lt;p&gt;&lt;img alt="病院おつかれさまでした" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan01_hu_1baa38dfda6c2b8.jpeg 800w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan01_hu_5c804326053d542.jpeg 1600w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="ふらふら生活"&gt;ふらふら生活
&lt;/h3&gt;&lt;p&gt;病院から戻った後はケロッとしていて、&lt;br&gt;
おやつを食べていつも通りゴロゴロ。&lt;/p&gt;
&lt;p&gt;&lt;img alt="お気に入りのクッション" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan02_hu_f052c27ac5210695.jpeg 800w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan02_hu_7b0a69c73f0067e2.jpeg 1600w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;基本的には今まで通り元気なのだが歩くときはふらふらしていて、&lt;br&gt;
ジャンプや着地に失敗することが多かった。&lt;/p&gt;
&lt;p&gt;だんだん自分でも嫌になってきたようで、&lt;br&gt;
1週間くらい経った頃には自分から高いところに登らなくなり、&lt;br&gt;
ずっとベッドでゴロゴロしていて元気もなくなってしまった。😭&lt;/p&gt;
&lt;p&gt;&lt;img alt="立ちあがろうとしたときにふらついて転んじゃった" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan03_hu_91c8feeeb1d5b5f3.jpeg 800w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan03_hu_fd51ec1f1a2d79f8.jpeg 1600w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan03.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;懸念の発作は突然体がビクッと動いて眼振が出るようなものがたまにあったが、&lt;br&gt;
そんなに長続きするものでもなく週に1,2回あるかないか、という感じだった。&lt;/p&gt;
&lt;p&gt;あまりひどい発作はなさそうだが見ていないところで危ない転び方をされると怖いので、&lt;br&gt;
このタイミングで&lt;a class="link" href="https://www.nitori-net.jp/ec/product/4968291589511s" target="_blank" rel="noopener"
 &gt;ニトリのペットサークル&lt;/a&gt;を購入。&lt;/p&gt;
&lt;p&gt;&lt;img alt="いきなり閉じ込められてふまんげ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan04_hu_8122c3f0116a938c.jpeg 800w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan04_hu_f4a205656c0ec217.jpeg 1600w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;本人は嫌そうだが、安全のためには仕方ない&amp;hellip;&lt;/p&gt;
&lt;h3 id="猫ドック"&gt;猫ドック
&lt;/h3&gt;&lt;p&gt;最初の受診から約2週後。&lt;/p&gt;
&lt;p&gt;あれからもひどい発作はないもののそとちゃんの調子があまり戻らないことと、&lt;br&gt;
&lt;a class="link" href="https://blog.uzimihsr.com/post/2025-03-16-sotochan/#%E7%8C%AB%E3%83%89%E3%83%83%E3%82%AF" target="_blank" rel="noopener"
 &gt;前回(2月に実施)からの頻度&lt;/a&gt;がちょうどよかったのもあり、&lt;br&gt;
半年ぶりの猫ドックを受けることにした。&lt;/p&gt;
&lt;p&gt;朝に病院に預けて、夕方お迎え。&lt;/p&gt;
&lt;p&gt;&lt;img alt="キャリーは相変わらず好き 今思えばこの時左耳を気にしてたね…" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan05_hu_5558b1a2d4d47438.jpeg 800w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan05_hu_ff9e02c2408296d3.jpeg 1600w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan05.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;詳細な結果は後日受領したのだが、&lt;br&gt;
お迎えのタイミングで当日わかった所見として &lt;strong&gt;左耳中耳炎からの前庭疾患&lt;/strong&gt; という診断が出た。&lt;/p&gt;
&lt;p&gt;左耳がかなり汚れていたのと、&lt;br&gt;
レントゲンでも左側の耳の骨が溶けているような見え方をしていることから外耳炎または中耳炎はほぼ確定、&lt;br&gt;
さらに発作(眼振)やふらつきといった症状が継続しており前庭疾患の疑いが強いということだった。&lt;/p&gt;
&lt;p&gt;前庭疾患の特徴としては平衡感覚が狂って気持ち悪い状態が続くもの。&lt;br&gt;
実際に出ている症状もまさにそれに起因する感じなのでほぼ決まり。&lt;/p&gt;
&lt;p&gt;また、眼振というのは異常がある方向に引っ張られることが多いらしく、&lt;br&gt;
眼振の動画をよくみると黒目が左耳方向に引っ張られてからゆっくり中央に戻るような感じで、&lt;br&gt;
まさに左耳が原因と思われる。&lt;/p&gt;
&lt;p&gt;&lt;img alt="上から撮った頭の骨のレントゲン写真 赤点線で囲んだところの骨が溶けて見える" class="gallery-image" data-flex-basis="306px" data-flex-grow="127" height="1747" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan06.png" srcset="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan06_hu_2692fc5a7eb86c09.png 800w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan06_hu_86a403cc468daa6f.png 1600w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan06.png 2228w" width="2228"&gt;&lt;/p&gt;
&lt;p&gt;まずは原因がわかって一安心。&lt;br&gt;
(実は初診の際、発作の原因が不明の場合は手の打ちようがない=発作を緩和する治療しかないと言われていた)&lt;/p&gt;
&lt;p&gt;他に腎機能の低下などもあったのだが、&lt;br&gt;
ひとまず中耳炎の治療を最優先で進めることに。&lt;/p&gt;
&lt;p&gt;完治までは3ヶ月から半年くらいはかかるとのことで、&lt;br&gt;
そとちゃんの長い闘病生活が始まった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="前回に比べると映りが良い" class="gallery-image" data-flex-basis="180px" data-flex-grow="75" height="1984" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan19.jpeg" srcset="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan19_hu_9a772418eb41c73f.jpeg 800w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan19.jpeg 1488w" width="1488"&gt;&lt;/p&gt;
&lt;h3 id="おくすり"&gt;おくすり
&lt;/h3&gt;&lt;p&gt;中耳炎の治療では抗生剤を飲むことになり、&lt;br&gt;
今回は&lt;a class="link" href="https://www.vm.nval.go.jp/public/detail/14212" target="_blank" rel="noopener"
 &gt;リレキシペットA錠75&lt;/a&gt;が処方された。&lt;/p&gt;
&lt;p&gt;&lt;img alt="処方箋 ついでに目ヤニを抑えるために右目の目薬も処方してもらった" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan07_hu_7064d9d0c16abdec.jpeg 800w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan07_hu_9a63efe3f4e72bfd.jpeg 1600w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan07.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;まずは体の内側から炎症の原因となる菌を抑えるのが目的で、&lt;br&gt;
これが効いてきたら今度は体の外側から与える薬に移行していくとのこと。&lt;/p&gt;
&lt;p&gt;お薬を飲むのは得意なそとちゃん。&lt;/p&gt;
&lt;p&gt;いつも通り砕いてちゅーるに混ぜたらちゃんと食べてくれた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="錠剤なので砕いてちゅーるに混ぜる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan08_hu_7ab9fd8056183898.jpeg 800w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan08_hu_169803d709c4cb74.jpeg 1600w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan08.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="ちゃんと食べてえらい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan09.jpeg" srcset="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan09_hu_644a5add4ce36c86.jpeg 800w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan09_hu_c328f17a444eacf0.jpeg 1600w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan09.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;これが効くとよかったのだが&amp;hellip;&lt;/p&gt;
&lt;h3 id="通院"&gt;通院①
&lt;/h3&gt;&lt;p&gt;当分の間は毎週通院することになったので、1週間後に再診。&lt;/p&gt;
&lt;p&gt;&lt;img alt="キャリーバッグが好きなのは毎回助かっちゃうなあ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan10.jpeg" srcset="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan10_hu_be716240273048c4.jpeg 800w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan10_hu_589e0fc394bfc88d.jpeg 1600w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan10.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;結果はなかなか厳しいものだった。&lt;/p&gt;
&lt;p&gt;1週前からの症状が改善していなかったのに加え、&lt;br&gt;
さらに耳が痛いのか首が傾くようになるなど悪化している様子だった。&lt;/p&gt;
&lt;p&gt;元々長期間の治療を想定していたが、&lt;br&gt;
抗生剤が菌に合ってない可能性を考えて薬を追加することになった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="2つの抗生剤を併用する" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan11.jpeg" srcset="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan11_hu_4018ef39e347b98b.jpeg 800w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan11_hu_8e36c6adafb52f14.jpeg 1600w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan11.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;新しく追加したのは&lt;a class="link" href="https://www.vm.nval.go.jp/public/detail/14221" target="_blank" rel="noopener"
 &gt;ビクタスSS錠20mg&lt;/a&gt;で、&lt;br&gt;
これまで与えていたお薬よりも対象となる菌の種類が多いため効果が期待できるとのこと。&lt;/p&gt;
&lt;p&gt;ただしこれは耐性菌ができやすいということでもあるので、&lt;br&gt;
今後を考えると先生もあまり使いたくなかったらしい。&lt;/p&gt;
&lt;p&gt;そのため、この日は菌を特定するために耳垢、膿を採取して試験(培養)に回し、&lt;br&gt;
対象が特定できたらそれに効く薬に変えることになった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="左が新しいお薬 右は最初から使ってるお薬" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan12.jpeg" srcset="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan12_hu_37e8bcf77c858379.jpeg 800w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan12_hu_27d34c68335fa581.jpeg 1600w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan12.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;さらに脱水気味の状態だったので、点滴を打ってもらってこの日は帰宅。&lt;/p&gt;
&lt;h3 id="食欲不振"&gt;食欲不振
&lt;/h3&gt;&lt;p&gt;お薬を増やしてから最初の数日はちゃんと食べてくれていたのだが、&lt;br&gt;
だんだんと薬入りちゅーるへの反応が悪くなってきた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="あんなに好きだったのに" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan13.jpeg" srcset="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan13_hu_5664b437736927de.jpeg 800w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan13_hu_827e2284e7ffc33a.jpeg 1600w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan13.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;薬が増えて味が悪くなったのか前庭疾患による食欲不振なのかはわからないが、&lt;br&gt;
あんなに大好きだったちゅーるに反応を示さないというのはかなりショックだった。&lt;/p&gt;
&lt;p&gt;試しに薬を薄めたり薬なしのちゅーるも出してみたがそれすら無反応なので、&lt;br&gt;
おそらく後者(食欲不振)が原因だとは思うが&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="かつお節トッピングもまたたびトッピングも不発 どうすれば…" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan14.jpeg" srcset="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan14_hu_ec42a247bfd59382.jpeg 800w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan14_hu_3a89f86ade48ff78.jpeg 1600w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan14.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;他のおやつなら気分が向けば(?)たまに食べることもあるので、&lt;br&gt;
それを祈るしかないという状況&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="めずらしい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan15.jpeg" srcset="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan15_hu_7ac93d908c72ec97.jpeg 800w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan15_hu_61268af0525f1f3.jpeg 1600w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan15.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="通院-1"&gt;通院②
&lt;/h3&gt;&lt;p&gt;さらに1週後、9月4度目の通院。&lt;/p&gt;
&lt;p&gt;&lt;img alt="病院に行く時だけは元気なんだよな" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan16.jpeg" srcset="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan16_hu_2aaff84412cbd727.jpeg 800w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan16_hu_f069f512b33ed8bb.jpeg 1600w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan16.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;状況はあまり良くなっていなかった。&lt;/p&gt;
&lt;p&gt;初期のような眼振は発生しなくなったが、&lt;br&gt;
依然ふらつき等の症状はそのまま。&lt;/p&gt;
&lt;p&gt;さらに前回の診察で試験に回した耳の菌はサンプルが弱く特定まで至らなかったため、&lt;br&gt;
再度試験を行いその結果が出るまでは今のお薬2種を継続することになった。&lt;/p&gt;
&lt;p&gt;特に心配だったのは体重がさらに減っていたこと。&lt;/p&gt;
&lt;p&gt;猫ドックの時でも3.34kgしかなかったのに、&lt;br&gt;
この1週間で3.22kgまで落ちてしまっていた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="激痩せ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan17.jpeg" srcset="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan17_hu_11af3bb18e4443fe.jpeg 800w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan17_hu_99a48098d34bc03.jpeg 1600w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan17.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;この週はご飯とおやつをほぼ残していたのでおそらくそれが原因。&lt;/p&gt;
&lt;p&gt;特に薬入りちゅーるを食べないと状況もよくなるはずがないので、&lt;br&gt;
今後はそとちゃんの口を開けて強制的に錠剤を飲ませることになった&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="なんだか反抗的な顔" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan18.jpeg" srcset="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan18_hu_8b0091027ccbc9f3.jpeg 800w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan18_hu_f67fb1874c13ff3.jpeg 1600w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan18.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;そとちゃんの病気に気づけなかったのがただただ悲しい。&lt;/p&gt;
&lt;p&gt;先生からは適切な頻度で健康診断(猫ドック)を受けていたのが良かったとは言われたものの、&lt;br&gt;
普段から耳を掻いているところを見ていたのになんで気づけなかったのか？と自分を責める気持ちも出てきてしまう。&lt;/p&gt;
&lt;p&gt;9月は最初から最後までこんな感じでそとちゃんの状態が悪く、&lt;br&gt;
それに引きずられる形で自分自身の精神も正直あまり良い状態ではなかった。&lt;/p&gt;
&lt;p&gt;もちろん一番辛いのはそとちゃんなので早く治してあげたいが、&lt;br&gt;
先は長そう&amp;hellip;&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="通院をがんばるねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan_hu_12813ce98fbc0d60.jpeg 800w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan_hu_9a9c5ddaefad395a.jpeg 1600w, https://blog.uzimihsr.com/post/2025-10-11-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>8月のそとちゃん</title><link>https://blog.uzimihsr.com/post/2025-09-13-sotochan/</link><pubDate>Sat, 13 Sep 2025 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2025-09-13-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan.jpeg" alt="Featured image of post 8月のそとちゃん" /&gt;&lt;h2 id="そとちゃん"&gt;そとちゃん
&lt;/h2&gt;&lt;h3 id="バリバリベッド"&gt;バリバリベッド
&lt;/h3&gt;&lt;p&gt;そとちゃんは窓際にある&lt;a class="link" href="https://www.necoichi.co.jp/Products/detail/id=7749" target="_blank" rel="noopener"
 &gt;バリバリベッド&lt;/a&gt;がすき。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ウィンクしちゃう" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan01_hu_91e8d7ee870c9c21.jpeg 800w, https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan01_hu_46974c79d585c809.jpeg 1600w, https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;使いすぎてボロボロになってきたので、新しいものを購入。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ぴかぴかだ" class="gallery-image" data-flex-basis="318px" data-flex-grow="132" height="1495" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan02_hu_ebc6da942cf6a532.jpeg 800w, https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan02_hu_2c503eee031d6d37.jpeg 1600w, https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;新品ってこんなに綺麗だったのか&amp;hellip;&lt;/p&gt;
&lt;p&gt;並べてみると一目瞭然。&lt;/p&gt;
&lt;p&gt;&lt;img alt="はじっこ以外も結構使ってたのね" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan03_hu_c42da4b50a5bc81c.jpeg 800w, https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan03_hu_e5e38a44629911e4.jpeg 1600w, https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan03.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;新しい方も気に入ってくれるか心配だったけど、&lt;br&gt;
割とすんなり使ってくれた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="それでもやっぱりはじっこでしか研がない" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan04_hu_8874759d693ce3e3.jpeg 800w, https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan04_hu_8c66f0fb65679180.jpeg 1600w, https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;気に入ってくれたところで古いものは処分しようと思うのですが&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="ダメですの顔" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan05_hu_8b631ce892f7dae9.jpeg 800w, https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan05_hu_8c069d6c68eb03a1.jpeg 1600w, https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan05.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;ダメでした。&lt;/p&gt;
&lt;p&gt;意図せず増築という形になり部屋が狭くなってしまったが、&lt;br&gt;
ねこは喜んでるのでOKです。😭&lt;/p&gt;
&lt;p&gt;&lt;img alt="大胆な使い方だ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan06_hu_6b6077d0437b0bb4.jpeg 800w, https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan06_hu_b259745d572443ca.jpeg 1600w, https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan06.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;よかったね〜😊&lt;/p&gt;
&lt;p&gt;&lt;img alt="ごまんえつ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan07_hu_2272dd1b7510cc8f.jpeg 800w, https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan07_hu_c2ca4427e89b259a.jpeg 1600w, https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan07.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="鼻水ずるずる"&gt;鼻水ずるずる
&lt;/h3&gt;&lt;p&gt;ある日ちょっと元気がないなと思っていたら、&lt;br&gt;
&lt;a class="link" href="https://blog.uzimihsr.com/post/2025-05-05-sotochan/#%E9%BC%BB%E6%B0%B4" target="_blank" rel="noopener"
 &gt;4月以来&lt;/a&gt;の鼻水が出てしまった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="しょぼしょぼしている" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan08_hu_b34fbc3adfc2a5fa.jpeg 800w, https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan08_hu_9660dd7120213968.jpeg 1600w, https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan08.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;前回ほどひどいくしゃみや鼻くそはないんだけど、心配なので病院へ。&lt;/p&gt;
&lt;p&gt;&lt;img alt="キャリーを出したとたん入ってくれるの、いつもたすかる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan09.jpeg" srcset="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan09_hu_a260fa5029feaa4a.jpeg 800w, https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan09_hu_f9ed6761b03c6db6.jpeg 1600w, https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan09.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;診断結果は鼻炎。&lt;/p&gt;
&lt;p&gt;前回と同じ(?)点鼻薬を処方してもらった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="前回は点眼用の入れ物で0.5%だった" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan10.jpeg" srcset="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan10_hu_58001e428772b694.jpeg 800w, https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan10_hu_8fd2aa5eb8eafa96.jpeg 1600w, https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan10.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;診察のついでにワクチンも打ってもらった。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://blog.uzimihsr.com/post/2024-10-30-sotochan/#%E7%97%85%E9%99%A2" target="_blank" rel="noopener"
 &gt;去年の9月&lt;/a&gt;以来で、&lt;br&gt;
ちょっと早めだけどそれくらいならOKらしい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="注射も全然平気 たすかるなあ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan11.jpeg" srcset="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan11_hu_845ff5935fcb7c44.jpeg 800w, https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan11_hu_fc28d6a13348d53e.jpeg 1600w, https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan11.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;すこし怪しいのは体重が結構落ちてたこと。&lt;/p&gt;
&lt;p&gt;4月の時点では3.8kgだったのが、&lt;br&gt;
この日は&lt;strong&gt;3.46kg&lt;/strong&gt;まで落ちてしまっていた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="激痩せ よくないね" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan12.jpeg" srcset="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan12_hu_23fd7a249dedac49.jpeg 800w, https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan12_hu_f27353564fd5e141.jpeg 1600w, https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan12.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://blog.uzimihsr.com/post/2025-08-15-sotochan/#%E3%81%94%E3%81%AF%E3%82%93%E5%95%8F%E9%A1%8C" target="_blank" rel="noopener"
 &gt;ごはんを残しがち&lt;/a&gt;だったので多少は落ちていると思ったが、&lt;br&gt;
ここまで急激に下がっているのはびっくりだった。&lt;/p&gt;
&lt;p&gt;先生とも相談して、&lt;br&gt;
食べないよりはマシということでおやつ(≠総合栄養食)でもいいからたくさん食べさせる方針になった。&lt;/p&gt;
&lt;p&gt;しょうがないね&amp;hellip;😭&lt;/p&gt;
&lt;p&gt;&lt;img alt="早速おやつをペロリ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan13.jpeg" srcset="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan13_hu_12b5f37af2efe17b.jpeg 800w, https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan13_hu_c27103a59ecf45d6.jpeg 1600w, https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan13.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="ごはん"&gt;ごはん
&lt;/h3&gt;&lt;p&gt;点鼻薬を使って数日で、&lt;br&gt;
鼻水がかなりおさまった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="薬がすぐに効いた ケロッとしてる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan14.jpeg" srcset="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan14_hu_3c5809b40327c01b.jpeg 800w, https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan14_hu_21c0f115bf137085.jpeg 1600w, https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan14.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;そのおかげかわからないが、&lt;br&gt;
あんまり食べなかったごはんをちょっと多めに食べてくれるようになった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="総合栄養食も食べられるじゃん えらい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan15.jpeg" srcset="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan15_hu_abd03944a9956f7e.jpeg 800w, https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan15_hu_69f5e6ebf3793e2f.jpeg 1600w, https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan15.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;総合栄養食はおやつに比べて匂いが弱めなので、&lt;br&gt;
鼻が詰まってる間はわかんなかったのかな&amp;hellip;？&lt;/p&gt;
&lt;p&gt;&lt;img alt="ごちそうさまの顔" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan16.jpeg" srcset="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan16_hu_df64577cad726133.jpeg 800w, https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan16_hu_f043e4465d9f77f0.jpeg 1600w, https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan16.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;この調子で体重も戻るといいな〜🙏&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;体重がガタ落ちしているのは心配。&lt;/p&gt;
&lt;p&gt;鼻も治ったしおやつも増やしたので、&lt;br&gt;
たくさん食べて少しは戻るといいが&amp;hellip;&lt;/p&gt;
&lt;p&gt;これを書いている9月はさらに不穏な兆候が出ており、&lt;br&gt;
あまりいい状態ではない、というのが正直なところ。&lt;/p&gt;
&lt;p&gt;はやく健康な状態に戻るといいな&amp;hellip;😭&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="バリバリベッドの女王" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan_hu_18205c2816eb1426.jpeg 800w, https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan_hu_588d9557b5ab6c05.jpeg 1600w, https://blog.uzimihsr.com/post/2025-09-13-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>7月のそとちゃん</title><link>https://blog.uzimihsr.com/post/2025-08-15-sotochan/</link><pubDate>Fri, 15 Aug 2025 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2025-08-15-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan.jpeg" alt="Featured image of post 7月のそとちゃん" /&gt;&lt;h2 id="そとちゃん"&gt;そとちゃん
&lt;/h2&gt;&lt;h3 id="ごはん問題"&gt;ごはん問題
&lt;/h3&gt;&lt;p&gt;最近またそとちゃんがごはんを残すようになってしまった😭&lt;/p&gt;
&lt;p&gt;&lt;img alt="これいらないの顔" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan01_hu_cddcff40eaee2540.jpeg 800w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan01_hu_8066b4440556e291.jpeg 1600w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://blog.uzimihsr.com/post/2024-12-09-sotochan/#%E3%81%94%E3%81%AF%E3%82%93%E9%A3%9F%E3%81%B9%E3%81%8F%E3%82%89%E3%81%B9" target="_blank" rel="noopener"
 &gt;去年のごはんイヤイヤ期&lt;/a&gt;はウェットフードを変えることでなんとか改善したが、&lt;br&gt;
今回は同じごはんでも日によって食べたり食べなかったり&amp;hellip;という感じで手強い。&lt;/p&gt;
&lt;p&gt;&lt;img alt="同じロイヤルカナンだけど食べる日もある" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan02_hu_66e34d2097333a15.jpeg 800w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan02_hu_37a2ce92d85ba22a.jpeg 1600w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="割と気に入ってたはずのカルカンでもこのありさま これでもマシな方" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan03_hu_8b9ddae09a262f0b.jpeg 800w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan03_hu_2913a10245889052.jpeg 1600w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan03.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;特定の味が嫌いになったとか飽きたならわかるんだけど、&lt;br&gt;
食べるときは食べるというのが厄介。&lt;/p&gt;
&lt;p&gt;&lt;img alt="開き直って昔食べなくなった黒缶をあげたら食べた どういうこと" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan04_hu_8dafe0fcc89955c8.jpeg 800w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan04_hu_10fd2ccc57429f5c.jpeg 1600w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;おやつならいつでも食べるので、&lt;br&gt;
(毎度のことだが)やっぱり食欲不振ではなさそう。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ちゅーるはいつでも大歓迎" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan05_hu_2ec0666e4fc11aa2.jpeg 800w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan05_hu_df785ab1b68fbd6e.jpeg 1600w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan05.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;おやつトッピング作戦を試すが、&lt;br&gt;
それも効果は薄めというか今度はトッピングだけ食べる悪質行為が発生してしまう😭&lt;/p&gt;
&lt;p&gt;&lt;img alt="ふりかけかけての顔" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan06_hu_c392761883463432.jpeg 800w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan06_hu_a01bae6a4c21445c.jpeg 1600w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan06.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;それでも食べないよりはマシだが&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="ふりかけ なくなった" class="gallery-image" data-flex-basis="352px" data-flex-grow="146" height="1352" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan07_hu_384cd6271cc210.jpeg 800w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan07_hu_ac6dce7656484644.jpeg 1600w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan07.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;困っちゃうねえ&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="おやつ以外も食べてね" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan08_hu_27307d4e0e939a99.jpeg 800w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan08_hu_31f9c7f0a57da478.jpeg 1600w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan08.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="ねこが落ちてる"&gt;ねこが落ちてる
&lt;/h3&gt;&lt;p&gt;常に冷房ガンガンの部屋なのに、&lt;br&gt;
夏になるとねこが落ちているのは何故だろう&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="おちてる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan09.jpeg" srcset="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan09_hu_97058c28fa02158d.jpeg 800w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan09_hu_f8692c8a257efa2.jpeg 1600w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan09.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;夏バテ？&lt;/p&gt;
&lt;p&gt;&lt;img alt="台所におちてる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan10.jpeg" srcset="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan10_hu_cc7aadb2d5a60655.jpeg 800w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan10_hu_b676bbee0ea2403f.jpeg 1600w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan10.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;気がつくといろんなところで落ちていてかわいい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="居間にもおちてる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan11.jpeg" srcset="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan11_hu_1357435280cbad01.jpeg 800w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan11_hu_836d4e085fcc092.jpeg 1600w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan11.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;落ち方にもいろいろあって、見ていて飽きない。&lt;/p&gt;
&lt;p&gt;&lt;img alt="おちながらのびてる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan12.jpeg" srcset="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan12_hu_c3abef9cdadb4e6.jpeg 800w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan12_hu_d368ec6502998b4.jpeg 1600w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan12.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;いいね〜〜👍&lt;/p&gt;
&lt;p&gt;&lt;img alt="自由" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan13.jpeg" srcset="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan13_hu_fc31a419d034e52b.jpeg 800w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan13_hu_ff5f74c3f0581928.jpeg 1600w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan13.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="スツール"&gt;スツール
&lt;/h3&gt;&lt;p&gt;だいぶ前に買った&lt;a class="link" href="https://www.nitori-net.jp/ec/product/7806137s" target="_blank" rel="noopener"
 &gt;ニトリのペットが入れるスツール&lt;/a&gt;が何故か今になってお気に入り。&lt;/p&gt;
&lt;p&gt;&lt;img alt="もちろん中でなく上に乗る 期待を裏切らない" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan15.jpeg" srcset="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan15_hu_69ca6946fea10185.jpeg 800w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan15_hu_6a49ea4ac54fe339.jpeg 1600w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan15.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="そのままここで寝ちゃう" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan14.jpeg" srcset="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan14_hu_1eb598e0397a9679.jpeg 800w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan14_hu_c7dfc7fa0a45ddf0.jpeg 1600w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan14.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;すごいときはトイレ以外丸一日ここで過ごしたりする。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ちょっとだけ爪が引っかかるのがいい感じ？" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan16.jpeg" srcset="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan16_hu_2977f4be2543aa86.jpeg 800w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan16_hu_7e82b3e37c8a1f54.jpeg 1600w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan16.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="中に入るのは超レア" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan17.jpeg" srcset="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan17_hu_7c4e73a7f5db1e5d.jpeg 800w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan17_hu_b04a3aba266f5e42.jpeg 1600w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan17.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;何がそんなにいいのかは謎だけど、&lt;br&gt;
たくさん使ってくれるのはうれしい。&lt;/p&gt;
&lt;p&gt;買ってよかった〜👍&lt;/p&gt;
&lt;p&gt;&lt;img alt="うごかない" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan18.jpeg" srcset="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan18_hu_98ab3283a3d00661.jpeg 800w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan18_hu_44178989ec096cf2.jpeg 1600w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan18.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;ごはんは残すけど、ねこは元気。&lt;br&gt;
暑さに負けず(?)毎日自由に暮らしている。&lt;/p&gt;
&lt;p&gt;健康のためにもごはん、残さないでほしいが&amp;hellip;😭&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="綿を補充したしろたんに慣れ始めたねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan_hu_16f0cd401e2ce211.jpeg 800w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan_hu_9ad2c00ba7b0124e.jpeg 1600w, https://blog.uzimihsr.com/post/2025-08-15-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>6月のそとちゃん</title><link>https://blog.uzimihsr.com/post/2025-07-21-sotochan/</link><pubDate>Mon, 21 Jul 2025 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2025-07-21-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan.jpeg" alt="Featured image of post 6月のそとちゃん" /&gt;&lt;h2 id="そとちゃん"&gt;そとちゃん
&lt;/h2&gt;&lt;h3 id="袋"&gt;袋
&lt;/h3&gt;&lt;p&gt;そとちゃんは袋が好き。&lt;/p&gt;
&lt;p&gt;&lt;img alt="出たり入ったり" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan01_hu_6c6bd476a38bfd9e.jpeg 800w, https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan01_hu_4a6ecd1a7d24762.jpeg 1600w, https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;ニンゲンの遠出でお留守番してもらったときはお土産を色々買ってみるけど、&lt;br&gt;
一番喜ぶのはやっぱり紙袋。&lt;/p&gt;
&lt;p&gt;その中でも最近は&lt;a class="link" href="https://www.wbstudiotour.jp/" target="_blank" rel="noopener"
 &gt;スタジオツアー東京&lt;/a&gt;でもらった紙袋が結構いい感じ。&lt;/p&gt;
&lt;p&gt;&lt;img alt="お気に入り" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan02_hu_59ebf3ef544de973.jpeg 800w, https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan02_hu_7bcd9f3cdee0a9f5.jpeg 1600w, https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;紙が結構丈夫で、あんまりへたらない。&lt;br&gt;
激しく遊んでもまだまだ入れちゃうのが良い。&lt;/p&gt;
&lt;p&gt;硬ければ良いわけではなく、&lt;br&gt;
ブランド物とかの加工された紙袋だと硬すぎてお気に召さないことが多いのだが、&lt;br&gt;
これは程よい硬さがいい感じっぽい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="紙が強いから入り口つぶれにくい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan03_hu_b4a9ab5b2bc8b432.jpeg 800w, https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan03_hu_7755f3f1d8cd0a19.jpeg 1600w, https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan03.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;気に入ってくれてよかった〜👍&lt;/p&gt;
&lt;h3 id="ごっちゃし座布団"&gt;ごっちゃし座布団
&lt;/h3&gt;&lt;p&gt;おいしいもつ煮が食べられると聞いてグルメ目的で幕張の野球場に行ってみたら、&lt;br&gt;
入場特典で&lt;a class="link" href="https://www.marines.co.jp/news/detail/202500633749.html" target="_blank" rel="noopener"
 &gt;ごっちゃし座布団&lt;/a&gt;がもらえたのでそとちゃんに贈呈してみた。&lt;br&gt;
(野球の試合をやっていた気もするけどもつ煮が美味しすぎてあまり覚えていない)&lt;/p&gt;
&lt;p&gt;&lt;img alt="謎のカタカナが書いてあるけどよくわからない" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan04_hu_ad6d40fc160279ac.jpeg 800w, https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan04_hu_8a07577073bbb082.jpeg 1600w, https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;座布団はかなり小さめで、ねこにはちょうどいい大きさ。&lt;/p&gt;
&lt;p&gt;&lt;img alt="乗りこなしてる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan05_hu_7a8518dab0100087.jpeg 800w, https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan05_hu_b01291188e3af001.jpeg 1600w, https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan05.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;しかもかなり軽くて、&lt;br&gt;
あんまり強くないそとちゃんの力でも爪を引っ掛ければ動かせるのでいい相撲相手になっている。&lt;/p&gt;
&lt;p&gt;&lt;img alt="22人連続アウトの情けない打線にお怒りの様子" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan06_hu_f9ff2213d8742aff.jpeg 800w, https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan06_hu_d814808eb1e2ae4e.jpeg 1600w, https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan06.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;ボロボロになるまで遊ぼうね&amp;hellip;&lt;/p&gt;
&lt;h3 id="お風呂"&gt;お風呂
&lt;/h3&gt;&lt;p&gt;ブラッシングが嫌いでサボりまくりのそとちゃん、&lt;br&gt;
ある日毛玉をちょっと多めに吐いてしまった。&lt;/p&gt;
&lt;p&gt;普段は上手に吐くのだが、&lt;br&gt;
今回はそこそこ汚れてしまったので久しぶりのお風呂が決定。&lt;/p&gt;
&lt;p&gt;&lt;img alt="これから何が起きるかわかってない顔" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan07_hu_4d9cade329d998fd.jpeg 800w, https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan07_hu_8c39884b83fc46e0.jpeg 1600w, https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan07.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://youtu.be/CKlk8awp0Qs?si=evXEsiwMZboekz_F" target="_blank" rel="noopener"
 &gt;最後に入った&lt;/a&gt;のは2~3年前?&lt;br&gt;
だいぶ久しぶりだった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="察した もう逃げたい" class="gallery-image" data-flex-basis="319px" data-flex-grow="133" height="1774" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan08.JPG" srcset="https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan08_hu_8fbc8f71cbb3641d.JPG 800w, https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan08_hu_22ad0e065c13d0d1.JPG 1600w, https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan08.JPG 2364w" width="2364"&gt;&lt;/p&gt;
&lt;p&gt;例に漏れずそとちゃんも水が苦手なので、なるべく手短に済ませる。&lt;/p&gt;
&lt;p&gt;まずは湯船に張ったぬるま湯で身体を濡らす。&lt;/p&gt;
&lt;p&gt;&lt;img alt="かわいいけどこれはすごく嫌な気持ちの顔" class="gallery-image" data-flex-basis="356px" data-flex-grow="148" height="1195" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan09.JPG" srcset="https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan09_hu_3ae71b00bf6a22ca.JPG 800w, https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan09_hu_4ba39797b66bdd68.JPG 1600w, https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan09.JPG 1774w" width="1774"&gt;&lt;/p&gt;
&lt;p&gt;地肌まで濡れたらねこ用シャンプーで全身を洗い、&lt;br&gt;
やさしめのシャワーともう一度湯船ですすいで終わり。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ニンゲン ゆるさない" class="gallery-image" data-flex-basis="414px" data-flex-grow="172" height="1115" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan10.JPG" srcset="https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan10_hu_952145fa1930e38d.JPG 800w, https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan10_hu_c7ef13a4bb11db70.JPG 1600w, https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan10.JPG 1925w" width="1925"&gt;&lt;/p&gt;
&lt;p&gt;そとちゃんは協力的ではないが抵抗が弱めだったので、&lt;br&gt;
お風呂自体は30分かからないくらいで終了。&lt;/p&gt;
&lt;p&gt;後はタオルドライと、&lt;br&gt;
暴れるのでちゅーるで釣りながらぬるめのドライヤーで仕上げ。&lt;/p&gt;
&lt;p&gt;&lt;img alt="いやな思いをした" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan11.jpeg" srcset="https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan11_hu_fbf65b5003d23ff.jpeg 800w, https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan11_hu_5abe8ac1ad2a369c.jpeg 1600w, https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan11.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;おつかれさまでした&amp;hellip;🛁&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;やはり夏はいろいろめんどくさくて更新が遅れてしまう。&lt;/p&gt;
&lt;p&gt;7月中旬にこれを書いているのだが今年の夏も暑いので、&lt;br&gt;
冷房をうまく使ってねこも人間も体調を崩さないように気をつけたい。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="いじけるとナマコみたいになるねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan_hu_31db00d383460a6b.jpeg 800w, https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan_hu_60e0996f336abaf1.jpeg 1600w, https://blog.uzimihsr.com/post/2025-07-21-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>5月のそとちゃん</title><link>https://blog.uzimihsr.com/post/2025-06-06-sotochan/</link><pubDate>Fri, 06 Jun 2025 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2025-06-06-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan.jpg" alt="Featured image of post 5月のそとちゃん" /&gt;&lt;h2 id="そとちゃん"&gt;そとちゃん
&lt;/h2&gt;&lt;h3 id="誕生日"&gt;誕生日
&lt;/h3&gt;&lt;p&gt;5月1日はそとちゃんの誕生日。🎂&lt;/p&gt;
&lt;p&gt;元野良なので推定だけど、&lt;br&gt;
うちに来たのが5月1日なのでそういうことにしている。&lt;/p&gt;
&lt;p&gt;&lt;img alt="りりしい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan01_hu_8220dbe4dc7fe800.jpeg 800w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan01_hu_3b86a45790e3a5ba.jpeg 1600w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;今年で推定9さい。&lt;/p&gt;
&lt;p&gt;3さいのときにうちに来てもう6年&amp;hellip;&lt;br&gt;
推定年齢が間違っていなければ野良だった期間の倍以上はうちで一緒に過ごしていることになる。&lt;/p&gt;
&lt;p&gt;すこしは家猫っぽくなっただろうか？&lt;/p&gt;
&lt;p&gt;&lt;img alt="たまに見せる野生の名残にドキッとしちゃうね クッションでだらけてなければ…" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan02_hu_ce8785d825afa1ae.jpeg 800w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan02_hu_b1d29d131c36c0f9.jpeg 1600w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;とりあえず元気に誕生日を迎えられてよかった。&lt;br&gt;
(実はこのときまだちょっと&lt;a class="link" href="https://blog.uzimihsr.com/post/2025-05-05-sotochan/#%E9%BC%BB%E6%B0%B4" target="_blank" rel="noopener"
 &gt;鼻水出てた&lt;/a&gt;けど&amp;hellip;)&lt;/p&gt;
&lt;p&gt;今年の誕生日プレゼントは色々考えたがこれというものが決まらず、&lt;br&gt;
くったくたになってしまった寝床のしろたんを修理してあげることにした。&lt;/p&gt;
&lt;p&gt;&lt;img alt="くったくたでぺったんこ 毛が溜まっているところがねこのポジション" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan03_hu_86c58a8bebd78de1.jpeg 800w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan03_hu_66e7bbaaa91fd783.jpeg 1600w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan03.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;うちにきたときからずっと寝床にしているしろたん。&lt;/p&gt;
&lt;p&gt;同じポジションでしか使わないもんだから、&lt;br&gt;
もう底に触れるくらい綿が抜けてしまって寝心地が悪そう。&lt;/p&gt;
&lt;p&gt;中身の綿袋を外し、&lt;br&gt;
ユザワヤで綿とテープを買ってきて補修&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="大手術" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan04_hu_f0d052f3bd481038.jpeg 800w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan04_hu_5f241ea15cf79752.jpeg 1600w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;素人作業だけどなんとか復活できたのでこちらをプレゼントとして献上。&lt;/p&gt;
&lt;p&gt;&lt;img alt="復活 外のカバーは洗うと不機嫌になるのでそのまま" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan05_hu_8649cbbfabe95d2e.jpeg 800w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan05_hu_d9b34e7b4c3e77e1.jpeg 1600w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan05.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&amp;hellip;が。&lt;/p&gt;
&lt;p&gt;どうやら綿をパンパンに詰めすぎてしまったようで、&lt;br&gt;
クッション性がなくなってしまった。&lt;/p&gt;
&lt;p&gt;そとちゃんが乗っても全然沈まなくて、寝返りを打つと転げ落ちてしまう。&lt;/p&gt;
&lt;p&gt;&lt;img alt="なんか思ってたのと違う 全然沈まない" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan06_hu_ad22c92f12568222.jpeg 800w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan06_hu_202885880960f95d.jpeg 1600w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan06.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;やってしまった&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="微妙な表情 ごめんて" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan07_hu_6ba6dece4dccd85a.jpeg 800w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan07_hu_48f8253fcc363dc9.jpeg 1600w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan07.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;結局そとちゃんもお気に召さず、&lt;br&gt;
今は&lt;a class="link" href="https://blog.uzimihsr.com/post/2025-02-28-sotochan/#%E3%82%82%E3%81%A1%E3%82%82%E3%81%A1%E3%82%AF%E3%83%83%E3%82%B7%E3%83%A7%E3%83%B3" target="_blank" rel="noopener"
 &gt;モチモチクッション&lt;/a&gt;を寝床にしている。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ごめん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan08_hu_10236609854bdeba.jpeg 800w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan08_hu_3d9ef33053102a8d.jpeg 1600w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan08.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;プレゼントはコケてしまったので、&lt;br&gt;
ごちそうで挽回。&lt;/p&gt;
&lt;p&gt;&lt;img alt="一番好きなおやつシーバに焼きかつおをほぐしてトッピング カロリーマシマシ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan11.jpeg" srcset="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan11_hu_7803e97d2a0ddef2.jpeg 800w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan11_hu_125b7ddeba4a2781.jpeg 1600w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan11.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;これでなんとかゆるしてほしい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ドカ食い" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan12.jpeg" srcset="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan12_hu_d7aca6ae83417ef.jpeg 800w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan12_hu_e91480382b221599.jpeg 1600w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan12.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;しろたんはいっぱいこねてまた自分好みにできるといいですね&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="不定期で整備中 完成未定" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan09.jpeg" srcset="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan09_hu_2a95e931a2be6a99.jpeg 800w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan09_hu_541f0e95f5555ac7.jpeg 1600w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan09.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="記念写真"&gt;記念写真
&lt;/h3&gt;&lt;p&gt;5月中旬には鼻水もだいぶ治ったので、&lt;br&gt;
&lt;a class="link" href="https://blog.uzimihsr.com/post/2024-06-06-sotochan/#%E8%A8%98%E5%BF%B5%E5%86%99%E7%9C%9F" target="_blank" rel="noopener"
 &gt;毎年恒例&lt;/a&gt;の記念写真を撮りに行った。&lt;/p&gt;
&lt;p&gt;&lt;img alt="控室にて やる気ありそう" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan10.jpeg" srcset="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan10_hu_7290df1faf0f4ef0.jpeg 800w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan10_hu_5fec29dc1a44d59d.jpeg 1600w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan10.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;相変わらずスタジオではやりたい放題。&lt;/p&gt;
&lt;p&gt;&lt;img alt="探検が忙しい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan13.jpeg" srcset="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan13_hu_b130f164e87618e7.jpeg 800w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan13_hu_11957cedbc7a269d.jpeg 1600w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan13.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="撮影どころではない" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan14.jpeg" srcset="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan14_hu_aa746e9d1334b21d.jpeg 800w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan14_hu_f0146ff11151e0a3.jpeg 1600w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan14.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;スタッフさんも慣れっこなので、&lt;br&gt;
一通り遊ばせてもらいそとちゃんが落ち着いてから撮影開始。&lt;/p&gt;
&lt;p&gt;&lt;img alt="写真撮られるだけでベタ褒めされる いいご身分" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan15.jpeg" srcset="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan15_hu_9ca604f5f740b759.jpeg 800w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan15_hu_62c6cf5e21b9e354.jpeg 1600w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan15.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;たくさん遊んで満足したのか、&lt;br&gt;
今年はおとなしくねこ単体でかなりの枚数を撮影することができた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="なんかかっこいい(?)" class="gallery-image" data-flex-basis="360px" data-flex-grow="150" height="3333" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan16.jpg" srcset="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan16_hu_b6d2e27cc88c8556.jpg 800w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan16_hu_b5fb7200a73a8db1.jpg 1600w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan16_hu_302931ee83b69487.jpg 2400w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan16.jpg 5000w" width="5000"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="デスクトップ背景にしたい" class="gallery-image" data-flex-basis="360px" data-flex-grow="150" height="3333" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan17.jpg" srcset="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan17_hu_69c376ece7b9de4.jpg 800w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan17_hu_64596654d0f993d7.jpg 1600w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan17_hu_73329e508ea9314a.jpg 2400w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan17.jpg 5000w" width="5000"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="ひとりでお座り すごい" class="gallery-image" data-flex-basis="159px" data-flex-grow="66" height="5000" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan18.jpg" srcset="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan18_hu_298c883c35414d76.jpg 800w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan18_hu_603816c8c2d0d879.jpg 1600w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan18_hu_693174badc59c1b3.jpg 2400w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan18.jpg 3333w" width="3333"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="スマホの壁紙にした" class="gallery-image" data-flex-basis="159px" data-flex-grow="66" height="5000" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan19.jpg" srcset="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan19_hu_6acd529ab284a7a3.jpg 800w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan19_hu_29f41f4812d992a4.jpg 1600w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan19_hu_3f3ad6f8f5820838.jpg 2400w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan19.jpg 3333w" width="3333"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="くわっ" class="gallery-image" data-flex-basis="360px" data-flex-grow="150" height="3333" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan20.jpg" srcset="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan20_hu_e6dd07a96db27b.jpg 800w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan20_hu_1ce835142b39a367.jpg 1600w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan20_hu_d5992993635076e5.jpg 2400w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan20.jpg 5000w" width="5000"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="ふわぁ〜" class="gallery-image" data-flex-basis="360px" data-flex-grow="150" height="3333" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan21.jpg" srcset="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan21_hu_8db5e25da8c213b5.jpg 800w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan21_hu_861580ffa33e2e0.jpg 1600w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan21_hu_c44954da6f4929fa.jpg 2400w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan21.jpg 5000w" width="5000"&gt;&lt;/p&gt;
&lt;p&gt;がんばりました&amp;hellip;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;無事にそとちゃんが9さいの誕生日を迎えられた。🎉&lt;br&gt;
歯は数本抜けちゃったし、ちょこちょこ病院に行く回数も増えてきたけどそとちゃん本人(猫)はまだまだ元気いっぱい。&lt;/p&gt;
&lt;p&gt;ねこの9さいは人間でいうと50~60歳くらいのレディなのでそれなりに敬って接したほうが良いのかもしれないが、&lt;br&gt;
そとちゃんは小さくてかわいいし自分からすると今も赤ちゃんみたいでベロベロに甘やかしている。&lt;/p&gt;
&lt;p&gt;10歳の誕生日も元気に迎えられるよう頑張りましょうね&amp;hellip;(主に人間が)&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="今年のベストショット(あくびの直前)" class="gallery-image" data-flex-basis="360px" data-flex-grow="150" height="3333" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan_hu_79439d8a458d21ea.jpg 800w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan_hu_6078d01abf04548c.jpg 1600w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan_hu_c830a0d71851678a.jpg 2400w, https://blog.uzimihsr.com/post/2025-06-06-sotochan/sotochan.jpg 5000w" width="5000"&gt;&lt;/p&gt;</description></item><item><title>4月のそとちゃん</title><link>https://blog.uzimihsr.com/post/2025-05-05-sotochan/</link><pubDate>Mon, 05 May 2025 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2025-05-05-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan.jpeg" alt="Featured image of post 4月のそとちゃん" /&gt;&lt;h2 id="そとちゃん"&gt;そとちゃん
&lt;/h2&gt;&lt;h3 id="こたつ"&gt;こたつ
&lt;/h3&gt;&lt;p&gt;4月になり暖かい日も増えてきたが、&lt;br&gt;
そとちゃんは相変わらずこたつを堪能している。&lt;/p&gt;
&lt;p&gt;&lt;img alt="満足げ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan01_hu_69917072c6637735.jpeg 800w, https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan01_hu_97e9561d07fa3a17.jpeg 1600w, https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;最近はあまり電源を点けないので中に入ることは少なくなってきたが、&lt;br&gt;
代わりにこたつに入った人の膝に乗るのがお気に入りになっている。&lt;/p&gt;
&lt;p&gt;&lt;img alt="膝というよりもはや股" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan02_hu_b2d34e60167fd44c.jpeg 800w, https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan02_hu_38240e52f5070e97.jpeg 1600w, https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;このポジションはかなり好きみたいで、&lt;br&gt;
こたつに入るとすぐに乗ってくるし誰もこたつに入っていないと鳴いて呼びにくる。&lt;/p&gt;
&lt;p&gt;&lt;img alt="基本的に30分くらいはこのまま" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan03_hu_cab31a40713e484d.jpeg 800w, https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan03_hu_72c2451de6205ccd.jpeg 1600w, https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan03.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;かわいいね&amp;hellip;&lt;br&gt;
(片付けられない)&lt;/p&gt;
&lt;h3 id="箱"&gt;箱
&lt;/h3&gt;&lt;p&gt;最近また荷物が届いたので箱を献上。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ヨドバシの段ボールはサイズも耐久性もいい感じ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan04_hu_d507b1ea83c0f7cf.jpeg 800w, https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan04_hu_5ad4fcffe7d00602.jpeg 1600w, https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;元々袋派のそとちゃんも、&lt;br&gt;
今ではすっかり箱を堪能するようになっている。&lt;br&gt;
(単に袋が最近溜まらないだけなのだが)&lt;/p&gt;
&lt;p&gt;&lt;img alt="箱に隠れて獲物を狙うのがすき" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan05_hu_846f3b97c89b0fd2.jpeg 800w, https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan05_hu_bb25ac6836b368f7.jpeg 1600w, https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan05.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="はやい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan06_hu_b58c428255b496dd.jpeg 800w, https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan06_hu_5f266c40d48f5c2a.jpeg 1600w, https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan06.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;今回の箱はフィット感が良く(?)、&lt;br&gt;
よく入って遊んでいる。&lt;/p&gt;
&lt;p&gt;&lt;img alt="謎の貫禄" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan07_hu_b07644a99d0ee256.jpeg 800w, https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan07_hu_ba06297d1bb8d4c8.jpeg 1600w, https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan07.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;楽しそうでなにより。&lt;/p&gt;
&lt;h3 id="鼻水"&gt;鼻水
&lt;/h3&gt;&lt;p&gt;月の後半からそとちゃんの鼻水が目立つようになってしまった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="鼻水ずるずる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan08_hu_85fa0c8a0edf1cc9.jpeg 800w, https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan08_hu_780b1adc893d5d3a.jpeg 1600w, https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan08.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;慢性的にくしゃみが出ていて、&lt;br&gt;
ずっと鼻をふがふがさせている。&lt;/p&gt;
&lt;p&gt;&lt;img alt="つらそう" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan09.jpeg" srcset="https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan09_hu_82874fe6e8e77770.jpeg 800w, https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan09_hu_e453403f2ebda0d6.jpeg 1600w, https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan09.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;それ以外は食欲もあり元気なのだが、&lt;br&gt;
1週間くらい経って透明だった鼻水が若干白くなり、&lt;br&gt;
鼻くそも目立つようになったので念のため病院へ。&lt;/p&gt;
&lt;p&gt;&lt;img alt="やっぱりキャリーには自分から入る" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan10.jpeg" srcset="https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan10_hu_a912f008cc999f10.jpeg 800w, https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan10_hu_109197d890b6bf6e.jpeg 1600w, https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan10.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;当日の体重は3.8kgで痩せ気味だがあまり問題なし、&lt;br&gt;
体温も37.9℃でおおむね平熱だった。&lt;/p&gt;
&lt;p&gt;鼻水を採取してそのまま検査へ。&lt;/p&gt;
&lt;p&gt;結果は細菌感染による鼻炎という診断だった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="鼻水の成分 白血球と球菌がたくさんいる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan11.jpeg" srcset="https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan11_hu_853f58c50e9a4ea0.jpeg 800w, https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan11_hu_95be8e33ddb63775.jpeg 1600w, https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan11.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;ワクチンを打っていたので風邪系はあまり無いと勝手に思っていたが、&lt;br&gt;
鼻水の成分的を見る限りは細菌に反応しているとのこと。&lt;/p&gt;
&lt;p&gt;なんの菌に感染しているのか特定するには時間がかかって大変なので、&lt;br&gt;
ひとまずの対応として菌の繁殖を抑えるために抗菌性の点鼻薬(&lt;a class="link" href="https://www.petmedic-pro.com/product.php?id=2334" target="_blank" rel="noopener"
 &gt;ベストロン&lt;/a&gt;)を処方してもらった。&lt;br&gt;
(これでも改善しないならより精密な検査、場合によっては菌の特定をするとのこと)&lt;/p&gt;
&lt;p&gt;&lt;img alt="点眼用とあるが今回は鼻から入れるらしい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan12.jpeg" srcset="https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan12_hu_973632a5aec8102b.jpeg 800w, https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan12_hu_1269fd6166b6db2c.jpeg 1600w, https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan12.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;猫の点鼻薬は初めてなのだが、&lt;br&gt;
目薬と同じ要領で上を向かせて後ろから垂らせばいいらしい。&lt;br&gt;
(目薬は昔何回か使ったことがある)&lt;/p&gt;
&lt;p&gt;&lt;img alt="嫌そうな顔" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan13.jpeg" srcset="https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan13_hu_f07cb2e015098f9f.jpeg 800w, https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan13_hu_ed0097b4820ed6fe.jpeg 1600w, https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan13.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;家に帰って早速試したところ、&lt;br&gt;
なんとか鼻に入れることができた。&lt;br&gt;
(かなり嫌がるが&amp;hellip;)&lt;/p&gt;
&lt;p&gt;&lt;img alt="対価" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan14.jpeg" srcset="https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan14_hu_242fa2cc41494663.jpeg 800w, https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan14_hu_e07d298f58411181.jpeg 1600w, https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan14.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;はやく治るといいな&amp;hellip;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;今年に入ってからちょこちょこ病院に行くことが増えてきたが、&lt;br&gt;
本人(猫)は割と元気なのが救い。&lt;/p&gt;
&lt;p&gt;5月はそとちゃんの誕生日(推定)もあるので、&lt;br&gt;
健康な9歳を迎えたいね&amp;hellip;&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="しもべの心配をよそに遊びまわるねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan_hu_2146ae6a0ffcdd19.jpeg 800w, https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan_hu_99f00b5e1c29b6d.jpeg 1600w, https://blog.uzimihsr.com/post/2025-05-05-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>3月のそとちゃん</title><link>https://blog.uzimihsr.com/post/2025-04-12-sotochan/</link><pubDate>Sat, 12 Apr 2025 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2025-04-12-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan.jpeg" alt="Featured image of post 3月のそとちゃん" /&gt;&lt;h2 id="そとちゃん"&gt;そとちゃん
&lt;/h2&gt;&lt;h3 id="スケーリング"&gt;スケーリング
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://blog.uzimihsr.com/post/2025-03-16-sotochan/" target="_blank" rel="noopener"
 &gt;歯肉炎がひどくて歯が抜けてしまった&lt;/a&gt;そとちゃん。&lt;/p&gt;
&lt;p&gt;残った歯を守るためにも2年ぶりのスケーリングを受けることに。&lt;/p&gt;
&lt;p&gt;当日の朝は珍しくキャリーに入るのを渋ったが無事病院へ&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="ふまんげ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan01_hu_5305d24b1aa4935b.jpeg 800w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan01_hu_2cfa714cba2ad68d.jpeg 1600w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;スケーリングは全身麻酔が必要だったりでほぼ半日かかるので、&lt;br&gt;
朝病院に預けて夕方お迎えに行く形。&lt;/p&gt;
&lt;p&gt;あとは先生に任せてしばしの別れ。&lt;/p&gt;
&lt;p&gt;&lt;img alt="がんばれ…" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan02_hu_abf0ece0ad762ff6.jpeg 800w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan02_hu_c082340bc7ef5e03.jpeg 1600w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;昼すぎには無事に終わった旨の電話をもらい、&lt;br&gt;
予定通り夕方再び病院へ。&lt;/p&gt;
&lt;p&gt;病院に着くと麻酔から目が覚めたそとちゃんがわんわん鳴いていた。&lt;/p&gt;
&lt;p&gt;今回も麻酔後にちょっと漏れたおしっこがお尻について機嫌が悪かった様子。&lt;/p&gt;
&lt;p&gt;&lt;img alt="がんばった えらい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan03_hu_6ca5c697daf83e73.jpeg 800w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan03_hu_3e9f5821de3edcb4.jpeg 1600w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan03.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;肝心のスケーリングだが、&lt;br&gt;
先生が術前術後の写真を撮っており、見せてもらうことができた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="before 茶色い歯石がついてる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan04_hu_8b48ab62ccbaf618.jpeg 800w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan04_hu_22e44f4219ad07fc.jpeg 1600w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="after 歯石が取れた" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan05_hu_3c7aa1bc412470df.jpeg 800w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan05_hu_10fb032864f90477.jpeg 1600w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan05.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;なんか光の当て方じゃね？と思ったけどちゃんと歯石は取れているらしい。&lt;/p&gt;
&lt;p&gt;あと気持ちの問題な気もするが口臭もちょっとマシになった気がする。&lt;/p&gt;
&lt;p&gt;麻酔のために前日の夜から約20時間近くごはんをあげてなかったので、&lt;br&gt;
帰宅後はごほうびごはんをドカ食い。&lt;/p&gt;
&lt;p&gt;&lt;img alt="えらかったからちゅーるトッピング" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan06_hu_6c7bf85680edc52d.jpeg 800w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan06_hu_4e80443c5cd3a28.jpeg 1600w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan06.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;がんばりました&amp;hellip;&lt;/p&gt;
&lt;h3 id="お水"&gt;お水
&lt;/h3&gt;&lt;p&gt;ねこの水飲み場は多いほうがいいらしい。&lt;/p&gt;
&lt;p&gt;知らなかったわけではないのだが、&lt;br&gt;
そもそも1箇所にしかなくてもそとちゃんはかなり水を飲んでくれるのであまり気にしていなかった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="水飲むのとくい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan07_hu_79ab4b8173a89494.jpeg 800w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan07_hu_8cab11348af983a.jpeg 1600w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan07.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;ある日なんとなく、&lt;br&gt;
本当になんとなく余っていた水飲み皿に水を入れて部屋に置いてみたのだが、&lt;br&gt;
そとちゃんがいきなり食いついた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="めっちゃ飲むじゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan08_hu_9939ed66aa34945d.jpeg 800w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan08_hu_3b83b0418c5e2d40.jpeg 1600w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan08.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;それはそれでいいんだけど、&lt;br&gt;
逆にこれまで使っていた&lt;a class="link" href="https://product.gex-fp.co.jp/ca/?m=ProductListDetail&amp;amp;cid=461&amp;amp;id=1395" target="_blank" rel="noopener"
 &gt;ピュアクリスタル&lt;/a&gt;の水を全然飲まなくなってしまった&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="これちがうの顔" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan09.jpeg" srcset="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan09_hu_2680aeeacc17c85.jpeg 800w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan09_hu_a07b9fdf52110be5.jpeg 1600w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan09.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;今までのはポンプと&lt;a class="link" href="https://product.gex-fp.co.jp/ca/?m=ProductListDetail&amp;amp;cid=462&amp;amp;id=2431" target="_blank" rel="noopener"
 &gt;猫用のフィルタ&lt;/a&gt;で濾過、&lt;br&gt;
しかも&lt;a class="link" href="https://product.gex-fp.co.jp/ca/?m=ProductListDetail&amp;amp;cid=465&amp;amp;id=2235" target="_blank" rel="noopener"
 &gt;ヒーター&lt;/a&gt;でねこ好みに温めてるめちゃんこお金のかかった水なのに、&lt;br&gt;
それよりも皿に汲んだだけの水道水を好むとは&amp;hellip;?🤔&lt;/p&gt;
&lt;p&gt;&lt;img alt="水飲むと褒められることを知っている" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan10.jpeg" srcset="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan10_hu_d612ab1bd5e9d2f2.jpeg 800w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan10_hu_8fdda9a80b4ab0c6.jpeg 1600w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan10.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;水はここ、と決めたら変えたくない的なこだわりがあるのかな？&lt;br&gt;
よくわからないがたくさん飲んでくれるならヨシ！😭💸&lt;/p&gt;
&lt;p&gt;&lt;img alt="置き場所入れ替えたり色々やったら元の水もちょっと飲むようになった" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan11.jpeg" srcset="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan11_hu_ef3f26ecb33b7e5d.jpeg 800w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan11_hu_6262a14b4f6d9b39.jpeg 1600w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan11.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="洗濯機"&gt;洗濯機
&lt;/h3&gt;&lt;p&gt;家で使ってた洗濯機がもう10年以上で耐用年数を超えていたので、&lt;br&gt;
いい機会だと思い&lt;a class="link" href="https://www.nitori-net.jp/ec/product/2113400001619/" target="_blank" rel="noopener"
 &gt;ニトリの激安ドラム式洗濯機&lt;/a&gt;を買ってみた。&lt;br&gt;
(めっちゃ異音がする初期不良を引いて色々あったのだがそれは割愛、安いけどちゃんとサポートしてくれたから不満なし)&lt;/p&gt;
&lt;p&gt;洗濯機といえば、うちには洗濯機大好きねこちゃんが一匹。&lt;/p&gt;
&lt;p&gt;&lt;img alt="興味津々" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan12.jpeg" srcset="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan12_hu_44408a565b55346e.jpeg 800w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan12_hu_111e43c31675e1bb.jpeg 1600w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan12.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;設置早々に洗濯機を調べるそとちゃん。&lt;/p&gt;
&lt;p&gt;&lt;img alt="入っちゃいそう(ほぼ入ってる)" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan13.jpeg" srcset="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan13_hu_cb78c00a284dd255.jpeg 800w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan13_hu_65ffa1de8d8ee2c6.jpeg 1600w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan13.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;今までは縦ドラムだったから頑張ってジャンプしないと入れなかったのだが、&lt;br&gt;
横ドラムになったので簡単に入れてしまう。&lt;br&gt;
(⚠️そもそもねこは洗濯機に入っちゃダメです)&lt;/p&gt;
&lt;p&gt;&lt;img alt="あーあ 悪いねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan14.jpeg" srcset="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan14_hu_9859a6f6b4a92c60.jpeg 800w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan14_hu_bb45a48b1e6433e3.jpeg 1600w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan14.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="怒られてるときにする顔じゃなくない？" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan15.jpeg" srcset="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan15_hu_d28aaeeaabf6e900.jpeg 800w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan15_hu_fb848dbc895af174.jpeg 1600w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan15.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;好きすぎて中に洗濯物があっても無理やり突破しようとする。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ダメだってば" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan16.jpeg" srcset="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan16_hu_6aec83b437c90e53.jpeg 800w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan16_hu_ec440875cd612cf7.jpeg 1600w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan16.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;ドラムの中だけでなく、 &lt;br&gt;
洗濯中も気を抜くとたまに上にのぼってしまう。&lt;/p&gt;
&lt;p&gt;&lt;img alt="洗濯機の上で溶けてる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan18.jpeg" srcset="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan18_hu_4d173e477049f828.jpeg 800w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan18_hu_79a2e327d919b77b.jpeg 1600w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan18.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;今回買った洗濯機は安いのでヒーター式乾燥なのだが、&lt;br&gt;
乾燥中は機械がかなり暖かくなるのでそれが気に入ってしまった様子。&lt;/p&gt;
&lt;p&gt;&lt;img alt="もちろん怒られるが聞く耳を持たない" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan17.jpeg" srcset="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan17_hu_2098e779448ca585.jpeg 800w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan17_hu_79fa4e23d54edff6.jpeg 1600w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan17.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;ドラムの回転でガンガン揺れててもお構いなし。&lt;br&gt;
洗濯機の上でねこがぷるぷる震えているのはちょっと面白いがやっぱり危険なのでダメです。&lt;/p&gt;
&lt;p&gt;&lt;img alt="※危ないので人間が見ていないときは近づけないようになった" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan19.jpeg" srcset="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan19_hu_15b8f8d4f71ae7fd.jpeg 800w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan19_hu_6585fb57ef2e4f60.jpeg 1600w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan19.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;2月はそとちゃんがちょっと大変だったけど、&lt;br&gt;
3月はほとんど元気に楽しく過ごせてよかった。&lt;/p&gt;
&lt;p&gt;お水の件も洗濯機の件もそうだけど、&lt;br&gt;
そとちゃんはなんでもすぐ好きになってくれるので一緒にいて楽しい。&lt;br&gt;
怖がるという賢さはあんまりないんだろうな&amp;hellip;😂&lt;/p&gt;
&lt;p&gt;あと歯磨きを頑張ってこの状態をキープしましょう😤&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="退屈タイムのねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan_hu_cd2dbcab4e81e9e3.jpeg 800w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan_hu_9a70127eb8555800.jpeg 1600w, https://blog.uzimihsr.com/post/2025-04-12-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>Azure SDK for PythonでCERTIFICATE_VERIFY_FAILEDを雑に回避する</title><link>https://blog.uzimihsr.com/post/2025-03-29-azure-sdk-for-python-ignore-cert-verify/</link><pubDate>Sat, 29 Mar 2025 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2025-03-29-azure-sdk-for-python-ignore-cert-verify/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2025-03-29-azure-sdk-for-python-ignore-cert-verify/sotochan.jpeg" alt="Featured image of post Azure SDK for PythonでCERTIFICATE_VERIFY_FAILEDを雑に回避する" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;Azure SDK for Pythonを使っていてサービスへの接続時に証明書検証エラー&lt;code&gt;SSL: CERTIFICATE_VERIFY_FAILED&lt;/code&gt;が出た時、&lt;br&gt;
雑に回避したかったら各クライアントのコンストラクタに&lt;code&gt;connection_verify=False&lt;/code&gt;を渡せば良い。&lt;br&gt;
(本番運用するような場合はちゃんとルート証明書を端末のRootCAに追加しよう！怒られても知らないぞ！)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# こんな感じ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;blob_service_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BlobServiceClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_connection_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;connect_str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;connection_verify&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="経緯"&gt;経緯
&lt;/h2&gt;&lt;p&gt;&lt;del&gt;会社のうんこPC&lt;/del&gt; ちょっと特殊な環境で開発しているときに&lt;a class="link" href="https://learn.microsoft.com/en-us/azure/developer/python/sdk/azure-sdk-overview" target="_blank" rel="noopener"
 &gt;Azure SDK for Python&lt;/a&gt;からAzureのサービスを呼び出したところ証明書エラーが出てしまった。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;azure.core.exceptions.ServiceRequestError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1028)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;このエラーは実行環境が信頼しているCA証明書でサーバー(Azure)側の証明書検証がしてしまうというもので、&lt;br&gt;
正攻法としては信頼するCA証明書のリストにAzureのルート証明書を追加すれば解決するのだが、&lt;br&gt;
&lt;del&gt;PCがうんこすぎてそこらへん全然自由にいじれない&lt;/del&gt;&lt;br&gt;
割と急いでたり動作検証で一回だけ通ればよかったりするときにわざわざ証明書をいじるのはけっこうめんどくさい。&lt;br&gt;
全然汚い方法でいいからサクッと解決したくなった(=証明書検証自体をスキップしたい)。&lt;/p&gt;
&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Python 3.13.2&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://pypi.org/project/azure-storage-blob/12.25.1/" target="_blank" rel="noopener"
 &gt;azure-storage-blob 12.25.1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://learn.microsoft.com/en-us/azure/storage/common/storage-account-create?tabs=azure-portal" target="_blank" rel="noopener"
 &gt;Azure Blob Storage&lt;/a&gt;は作成済みとする&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="手順"&gt;手順
&lt;/h2&gt;&lt;h3 id="キーワード引数を指定"&gt;キーワード引数を指定
&lt;/h3&gt;&lt;p&gt;とりあえず使うコードはこんな感じ。&lt;br&gt;
対象とするAzureサービスはなんでもいいが今回は&lt;a class="link" href="https://learn.microsoft.com/en-us/azure/storage/blobs/storage-quickstart-blobs-python?tabs=managed-identity%2Croles-azure-portal%2Csign-in-azure-cli&amp;amp;pivots=blob-storage-quickstart-scratch" target="_blank" rel="noopener"
 &gt;Blob Storageのクライアント&lt;/a&gt;を使う。&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/fbfb4b4e40cb5ec81b4847a7fc85346c.js"&gt;&lt;/script&gt;
&lt;script src="https://gist.github.com/uzimihsr/9cf9a8876376592c5d603b04533baf83.js"&gt;&lt;/script&gt;
&lt;p&gt;これを特定の環境で実行したとき、次のようなエラーが出るものとする。&lt;br&gt;
(&lt;a class="link" href="https://learn.microsoft.com/en-us/azure/storage/blobs/storage-quickstart-blobs-python?tabs=connection-string%2Croles-azure-portal%2Csign-in-azure-cli&amp;amp;pivots=blob-storage-quickstart-scratch#authenticate-to-azure-and-authorize-access-to-blob-data" target="_blank" rel="noopener"
 &gt;接続文字列&lt;/a&gt;はportalから取得できる)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 依存関係入れる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ pip install -r requirements.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 接続文字列を環境変数に設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;AZURE_STORAGE_CONNECTION_STRING&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;DefaultEndpointsProtocol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;AccountName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;...&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;AccountKey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;...&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;EndpointSuffix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;core.windows.net
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# スクリプト実行、証明書検証エラー発生&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ python main.py
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Traceback &lt;span class="o"&gt;(&lt;/span&gt;most recent call last&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &lt;span class="s2"&gt;&amp;#34;/test/main.py&amp;#34;&lt;/span&gt;, line 14, in &amp;lt;module&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; container in container_list:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ^^^^^^^^^^^^^^
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &lt;span class="s2"&gt;&amp;#34;/usr/local/lib/python3.13/site-packages/azure/core/paging.py&amp;#34;&lt;/span&gt;, line 123, in __next__
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; next&lt;span class="o"&gt;(&lt;/span&gt;self._page_iterator&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &lt;span class="s2"&gt;&amp;#34;/usr/local/lib/python3.13/site-packages/azure/core/paging.py&amp;#34;&lt;/span&gt;, line 75, in __next__
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; self._response &lt;span class="o"&gt;=&lt;/span&gt; self._get_next&lt;span class="o"&gt;(&lt;/span&gt;self.continuation_token&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &lt;span class="s2"&gt;&amp;#34;/usr/local/lib/python3.13/site-packages/azure/storage/blob/_models.py&amp;#34;&lt;/span&gt;, line 538, in _get_next_cb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; self._command&lt;span class="o"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ~~~~~~~~~~~~~^
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;marker&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;continuation_token or None,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;maxresults&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;self.results_per_page,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;cls&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;return_context_and_deserialized,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;use_location&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;self.location_mode&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &lt;span class="s2"&gt;&amp;#34;/usr/local/lib/python3.13/site-packages/azure/core/tracing/decorator.py&amp;#34;&lt;/span&gt;, line 105, in wrapper_use_tracer
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; func&lt;span class="o"&gt;(&lt;/span&gt;*args, **kwargs&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &lt;span class="s2"&gt;&amp;#34;/usr/local/lib/python3.13/site-packages/azure/storage/blob/_generated/operations/_service_operations.py&amp;#34;&lt;/span&gt;, line 685, in list_containers_segment
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; pipeline_response: &lt;span class="nv"&gt;PipelineResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; self._client._pipeline.run&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="c1"&gt;# pylint: disable=protected-access&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; _request, &lt;span class="nv"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;_stream, **kwargs
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ^
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &lt;span class="s2"&gt;&amp;#34;/usr/local/lib/python3.13/site-packages/azure/core/pipeline/_base.py&amp;#34;&lt;/span&gt;, line 240, in run
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; first_node.send&lt;span class="o"&gt;(&lt;/span&gt;pipeline_request&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &lt;span class="s2"&gt;&amp;#34;/usr/local/lib/python3.13/site-packages/azure/core/pipeline/_base.py&amp;#34;&lt;/span&gt;, line 96, in send
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; self.next.send&lt;span class="o"&gt;(&lt;/span&gt;request&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &lt;span class="s2"&gt;&amp;#34;/usr/local/lib/python3.13/site-packages/azure/core/pipeline/_base.py&amp;#34;&lt;/span&gt;, line 96, in send
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; self.next.send&lt;span class="o"&gt;(&lt;/span&gt;request&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &lt;span class="s2"&gt;&amp;#34;/usr/local/lib/python3.13/site-packages/azure/core/pipeline/_base.py&amp;#34;&lt;/span&gt;, line 96, in send
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; self.next.send&lt;span class="o"&gt;(&lt;/span&gt;request&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;Previous line repeated &lt;span class="m"&gt;2&lt;/span&gt; more times&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &lt;span class="s2"&gt;&amp;#34;/usr/local/lib/python3.13/site-packages/azure/core/pipeline/policies/_redirect.py&amp;#34;&lt;/span&gt;, line 204, in send
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; self.next.send&lt;span class="o"&gt;(&lt;/span&gt;request&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &lt;span class="s2"&gt;&amp;#34;/usr/local/lib/python3.13/site-packages/azure/core/pipeline/_base.py&amp;#34;&lt;/span&gt;, line 96, in send
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; self.next.send&lt;span class="o"&gt;(&lt;/span&gt;request&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &lt;span class="s2"&gt;&amp;#34;/usr/local/lib/python3.13/site-packages/azure/storage/blob/_shared/policies.py&amp;#34;&lt;/span&gt;, line 555, in send
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; raise err
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &lt;span class="s2"&gt;&amp;#34;/usr/local/lib/python3.13/site-packages/azure/storage/blob/_shared/policies.py&amp;#34;&lt;/span&gt;, line 527, in send
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; self.next.send&lt;span class="o"&gt;(&lt;/span&gt;request&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &lt;span class="s2"&gt;&amp;#34;/usr/local/lib/python3.13/site-packages/azure/core/pipeline/_base.py&amp;#34;&lt;/span&gt;, line 96, in send
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; self.next.send&lt;span class="o"&gt;(&lt;/span&gt;request&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &lt;span class="s2"&gt;&amp;#34;/usr/local/lib/python3.13/site-packages/azure/core/pipeline/_base.py&amp;#34;&lt;/span&gt;, line 96, in send
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; self.next.send&lt;span class="o"&gt;(&lt;/span&gt;request&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &lt;span class="s2"&gt;&amp;#34;/usr/local/lib/python3.13/site-packages/azure/core/pipeline/_base.py&amp;#34;&lt;/span&gt;, line 96, in send
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; self.next.send&lt;span class="o"&gt;(&lt;/span&gt;request&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;Previous line repeated &lt;span class="m"&gt;1&lt;/span&gt; more time&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &lt;span class="s2"&gt;&amp;#34;/usr/local/lib/python3.13/site-packages/azure/storage/blob/_shared/policies.py&amp;#34;&lt;/span&gt;, line 301, in send
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; self.next.send&lt;span class="o"&gt;(&lt;/span&gt;request&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &lt;span class="s2"&gt;&amp;#34;/usr/local/lib/python3.13/site-packages/azure/core/pipeline/_base.py&amp;#34;&lt;/span&gt;, line 96, in send
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; self.next.send&lt;span class="o"&gt;(&lt;/span&gt;request&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &lt;span class="s2"&gt;&amp;#34;/usr/local/lib/python3.13/site-packages/azure/core/pipeline/_base.py&amp;#34;&lt;/span&gt;, line 96, in send
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; self.next.send&lt;span class="o"&gt;(&lt;/span&gt;request&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &lt;span class="s2"&gt;&amp;#34;/usr/local/lib/python3.13/site-packages/azure/core/pipeline/_base.py&amp;#34;&lt;/span&gt;, line 128, in send
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; self._sender.send&lt;span class="o"&gt;(&lt;/span&gt;request.http_request, **request.context.options&lt;span class="o"&gt;)&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &lt;span class="s2"&gt;&amp;#34;/usr/local/lib/python3.13/site-packages/azure/core/pipeline/transport/_requests_basic.py&amp;#34;&lt;/span&gt;, line 409, in send
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; raise error
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;azure.core.exceptions.ServiceRequestError: &lt;span class="o"&gt;[&lt;/span&gt;SSL: CERTIFICATE_VERIFY_FAILED&lt;span class="o"&gt;]&lt;/span&gt; certificate verify failed: unable to get &lt;span class="nb"&gt;local&lt;/span&gt; issuer certificate &lt;span class="o"&gt;(&lt;/span&gt;_ssl.c:1028&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここで証明書検証をスキップするようにしたいが、&lt;br&gt;
&lt;a class="link" href="https://learn.microsoft.com/ja-jp/python/api/azure-storage-blob/azure.storage.blob.blobserviceclient?view=azure-python#azure-storage-blob-blobserviceclient-list-containers" target="_blank" rel="noopener"
 &gt;使ってるクライアント&lt;/a&gt;にそれっぽいオプションがなさそう&amp;hellip;詰んだ&amp;hellip;&lt;br&gt;
と思ったが、ちょっとエラーを調べるとこのクライアントが内部で呼び出してるクラスとそのパラメータみたいなのが出てきた。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/Azure/azure-sdk-for-python/blob/21ba181f927de0a6580ad75a068dd9c5045420e9/sdk/storage/azure-storage-blob/azure/storage/blob/_blob_service_client.py#L54" target="_blank" rel="noopener"
 &gt;https://github.com/Azure/azure-sdk-for-python/blob/21ba181f927de0a6580ad75a068dd9c5045420e9/sdk/storage/azure-storage-blob/azure/storage/blob/_blob_service_client.py#L54&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/Azure/azure-sdk-for-python/blob/21ba181f927de0a6580ad75a068dd9c5045420e9/sdk/core/azure-core/azure/core/pipeline/transport/_requests_basic.py#L259" target="_blank" rel="noopener"
 &gt;https://github.com/Azure/azure-sdk-for-python/blob/21ba181f927de0a6580ad75a068dd9c5045420e9/sdk/core/azure-core/azure/core/pipeline/transport/_requests_basic.py#L259&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://learn.microsoft.com/ja-jp/python/api/azure-core/azure.core.configuration.connectionconfiguration?view=azure-python" target="_blank" rel="noopener"
 &gt;https://learn.microsoft.com/ja-jp/python/api/azure-core/azure.core.configuration.connectionconfiguration?view=azure-python&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;(BlobServiceClientがHTTPリクエストを送るメソッドの内部でConnectionConfigurationを呼び出していて、このclassにはconnection_verifyといういかにも証明書検証の有無を司ってそうなパラメータがある)&lt;/p&gt;
&lt;p&gt;試しにキーワード引数(kwargs)をクライアントのコンストラクタに渡してみよう&amp;hellip;&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/fb38aaa360ea71b4a4c48fe1f1676163.js"&gt;&lt;/script&gt;
&lt;p&gt;コードを書き換えて再度実行したところ、&lt;br&gt;
「ちゃんと証明書検証したほうがいいぞ」的な警告は出るものの今度はエラーにならずちゃんと呼び出しが成功した(コンテナ名の一覧が表示できた)。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ python main.py
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/usr/local/lib/python3.13/site-packages/urllib3/connectionpool.py:1097: InsecureRequestWarning: Unverified HTTPS request is being made to host &lt;span class="s1"&gt;&amp;#39;stuzimihsrexample.blob.core.windows.net&amp;#39;&lt;/span&gt;. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#tls-warnings
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; warnings.warn&lt;span class="o"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;example-container-1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;example-container-2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;azure.core.configuration.ConnectionConfigurationは他のAzureサービスのクライアントでも通信時に使われているようなので、&lt;br&gt;
同様に各クライアントのコンストラクタ引数に&lt;code&gt;connection_verify=False&lt;/code&gt;を渡せば証明書検証を回避できるはず。&lt;/p&gt;
&lt;p&gt;やったぜ。&lt;/p&gt;
&lt;h3 id="証明書エラーの再現手順"&gt;(証明書エラーの再現手順)
&lt;/h3&gt;&lt;p&gt;普通の環境で実行しても証明書エラーに遭うことはなかなかないので、&lt;br&gt;
今回は問題を再現するため以下の手順で信頼するCA証明書が欠けているような状態を作った。&lt;/p&gt;
&lt;p&gt;雑にDockerでPythonコンテナを立ち上げ、RootCAのリストを取得する。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="c1"&gt;# 作業ディレクトリ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;pwd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/path/to/tempdir
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls -1 &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;main.py
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;requirements.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="c1"&gt;# testディレクトリをマウントしてPythonコンテナを立て、そのままbashで入る&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run --rm -it -v /path/to/tempdir/test:/test python:3 /bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;root@f8a544bd9c26:/#
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;root@f8a544bd9c26:/# &lt;span class="c1"&gt;# 依存関係入れる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;root@f8a544bd9c26:/# &lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;root@f8a544bd9c26:/test# pip install -r requirements.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;root@f8a544bd9c26:/test# &lt;span class="c1"&gt;# RootCAの場所を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;root@f8a544bd9c26:/test# python
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Python 3.13.2 &lt;span class="o"&gt;(&lt;/span&gt;main, Mar &lt;span class="m"&gt;18&lt;/span&gt; 2025, 22:43:33&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;GCC 12.2.0&lt;span class="o"&gt;]&lt;/span&gt; on linux
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Type &lt;span class="s2"&gt;&amp;#34;help&amp;#34;&lt;/span&gt;, &lt;span class="s2"&gt;&amp;#34;copyright&amp;#34;&lt;/span&gt;, &lt;span class="s2"&gt;&amp;#34;credits&amp;#34;&lt;/span&gt; or &lt;span class="s2"&gt;&amp;#34;license&amp;#34;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; more information.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt;&amp;gt;&amp;gt; import certifi
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt;&amp;gt;&amp;gt; certifi.where&lt;span class="o"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;&amp;#39;/usr/local/lib/python3.13/site-packages/certifi/cacert.pem&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;root@f8a544bd9c26:/test# &lt;span class="c1"&gt;# RootCAをコピーしてホストOS側で編集する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;root@f8a544bd9c26:/test# cp /usr/local/lib/python3.13/site-packages/certifi/cacert.pem ./cacert.pem
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;拾ってきたRootCAをホストOS側から任意のエディタで開き、&lt;br&gt;
&lt;code&gt;# Issuer: CN=DigiCert Global Root G2&lt;/code&gt;の部分のpem(画像では1740~1768行目)をごっそり削除する。&lt;/p&gt;
&lt;p&gt;&lt;img alt="DigiCert Global Root G2を削除" class="gallery-image" data-flex-basis="308px" data-flex-grow="128" height="902" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-03-29-azure-sdk-for-python-ignore-cert-verify/sc02.png" srcset="https://blog.uzimihsr.com/post/2025-03-29-azure-sdk-for-python-ignore-cert-verify/sc02_hu_e47646a8ac69d9ba.png 800w, https://blog.uzimihsr.com/post/2025-03-29-azure-sdk-for-python-ignore-cert-verify/sc02.png 1161w" width="1161"&gt;&lt;/p&gt;
&lt;p&gt;(Blob StorageのRootCAが&lt;code&gt;DigiCert Global Root G2&lt;/code&gt;であることはブラウザで確認した。)&lt;/p&gt;
&lt;p&gt;&lt;img alt="Blob Storageの証明書のRootCAはDigiCert Global Root G2" class="gallery-image" data-flex-basis="396px" data-flex-grow="165" height="725" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-03-29-azure-sdk-for-python-ignore-cert-verify/sc01.png" srcset="https://blog.uzimihsr.com/post/2025-03-29-azure-sdk-for-python-ignore-cert-verify/sc01_hu_6263a190663cc5f1.png 800w, https://blog.uzimihsr.com/post/2025-03-29-azure-sdk-for-python-ignore-cert-verify/sc01.png 1197w" width="1197"&gt;&lt;/p&gt;
&lt;p&gt;これで信頼されたRootCAのリストからBlob StorageのRootCAが消えたので、&lt;br&gt;
これをPythonが参照するように上書きする。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;root@f8a544bd9c26:/test# &lt;span class="c1"&gt;# 編集後のcacert.pemで上書き&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;root@f8a544bd9c26:/test# cp ./cacert.pem /usr/local/lib/python3.13/site-packages/certifi/cacert.pem
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;あとはAzure portalから&lt;a class="link" href="https://learn.microsoft.com/en-us/azure/storage/blobs/storage-quickstart-blobs-python?tabs=connection-string%2Croles-azure-portal%2Csign-in-azure-cli&amp;amp;pivots=blob-storage-quickstart-scratch#authenticate-to-azure-and-authorize-access-to-blob-data" target="_blank" rel="noopener"
 &gt;接続文字列&lt;/a&gt;をコピーしてきて環境変数に張り付けて、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;root@f8a544bd9c26:/test# &lt;span class="c1"&gt;# 接続文字列を環境変数に設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;root@f8a544bd9c26:/test# &lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;AZURE_STORAGE_CONNECTION_STRING&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;DefaultEndpointsProtocol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;AccountName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;...&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;AccountKey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;...&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;EndpointSuffix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;core.windows.net
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;コードを実行したらちゃんとエラーになった。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;root@f8a544bd9c26:/test# python main.py
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Traceback &lt;span class="o"&gt;(&lt;/span&gt;most recent call last&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &lt;span class="s2"&gt;&amp;#34;/test/main.py&amp;#34;&lt;/span&gt;, line 14, in &amp;lt;module&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; container in container_list:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ^^^^^^^^^^^^^^
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;#...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;azure.core.exceptions.ServiceRequestError: &lt;span class="o"&gt;[&lt;/span&gt;SSL: CERTIFICATE_VERIFY_FAILED&lt;span class="o"&gt;]&lt;/span&gt; certificate verify failed: unable to get &lt;span class="nb"&gt;local&lt;/span&gt; issuer certificate &lt;span class="o"&gt;(&lt;/span&gt;_ssl.c:1028&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;&lt;del&gt;うんこPCで開発すんのマジしんどい、営業マンと同じ構成のポンコツ制限PCをエンジニアに使わせるんじゃないよ&lt;/del&gt; 　&lt;/p&gt;
&lt;p&gt;超久しぶりにPython触ったら色々わかんなすぎて泣いてしまった。&lt;br&gt;
やっぱりGoがいいなあ&amp;hellip;&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="自由を与えすぎると危険になる例" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-03-29-azure-sdk-for-python-ignore-cert-verify/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2025-03-29-azure-sdk-for-python-ignore-cert-verify/sotochan_hu_cad35e8e7b61d477.jpeg 800w, https://blog.uzimihsr.com/post/2025-03-29-azure-sdk-for-python-ignore-cert-verify/sotochan_hu_94e13c6d03ad48b0.jpeg 1600w, https://blog.uzimihsr.com/post/2025-03-29-azure-sdk-for-python-ignore-cert-verify/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>2月のそとちゃん</title><link>https://blog.uzimihsr.com/post/2025-03-16-sotochan/</link><pubDate>Sun, 16 Mar 2025 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2025-03-16-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan.jpeg" alt="Featured image of post 2月のそとちゃん" /&gt;&lt;h2 id="そとちゃん"&gt;そとちゃん
&lt;/h2&gt;&lt;h3 id="歯が抜けた"&gt;歯が抜けた
&lt;/h3&gt;&lt;p&gt;ある日の夜。&lt;/p&gt;
&lt;p&gt;寝る前に日課の&lt;a class="link" href="https://www.lion-pet.co.jp/product/petkiss/kinou_sheet_apple.htm" target="_blank" rel="noopener"
 &gt;歯みがきシート&lt;/a&gt;をしていたら、&lt;br&gt;
そとちゃんが嫌がって動いたときに歯が引っかかってそのままポロッと抜けてしまった。😱&lt;/p&gt;
&lt;p&gt;&lt;img alt="右上の奥歯" class="gallery-image" data-flex-basis="336px" data-flex-grow="140" height="1416" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan01_hu_b5ae6df74652e06a.jpeg 800w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan01_hu_c87c424497f76d9f.jpeg 1600w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;血が出たものの、ねこ自身は全く気にしてない様子。&lt;/p&gt;
&lt;p&gt;念の為病院に電話したところ、&lt;br&gt;
血が止まって本人(ねこ)が痛がるそぶりもなければ急診の必要はないとのことだった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="怒りのちゅーるドカ食い 爪がささってるね" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan02_hu_63f0dea769bf2629.jpeg 800w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan02_hu_86569220d6132e7a.jpeg 1600w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;抜けたのは右上の奥歯。&lt;/p&gt;
&lt;p&gt;&lt;img alt="赤い丸の部分が抜けた さらに奥の歯は2年前に抜歯済み" class="gallery-image" data-flex-basis="297px" data-flex-grow="124" height="1599" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan03_hu_57ebca2c533eb86f.jpeg 800w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan03_hu_378ef85653018248.jpeg 1600w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan03.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;元々右側の歯は歯肉炎がひどくて、&lt;br&gt;
&lt;a class="link" href="https://blog.uzimihsr.com/post/2023-05-05-sotochan/" target="_blank" rel="noopener"
 &gt;2年前にスケーリング(歯石除去)したとき&lt;/a&gt;に一番奥の歯を抜歯していたのだが、&lt;br&gt;
今回は手前の歯が抜けてしまった&amp;hellip;&lt;/p&gt;
&lt;p&gt;翌朝さっそく病院へ。&lt;/p&gt;
&lt;p&gt;&lt;img alt="キャリーはやっぱり好き" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan04_hu_1bad944800313fbb.jpeg 800w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan04_hu_22ddc6d8bf9bd6e1.jpeg 1600w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;診察の結果、&lt;br&gt;
とくに異常はなし。&lt;/p&gt;
&lt;p&gt;気になるなら抗生剤を出してもよいが、&lt;br&gt;
血が止まっているなら必須ではないとのことなので一旦なしにしてもらった。&lt;/p&gt;
&lt;p&gt;あとは残った右下の歯も歯肉炎がひどかったので、&lt;br&gt;
後日再びスケーリングをすることに。&lt;/p&gt;
&lt;p&gt;歯磨きは毎晩やっていたが、&lt;br&gt;
左側に比べて右側は痛がるのであまりうまくできていなかった。&lt;/p&gt;
&lt;p&gt;反省&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="つかれた" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan05_hu_952b0b252e907aab.jpeg 800w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan05_hu_190c7dc4a296b47.jpeg 1600w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan05.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="猫ドック"&gt;猫ドック
&lt;/h3&gt;&lt;p&gt;スケーリングは全身麻酔が伴うため、&lt;br&gt;
安全のために血液検査が必要。&lt;/p&gt;
&lt;p&gt;どうせ血液検査をやるならということで、&lt;br&gt;
そとちゃんは初めての猫ドックを受けることになった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="やる気まんまん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan06_hu_76aaa8d81443cb61.jpeg 800w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan06_hu_6730c43a4bd6231e.jpeg 1600w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan06.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;朝に病院に預けて、
夕方までみっちり検査。&lt;/p&gt;
&lt;p&gt;病院大好きそとちゃんも流石に疲れたのか、&lt;br&gt;
家に帰ってきたころにはすっかりしょんぼりしていた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="しょぼしょぼ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan07_hu_278288808ce39455.jpeg 800w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan07_hu_b042a760ecf55450.jpeg 1600w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan07.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;加えて前日夜からご飯を抜いていたので、&lt;br&gt;
めちゃめちゃお腹が空いていた様子。&lt;/p&gt;
&lt;p&gt;一応検査後に病院でもおやつをもらったはずだが、&lt;br&gt;
帰宅後すぐにごはんをドカ食い。&lt;/p&gt;
&lt;p&gt;&lt;img alt="もぐもぐタイム" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan08_hu_d6d637e5cf86a5f4.jpeg 800w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan08_hu_7cb6e77689fd7287.jpeg 1600w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan08.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;がんばりました&amp;hellip;&lt;/p&gt;
&lt;p&gt;気になる結果は&amp;hellip;？&lt;/p&gt;
&lt;p&gt;&lt;img alt="写真つきの報告書をもらいました 機嫌悪い顔で笑っちゃった" class="gallery-image" data-flex-basis="180px" data-flex-grow="75" height="1984" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan09.jpeg" srcset="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan09_hu_c5516782be061ad5.jpeg 800w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan09.jpeg 1488w" width="1488"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;身体検査&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="口腔が真っ赤" class="gallery-image" data-flex-basis="180px" data-flex-grow="75" height="1984" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan10.jpeg" srcset="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan10_hu_9bd88c022cf80a07.jpeg 800w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan10.jpeg 1488w" width="1488"&gt;&lt;/p&gt;
&lt;p&gt;体重は3.9kgでちょっと痩せ気味。&lt;br&gt;
体格的に4.0kgは欲しいが&lt;a class="link" href="https://blog.uzimihsr.com/post/2024-10-30-sotochan" target="_blank" rel="noopener"
 &gt;ごはんを好き嫌いしていた&lt;/a&gt;のもあって減ってしまった。&lt;/p&gt;
&lt;p&gt;体温は平熱(38.2℃)で問題なし。&lt;/p&gt;
&lt;p&gt;右眼は相変わらず目ヤニが多め。&lt;br&gt;
タンパク質多めの食事にすると改善するかも？&lt;br&gt;
目薬を処方することもできるが、&lt;br&gt;
ほぼ生まれつきのようなもの(猫風邪の後遺症)なのでこまめに拭くのが一番らしい。&lt;/p&gt;
&lt;p&gt;口は主に右側の歯肉炎が引っかかった。&lt;br&gt;
歯列異常の診断は歯が抜けてしまっているからとのこと。&lt;/p&gt;
&lt;p&gt;皮膚はフケが目立ち、&lt;br&gt;
左耳の付け根に脱毛があった様子。&lt;br&gt;
フケは一時的なストレス、&lt;br&gt;
脱毛は脚で掻く癖があるのでそれ由来っぽい。&lt;br&gt;
掻きすぎて出血などがあれば治療しなきゃだけど、
今の所問題なし。&lt;br&gt;
夏になったら久しぶりにお風呂入ろうか&amp;hellip;&lt;/p&gt;
&lt;p&gt;触診は背中を押した時に嫌がるそぶりを見せたので気をつけたほうがいいらしい。&lt;br&gt;
とはいえレントゲン(後述)では異常はなかった。&lt;/p&gt;
&lt;p&gt;その他は異常なし。&lt;/p&gt;
&lt;p&gt;いろいろ引っかかってしまったが、&lt;br&gt;
緊急で対応が必要というよりは「今後も注意して見てね」くらいのものだったので一安心。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;便検査 尿検査&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="おしっこが薄い" class="gallery-image" data-flex-basis="180px" data-flex-grow="75" height="1984" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan11.jpeg" srcset="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan11_hu_657b8e9715012e40.jpeg 800w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan11.jpeg 1488w" width="1488"&gt;&lt;/p&gt;
&lt;p&gt;うんちは異常なし。&lt;br&gt;
形も成分もいい感じ。&lt;/p&gt;
&lt;p&gt;おしっこは尿比重が低いのが問題とのこと。&lt;br&gt;
薄すぎるので腎機能が低下している可能性がある。&lt;/p&gt;
&lt;p&gt;そとちゃんは元々水を良く飲むのでそれが関係しているかもしれないが、&lt;br&gt;
腎機能が落ちた猫は水をたくさん飲む傾向にあるのでやはり注意が必要。&lt;/p&gt;
&lt;p&gt;1回のおしっこの量が異常に増えたりしたら再検査も視野に入れたほうが良いらしい。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;レントゲン検査&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="咳に注意" class="gallery-image" data-flex-basis="180px" data-flex-grow="75" height="1984" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan12.jpeg" srcset="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan12_hu_d3e20f790d8e2b16.jpeg 800w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan12.jpeg 1488w" width="1488"&gt;
&lt;img alt="消化器系はとても綺麗" class="gallery-image" data-flex-basis="180px" data-flex-grow="75" height="1984" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan13.jpeg" srcset="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan13_hu_bc1fc80ec3ec559b.jpeg 800w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan13.jpeg 1488w" width="1488"&gt;&lt;/p&gt;
&lt;p&gt;おおむね問題なしだが、&lt;br&gt;
気管支パターンが見つかったので咳が増えたら注意が必要とのこと。&lt;br&gt;
よく水を飲んだ後にくしゃみか咳のような動きをよくやるので気をつけてあげたい。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;エコー検査&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="膵臓…" class="gallery-image" data-flex-basis="180px" data-flex-grow="75" height="1984" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan14.jpeg" srcset="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan14_hu_9c1f7b3cc59c061c.jpeg 800w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan14.jpeg 1488w" width="1488"&gt;&lt;/p&gt;
&lt;p&gt;こちらもおおむね問題なし。&lt;/p&gt;
&lt;p&gt;膵臓がわずかに肥大していたとのことだが、&lt;br&gt;
異常があれば食欲低下や嘔吐の症状が出るはずなので元々ちょっと大きいだけかもしれない。&lt;br&gt;
(そとちゃんは好き嫌いするだけで食欲が落ちたことはほぼない)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;血液検査&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="クレアチニンが基準値超え" class="gallery-image" data-flex-basis="180px" data-flex-grow="75" height="1984" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan15.jpeg" srcset="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan15_hu_7b51ca7790a07405.jpeg 800w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan15.jpeg 1488w" width="1488"&gt;
&lt;img alt="SDMAが低いのは良いこと" class="gallery-image" data-flex-basis="180px" data-flex-grow="75" height="1984" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan16.jpeg" srcset="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan16_hu_e645c89d20125553.jpeg 800w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan16.jpeg 1488w" width="1488"&gt;&lt;/p&gt;
&lt;p&gt;大きな異常はなし。&lt;/p&gt;
&lt;p&gt;腎機能の値であるクレアチニンがわずかに基準値を上回っているが、&lt;br&gt;
元々ブレが大きい値であること、&lt;br&gt;
腎臓に本当に異常があるときすぐ上がる値(&lt;a class="link" href="https://www.idexx.co.jp/ja/veterinary/reference-laboratories/sdma/why-sdma-matters/" target="_blank" rel="noopener"
 &gt;SDMA&lt;/a&gt;)が低いのでそこまで深刻な状態ではないらしい。&lt;/p&gt;
&lt;p&gt;MCHCと血小板数も少なかったが、&lt;br&gt;
こちらも基準値をギリギリ下回る程度なので大丈夫。&lt;/p&gt;
&lt;p&gt;こんな感じで大きな異常はなし、&lt;br&gt;
全身麻酔も打てるでしょうとのことで3月にスケーリングを行うことになった。&lt;/p&gt;
&lt;h3 id="おしっこ"&gt;おしっこ
&lt;/h3&gt;&lt;p&gt;そとちゃんの病院通いはこれで終わらず&amp;hellip;😭&lt;/p&gt;
&lt;p&gt;猫ドックから帰ってから数日後、&lt;br&gt;
こんどはそとちゃんがほぼ初めての粗相をしてしまった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="カーペットでおしっこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan17.jpeg" srcset="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan17_hu_e8fc4218c3b5e0c.jpeg 800w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan17_hu_1db0ecf3ea63650a.jpeg 1600w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan17.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;これまでにそとちゃんが粗相をしたのはたったの一回、&lt;br&gt;
それもうちにお迎えした初日でトイレの場所がわからなかったときだけだったので、&lt;br&gt;
とても心配になった。&lt;/p&gt;
&lt;p&gt;様子を見ていると何度もトイレに行ってはいるのだが、&lt;br&gt;
なかなかうまくおしっこが出ない様子。&lt;br&gt;
(うんちは問題なくできていた)&lt;/p&gt;
&lt;p&gt;&lt;img alt="トイレには行ける" class="gallery-image" data-flex-basis="371px" data-flex-grow="154" height="753" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan18.PNG" srcset="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan18_hu_b956e634832da82.PNG 800w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan18.PNG 1165w" width="1165"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="おしっこが全然出てない" class="gallery-image" data-flex-basis="395px" data-flex-grow="164" height="914" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan19.PNG" srcset="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan19_hu_d2ec97ea0653189d.PNG 800w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan19.PNG 1506w" width="1506"&gt;&lt;/p&gt;
&lt;p&gt;トイレだとうまくおしっこできないから、&lt;br&gt;
他におしりの居心地がいい場所を探してそこでおしっこを試みる、&lt;br&gt;
といった動きをしているように見えた。&lt;/p&gt;
&lt;p&gt;移動した先でもなかなかおしっこが上手に出せず、&lt;br&gt;
血尿と思われるものがポタポタ出ている状態。&lt;/p&gt;
&lt;p&gt;&lt;img alt="血尿らしき赤いものが" class="gallery-image" data-flex-basis="418px" data-flex-grow="174" height="956" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan20.PNG" srcset="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan20_hu_c46ecbe60799a3d0.PNG 800w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan20_hu_1816dbd327258fb5.PNG 1600w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan20.PNG 1668w" width="1668"&gt;&lt;/p&gt;
&lt;p&gt;辛そうなのですぐに病院へ。&lt;/p&gt;
&lt;p&gt;&lt;img alt="かわいそう" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan21.jpeg" srcset="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan21_hu_b63f0cfdacc75c6a.jpeg 800w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan21_hu_8c4d7cd0f92937f1.jpeg 1600w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan21.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;やはりおしっこがうまく出せず溜まっていたようで、&lt;br&gt;
すぐにカテーテルで全て排出してもらった。&lt;/p&gt;
&lt;p&gt;腎臓に問題があると排尿を我慢することもあるらしいが、&lt;br&gt;
直近の検査で問題ないことと、&lt;br&gt;
上記の症状や排出した尿から細菌の値が少し出たので&lt;strong&gt;細菌性膀胱炎&lt;/strong&gt;との診断。&lt;/p&gt;
&lt;p&gt;原因としてはトイレでうんちや汚れた砂が尿道に触れたのかも？とのこと。&lt;/p&gt;
&lt;p&gt;素人的には猫ドックで採尿(膀胱穿刺)してもらったときに膀胱に傷がついたのでは？とも思ったが、&lt;br&gt;
実際は針ではなくカテーテルで採尿していたので考えづらいということだった。&lt;/p&gt;
&lt;p&gt;治療のため、&lt;br&gt;
1週間ほど抗生物質の&lt;a class="link" href="https://www.vmdp.jp/products/amoxiclear/amoxiclear.html" target="_blank" rel="noopener"
 &gt;アモキクリア&lt;/a&gt;を飲むことになった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="錠剤なので砕いてちゅーるに混ぜて飲ませる" class="gallery-image" data-flex-basis="290px" data-flex-grow="120" height="2268" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan22.jpeg" srcset="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan22_hu_500995f73aac6f39.jpeg 800w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan22_hu_e5362dedea80d039.jpeg 1600w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan22_hu_bc313d529c2e994c.jpeg 2400w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan22.jpeg 2741w" width="2741"&gt;&lt;/p&gt;
&lt;p&gt;帰宅後は何事もなかったかのようにケロッと復活。&lt;/p&gt;
&lt;p&gt;溜まってたおしっこがなくなってスッキリしたのかな？&lt;/p&gt;
&lt;p&gt;&lt;img alt="いいからさっさとちゅーるをよこせの顔" class="gallery-image" data-flex-basis="321px" data-flex-grow="133" height="1483" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan23.jpeg" srcset="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan23_hu_9d37f6ff2784e28a.jpeg 800w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan23_hu_ec873d440d601379.jpeg 1600w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan23.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;そして翌朝。&lt;/p&gt;
&lt;p&gt;なんとまだ2回しか薬を飲んでないのに普通にトイレでおしっこできるようになった。&lt;/p&gt;
&lt;p&gt;薬が効くにしてはちょっと早いと思うけどまあいいのかな？&lt;/p&gt;
&lt;p&gt;&lt;img alt="プラシーボ効果？(日本語はわからないはずだが…)" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan24.jpeg" srcset="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan24_hu_2305b30d3f63c1c.jpeg 800w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan24_hu_f9c29fb03da3e0f6.jpeg 1600w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan24.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;薬もしっかり飲みきり、&lt;br&gt;
以降は血尿も粗相もなくなった。&lt;/p&gt;
&lt;p&gt;トイレはこまめに砂を入れ替えてるけど、再発しないといいな&amp;hellip;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;2月はなんと3回も(1回は検査だけど)病院のお世話になってしまった。&lt;/p&gt;
&lt;p&gt;お財布に大ダメージなのはもちろんだが、&lt;br&gt;
やはりシニアねこ(次の5月で推定9さい)なので心配が大きい。&lt;/p&gt;
&lt;p&gt;歯が抜けたのも、毎日の歯磨きをもっと頑張っていれば防げたと思うと悔しい。&lt;/p&gt;
&lt;p&gt;これで右上の歯は犬歯以外の臼歯が全部抜けてしまった。&lt;br&gt;
綺麗な左側の歯は全部守っていきたいな&amp;hellip;&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="災難だったねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan_hu_c8616c39c85ef102.jpeg 800w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan_hu_95d939578dd0b928.jpeg 1600w, https://blog.uzimihsr.com/post/2025-03-16-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>1月のそとちゃん</title><link>https://blog.uzimihsr.com/post/2025-02-28-sotochan/</link><pubDate>Fri, 28 Feb 2025 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2025-02-28-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan.jpeg" alt="Featured image of post 1月のそとちゃん" /&gt;&lt;h2 id="そとちゃん"&gt;そとちゃん
&lt;/h2&gt;&lt;h3 id="ホットカーペット"&gt;ホットカーペット
&lt;/h3&gt;&lt;p&gt;新年早々そとちゃんにうれしいお年玉。&lt;/p&gt;
&lt;p&gt;我が家にホットカーペットが導入された。🎉&lt;/p&gt;
&lt;p&gt;&lt;img alt="うれしいね" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan01_hu_1646ff11e8542d09.jpeg 800w, https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan01_hu_f020349276abe8e8.jpeg 1600w, https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;友人から譲り受けたもので(物々交換なのに対価をまだ渡せておらず申し訳ない)、&lt;br&gt;
うちの部屋にぴったりサイズ。&lt;/p&gt;
&lt;p&gt;すぐにそとちゃんのお気に入りになった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="新しいものを警戒するとかそういうのはないです" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan02_hu_de65f9ff71c19406.jpeg 800w, https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan02_hu_6d727fcb105b69cc.jpeg 1600w, https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;電源を入れるとすぐ乗ってきて溶けちゃう。&lt;/p&gt;
&lt;p&gt;かわいいね。&lt;/p&gt;
&lt;p&gt;&lt;img alt="日光とのコンボが最高" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan03_hu_47ef3e9a5e9fbf16.jpeg 800w, https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan03_hu_b71b146caeebddbe.jpeg 1600w, https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan03.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;たまに電源を落とすと明らかに機嫌が悪くなる。&lt;/p&gt;
&lt;p&gt;&lt;img alt="はやくあったかくしての顔" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan04_hu_73ee22a9fc0af9f0.jpeg 800w, https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan04_hu_112a31fa066da140.jpeg 1600w, https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;上手につかってくれるといいな&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="真剣な眼差しで溶けている" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan05_hu_7b4a0d20ec9c1688.jpeg 800w, https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan05_hu_aa1d8829480f6097.jpeg 1600w, https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan05.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="気に入ってくれてよかった" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan06_hu_3f26ad303165e4b8.jpeg 800w, https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan06_hu_7e019697c9af8447.jpeg 1600w, https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan06.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="もちもちクッション"&gt;もちもちクッション
&lt;/h3&gt;&lt;p&gt;良い子にしているそとちゃんに俺からもお年玉を&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="とくいげ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan07_hu_7c82182d0ce185b4.jpeg 800w, https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan07_hu_74d4f5b50a459005.jpeg 1600w, https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan07.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;ニトリで&lt;a class="link" href="https://www.nitori-net.jp/ec/product/7806981s/" target="_blank" rel="noopener"
 &gt;もちもちクッション&lt;/a&gt;を購入。　　&lt;/p&gt;
&lt;p&gt;直径60cmで、そとちゃんにちょうど良いサイズ。&lt;/p&gt;
&lt;p&gt;&lt;img alt="上手に乗るね" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan08_hu_fcd5fc0cfa8d5c9f.jpeg 800w, https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan08_hu_43de83b533f627f3.jpeg 1600w, https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan08.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;こちらも早速気に入ってくれて、&lt;br&gt;
気づけば上で丸くなっている。&lt;/p&gt;
&lt;p&gt;&lt;img alt="まるい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan09.jpeg" srcset="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan09_hu_fb0d2e6a88028de2.jpeg 800w, https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan09_hu_dffb6add741a504.jpeg 1600w, https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan09.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="横から見てもまるい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan10.jpeg" srcset="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan10_hu_a52a925d31df5c98.jpeg 800w, https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan10_hu_7534ff16a49cfdf1.jpeg 1600w, https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan10.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;丸くないときもある。&lt;/p&gt;
&lt;p&gt;&lt;img alt="こちらも日光とのコンボが強い" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan11.jpeg" srcset="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan11_hu_7a50bb872333aa18.jpeg 800w, https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan11_hu_14138894de046a65.jpeg 1600w, https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan11.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="クッションの上で伸びたりくねくねする" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan12.jpeg" srcset="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan12_hu_3c4561db3d3bfc3c.jpeg 800w, https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan12_hu_4b7060ec28ab8067.jpeg 1600w, https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan12.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="サービスショット" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan13.jpeg" srcset="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan13_hu_576ac8e0e9dd6584.jpeg 800w, https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan13_hu_f47ec0b9e95e0120.jpeg 1600w, https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan13.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="サービスショット2" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan14.jpeg" srcset="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan14_hu_77da9fd94bb1bb77.jpeg 800w, https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan14_hu_fd1566adba4ba66b.jpeg 1600w, https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan14.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;他のねこちゃんはこういったクッションでふみふみする子が多いみたいだけど、&lt;br&gt;
そとちゃんはやっぱりふみふみしなかった😂&lt;br&gt;
(自分がお母さん猫だから子猫しぐさはあまりしないのかな&amp;hellip;?)&lt;/p&gt;
&lt;p&gt;&lt;img alt="こねるかと思ったけど座り直しただけだった" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan15.jpeg" srcset="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan15_hu_d35a0298d251f89a.jpeg 800w, https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan15_hu_bee0790643f3ddd7.jpeg 1600w, https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan15.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;ホットカーペットと合わせて楽しくすごしてくれたらうれしい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="幸せそうでなにより" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan16.jpeg" srcset="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan16_hu_396bf94f2f926320.jpeg 800w, https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan16_hu_842dc06d31b31de2.jpeg 1600w, https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan16.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;1月はそとちゃんに嬉しいプレゼントが多くてよかった。&lt;/p&gt;
&lt;p&gt;なんでも喜んでくれるからあげた方もうれしい。&lt;/p&gt;
&lt;p&gt;これで冬を乗り切りたいな&amp;hellip;&lt;br&gt;
(2月現在、ホットカーペットで電気代が爆発中💸)&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="もちもち" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan_hu_8b77674e9e9f7a5e.jpeg 800w, https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan_hu_4fd42928c64cf885.jpeg 1600w, https://blog.uzimihsr.com/post/2025-02-28-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>12月のそとちゃん(2024)</title><link>https://blog.uzimihsr.com/post/2025-01-12-sotochan/</link><pubDate>Sun, 12 Jan 2025 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2025-01-12-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan.jpeg" alt="Featured image of post 12月のそとちゃん(2024)" /&gt;&lt;h2 id="そとちゃん"&gt;そとちゃん
&lt;/h2&gt;&lt;h3 id="来客"&gt;来客
&lt;/h3&gt;&lt;p&gt;12月はちょこちょこ来客があり、&lt;br&gt;
人間大好きなそとちゃんは大喜びだった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ひざに乗せてもらえてご満悦" class="gallery-image" data-flex-basis="441px" data-flex-grow="184" height="1078" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan01_hu_75088784705f5616.jpeg 800w, https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan01_hu_49a0210803b91562.jpeg 1600w, https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;そとちゃんはマジでお客さんが大好きなので、&lt;br&gt;
自分からひざに乗りたがる。&lt;/p&gt;
&lt;p&gt;&lt;img alt="お客さんの匂いを嗅ぐのがすき" class="gallery-image" data-flex-basis="227px" data-flex-grow="94" height="2089" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan03_hu_c5c520d460ab1ae2.jpeg 800w, https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan03_hu_605e4e164f0364d3.jpeg 1600w, https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan03.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="うちに来たお客さんは必ず一度ソファに座ってねこを載せないといけない" class="gallery-image" data-flex-basis="444px" data-flex-grow="185" height="1072" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan06_hu_f9872fe564073460.jpeg 800w, https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan06_hu_6a1da4d376a4a527.jpeg 1600w, https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan06.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;普段から全然面識のない配送員さんや業者さんにも絡んでしまうし、&lt;br&gt;
載せてもらえないと不機嫌になるくらいにはお客さんが好き。&lt;/p&gt;
&lt;p&gt;&lt;img alt="愛想を振り撒く" class="gallery-image" data-flex-basis="332px" data-flex-grow="138" height="1611" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan04_hu_552037424d0be15.jpeg 800w, https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan04_hu_a991da9669399dd4.jpeg 1600w, https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan04.jpeg 2230w" width="2230"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="サービス精神旺盛" class="gallery-image" data-flex-basis="360px" data-flex-grow="150" height="1321" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan02_hu_93a7b41057620f62.jpeg 800w, https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan02_hu_66475f9e8ca179bf.jpeg 1600w, https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;猫カフェでアルバイトできるんじゃないかしら&amp;hellip;😂&lt;/p&gt;
&lt;p&gt;&lt;img alt="誰にでも簡単に抱かれてしまうメス猫()" class="gallery-image" data-flex-basis="312px" data-flex-grow="130" height="1522" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan05_hu_2ea828086d947c05.jpeg 800w, https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan05_hu_c5826e068efb2778.jpeg 1600w, https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan05.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="麻雀"&gt;麻雀
&lt;/h3&gt;&lt;p&gt;たびたび来客がある中で、&lt;br&gt;
なんとそとちゃんが麻雀好きなことが判明。🀄️&lt;/p&gt;
&lt;p&gt;マットの上に登って大胆に観戦。&lt;/p&gt;
&lt;p&gt;&lt;img alt="河が見えない" class="gallery-image" data-flex-basis="389px" data-flex-grow="162" height="1140" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan07.JPG" srcset="https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan07_hu_a802972b792a53bd.JPG 800w, https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan07_hu_5103f744d7269edf.JPG 1600w, https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan07.JPG 1851w" width="1851"&gt;&lt;/p&gt;
&lt;p&gt;さらに牌もおててで上手に転がす。&lt;br&gt;
すごいなあ&amp;hellip;(ゲームにならない)&lt;/p&gt;
&lt;p&gt;&lt;img alt="フリテン解消(物理)" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan08_hu_7899f654d72c7d95.jpeg 800w, https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan08_hu_1f16c2e03fe918df.jpeg 1600w, https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan08.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="クリスマス"&gt;クリスマス
&lt;/h3&gt;&lt;p&gt;そとちゃんは今年もサンタさんになった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="サンタさん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan09.jpeg" srcset="https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan09_hu_b038a64cbb4b4735.jpeg 800w, https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan09_hu_7b381eaed06dee7a.jpeg 1600w, https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan09.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;べらぼうにかわいいね&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="まんざらでもない" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan10.jpeg" srcset="https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan10_hu_faa99789ff7cefb3.jpeg 800w, https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan10_hu_91b7a860bda63c8d.jpeg 1600w, https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan10.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;今年も1年良い子にしていたそとちゃんには&lt;a class="link" href="https://www.garigari-cat.com/product/nyancoroby/nyancoroby-circle/" target="_blank" rel="noopener"
 &gt;プレゼント&lt;/a&gt;をご用意。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ニャンコロビー サークルタイプ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan11.jpeg" srcset="https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan11_hu_1933dc312e2bdbce.jpeg 800w, https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan11_hu_d601222f0c57d41d.jpeg 1600w, https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan11.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="たのしそう" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan12.jpeg" srcset="https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan12_hu_9353339c2d2b892c.jpeg 800w, https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan12_hu_8e9fc0e70974a88f.jpeg 1600w, https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan12.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;楽しいクリスマスになってよかった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="次のクリスマスも元気に迎えたい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan13.jpeg" srcset="https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan13_hu_d5987a9c80d536fa.jpeg 800w, https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan13_hu_94e23715518bd3fa.jpeg 1600w, https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan13.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;2024年もそとちゃんはよく食べて寝て遊んで元気だった。&lt;/p&gt;
&lt;p&gt;大きな環境の変化もあったが、&lt;br&gt;
そとちゃんはすぐに慣れてごきげんになってくれるので本当に助かる。&lt;/p&gt;
&lt;p&gt;しもべとしてはあまり良いことがない1年だったので、&lt;br&gt;
2025年はねこを見習って明るく楽しい年にしたい。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="クリスマスのベストショット" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan_hu_338bed3a41f2069e.jpeg 800w, https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan_hu_c100f759548f9ebf.jpeg 1600w, https://blog.uzimihsr.com/post/2025-01-12-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>11月のそとちゃん(2024)</title><link>https://blog.uzimihsr.com/post/2025-01-11-sotochan/</link><pubDate>Sat, 11 Jan 2025 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2025-01-11-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan.jpeg" alt="Featured image of post 11月のそとちゃん(2024)" /&gt;&lt;h2 id="そとちゃん"&gt;そとちゃん
&lt;/h2&gt;&lt;h3 id="こたつ"&gt;こたつ
&lt;/h3&gt;&lt;p&gt;だいぶ寒くなってきたのでこたつを導入。&lt;/p&gt;
&lt;p&gt;&lt;img alt="こたつ大好き" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan01_hu_cae862fdf3a7ee60.jpeg 800w, https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan01_hu_5f944a9c0ea40629.jpeg 1600w, https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="ごきげん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan02_hu_46555715989402e4.jpeg 800w, https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan02_hu_3c1101a64328d61b.jpeg 1600w, https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;例年通りそとちゃんはこたつ大好きねこちゃんなので楽しそう。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ご満悦" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan03_hu_32a4f38ca476cb54.jpeg 800w, https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan03_hu_e51620228e84f7b3.jpeg 1600w, https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan03.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="こたつ布団の裾を使いこなしている" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan04_hu_cc8d408c7127cead.jpeg 800w, https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan04_hu_89e0bedebf45af43.jpeg 1600w, https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;でもやっぱり人間が入ると嫌みたいで出ていってしまう。&lt;/p&gt;
&lt;p&gt;ちなみにこたつを出た後は人間のひざに収まる。&lt;/p&gt;
&lt;p&gt;&lt;img alt="いつもの" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan07_hu_d9b48ad4ad198dc.jpeg 800w, https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan07_hu_62c425e3decc1247.jpeg 1600w, https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan07.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="体がおさまってないようにも見える" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan06_hu_1a213caaf40e63ab.jpeg 800w, https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan06_hu_49fa6e82472eeea2.jpeg 1600w, https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan06.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;人間の脚が入っててもひざ上よりはこたつのほうが広くて快適だと思うのだが、&lt;br&gt;
ねこ基準だとそうではない様子。&lt;/p&gt;
&lt;p&gt;&lt;img alt="撫でろ圧" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan08_hu_a213d282191c443d.jpeg 800w, https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan08_hu_54fb8f9aa9bd1d6b.jpeg 1600w, https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan08.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="おちついてる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan09.jpeg" srcset="https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan09_hu_f4702e74888feefe.jpeg 800w, https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan09_hu_60c6d49ebea2c44d.jpeg 1600w, https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan09.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="かわいいね" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan05_hu_f7f2704a862cd1e8.jpeg 800w, https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan05_hu_360d1280796b2f25.jpeg 1600w, https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan05.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;仲良く共存できたらいいな&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="基本的にはねこのもの" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan10.jpeg" srcset="https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan10_hu_d9df67405242cb5e.jpeg 800w, https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan10_hu_96119bb808a1f5af.jpeg 1600w, https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan10.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="ふとん"&gt;ふとん
&lt;/h3&gt;&lt;p&gt;こたつも出したし、&lt;br&gt;
人間のふとんも暖かいやつに変更&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="邪魔すんなの顔" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan11.jpeg" srcset="https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan11_hu_c6756df163c6206e.jpeg 800w, https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan11_hu_1ee60e1ba532e820.jpeg 1600w, https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan11.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;したら&lt;a class="link" href="https://blog.uzimihsr.com/post/2023-12-03-sotochan/#%E3%81%B5%E3%81%A8%E3%82%93" target="_blank" rel="noopener"
 &gt;今回も&lt;/a&gt;そとちゃんに気に入られてしまった。&lt;/p&gt;
&lt;p&gt;ねこにはこたつがあるのに&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="まるい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan12.jpeg" srcset="https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan12_hu_f79dd002d01afd0c.jpeg 800w, https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan12_hu_999ad4265fcc3e4.jpeg 1600w, https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan12.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;人間が寝ててもおかまいなし。&lt;/p&gt;
&lt;p&gt;躊躇なく上に乗って寝てしまう。&lt;br&gt;
(ちなみに布団をかぶるのは苦手なので中には入らない)&lt;/p&gt;
&lt;p&gt;&lt;img alt="まるい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan13.jpeg" srcset="https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan13_hu_470f932d5f54e896.jpeg 800w, https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan13_hu_1012cd5051b3497c.jpeg 1600w, https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan13.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;まあ幸せそうなのでOKです。&lt;/p&gt;
&lt;p&gt;&lt;img alt="この寝顔である" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan14.jpeg" srcset="https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan14_hu_336bff6b2842f560.jpeg 800w, https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan14_hu_81309e45559c77eb.jpeg 1600w, https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan14.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;ブログを更新しないままついに年を越してしまった。&lt;/p&gt;
&lt;p&gt;今冬はまだまだ寒さが続くがそとちゃんは元気いっぱい。&lt;br&gt;
こたつとふとんをうまく使って寒さを乗り切って欲しい。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="めずらしく黒目が大きいねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan_hu_33bba5e2062dbe04.jpeg 800w, https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan_hu_263adcea35f71764.jpeg 1600w, https://blog.uzimihsr.com/post/2025-01-11-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>10月のそとちゃん(2024)</title><link>https://blog.uzimihsr.com/post/2024-12-09-sotochan/</link><pubDate>Mon, 09 Dec 2024 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2024-12-09-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan.jpeg" alt="Featured image of post 10月のそとちゃん(2024)" /&gt;&lt;h2 id="そとちゃん"&gt;そとちゃん
&lt;/h2&gt;&lt;h3 id="ごはん食べくらべ"&gt;ごはん食べくらべ
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://blog.uzimihsr.com/post/2024-10-30-sotochan/#%E3%81%94%E3%81%AF%E3%82%93%E5%95%8F%E9%A1%8C" target="_blank" rel="noopener"
 &gt;いつものごはんを食べなくなってしまった&lt;/a&gt;そとちゃん。&lt;/p&gt;
&lt;p&gt;&lt;img alt="黒缶に見向きもしない" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="1116" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan01.JPG" srcset="https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan01_hu_aa7980a0c248019f.JPG 800w, https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan01_hu_f657f607c397bafa.JPG 1600w, https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan01.JPG 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;何日も食べてくれないと流石に困るので、&lt;br&gt;
他のごはんを試してみることにした。&lt;/p&gt;
&lt;div class="video-wrapper"&gt;
 &lt;iframe loading="lazy" 
 src="https://www.youtube.com/embed/h0pwdHJJqlE" 
 allowfullscreen 
 title="YouTube Video"
 &gt;
 &lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;(久しぶりに動画作るのが結構大変で時間かかってしまった&amp;hellip;)&lt;/p&gt;
&lt;p&gt;試したごはんと結果はこんな感じ。&lt;/p&gt;
&lt;p&gt;&lt;img alt="近所で売ってた総合栄養食のウェットフード" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan06_hu_4b92e28f3f8a51f0.jpeg 800w, https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan06_hu_df3b45e4a678cc4b.jpeg 1600w, https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan06.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;ごはん&lt;/th&gt;
 &lt;th&gt;結果&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;a class="link" href="https://www.aixia.jp/product/detail_4580101260290" target="_blank" rel="noopener"
 &gt;MiawMiaw&lt;/a&gt;&lt;/td&gt;
 &lt;td&gt;🙂 黒缶に比べればまあ食べたな、という程度&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;a class="link" href="https://www.inaba-petfood.co.jp/product/detail/CIAO&amp;#43;%E3%83%91%E3%82%A6%E3%83%81/6680" target="_blank" rel="noopener"
 &gt;CIAO&lt;/a&gt;&lt;/td&gt;
 &lt;td&gt;🙂 MiawMiawと同じくらい食べたけど少し食べづらそうだった&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;a class="link" href="https://marspetcare.jp/category/NT_C_WR/WR_C_ADULT_CHICKEN_TSUNA_POUCH.html" target="_blank" rel="noopener"
 &gt;WILD RECIPE&lt;/a&gt;&lt;/td&gt;
 &lt;td&gt;🤩 飲むように食べた&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;a class="link" href="https://nestle.jp/brand/monpetit/product/mini_pouch/" target="_blank" rel="noopener"
 &gt;MonPetit&lt;/a&gt;&lt;/td&gt;
 &lt;td&gt;🤩 よく食べた&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;a class="link" href="https://page.mkgr.jp/product/190495/" target="_blank" rel="noopener"
 &gt;NaturaHa&lt;/a&gt;&lt;/td&gt;
 &lt;td&gt;😕 あんまり食べなかった&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;a class="link" href="https://www.aixia.jp/product/detail_4580101260733" target="_blank" rel="noopener"
 &gt;黒缶&lt;/a&gt;&lt;/td&gt;
 &lt;td&gt;😭 笑っちゃうくらい食べない&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;a class="link" href="https://shop.royalcanin.jp/%E3%82%A4%E3%83%B3%E3%83%89%E3%82%A2-%E3%82%B0%E3%83%AC%E3%83%BC%E3%83%93%E3%83%BC%EF%BC%88%E5%AE%A4%E5%86%85%E3%81%A7%E7%94%9F%E6%B4%BB%E3%81%99%E3%82%8B%E7%8C%AB%E5%B0%82%E7%94%A8%E3%82%A6%E3%82%A7%E3%83%83%E3%83%88%E3%83%95%E3%83%BC%E3%83%89-%E6%88%90%E7%8C%AB%E7%94%A8%EF%BC%89-1278" target="_blank" rel="noopener"
 &gt;ROYAL CANIN&lt;/a&gt;&lt;/td&gt;
 &lt;td&gt;😊 そこそこ食べた&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;a class="link" href="https://shop.royalcanin.jp/%E3%82%A4%E3%83%B3%E3%83%89%E3%82%A2-7&amp;#43;-%E3%82%B0%E3%83%AC%E3%83%BC%E3%83%93%E3%83%BC%EF%BC%88%E5%AE%A4%E5%86%85%E3%81%A7%E7%94%9F%E6%B4%BB%E3%81%99%E3%82%8B7%E6%AD%B3%E4%BB%A5%E4%B8%8A%E3%81%AE%E7%8C%AB%E5%B0%82%E7%94%A8%E3%83%95%E3%83%BC%E3%83%89-%E4%B8%AD%E9%AB%98%E9%BD%A2%E7%8C%AB%E7%94%A8%EF%BC%89-1305" target="_blank" rel="noopener"
 &gt;ROYAL CANIN(7+)&lt;/a&gt;&lt;/td&gt;
 &lt;td&gt;😊 シニア向けだけど、普通のと同じくらい食べた&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;a class="link" href="https://kalkan.jp/products/adult/pouch-jelly-maguro-shitabirame.html" target="_blank" rel="noopener"
 &gt;kalkan&lt;/a&gt;&lt;/td&gt;
 &lt;td&gt;🥰 めちゃめちゃ食べた&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;食べた順だとワイルドレシピとモンプチがかなりよかったんだけど、&lt;br&gt;
この2つは1袋あたりの量が他のフードの半分くらいなので若干使いづらいかな&amp;hellip;?と思った。&lt;br&gt;
毎回2袋開けるのは手間もゴミも増えるし、&lt;br&gt;
なにより値段も高いし&amp;hellip;💸&lt;/p&gt;
&lt;p&gt;その次くらいによく食べたのがカルカン。&lt;br&gt;
お手頃価格なのに食いつきがよかった。&lt;br&gt;
庶民派ねこちゃんですね&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="カルカン" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="1116" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan02.JPG" srcset="https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan02_hu_952ef10e9630ba0f.JPG 800w, https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan02_hu_5b19d75a72c899c1.JPG 1600w, https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan02.JPG 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="ほぼ完食" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="1116" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan03.JPG" srcset="https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan03_hu_791d5560faffbfae.JPG 800w, https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan03_hu_f46d4a3ce4c66245.JPG 1600w, https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan03.JPG 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;あとは自分のエゴでロイヤルカナンを選出。&lt;br&gt;
そろそろシニア向けフードにも挑戦しないとな&amp;hellip;と前から思っていたが、&lt;br&gt;
今回試した感じだと結構食べてくれそうなので。&lt;/p&gt;
&lt;p&gt;&lt;img alt="シニア向けロイヤルカナン" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="1116" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan04.JPG" srcset="https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan04_hu_58363d6089cc639f.JPG 800w, https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan04_hu_17fa33842fd264bd.JPG 1600w, https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan04.JPG 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="普通のと同じくらい食べた" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="1116" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan05.JPG" srcset="https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan05_hu_af0d95129fddea0b.JPG 800w, https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan05_hu_1ad7def9921d4a5b.JPG 1600w, https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan05.JPG 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;そんな感じで、&lt;br&gt;
当分の間はカルカンとロイヤルカナンを併用することにした。&lt;/p&gt;
&lt;p&gt;いっぱい食べてくれ〜🙏&lt;/p&gt;
&lt;h3 id="ハロウィン"&gt;ハロウィン
&lt;/h3&gt;&lt;p&gt;毎年のやつ。&lt;/p&gt;
&lt;p&gt;&lt;img alt="いつものドラキュラマント" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan07_hu_874ed9c32a484ea5.jpeg 800w, https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan07_hu_402074cf09215993.jpeg 1600w, https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan07.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;今年もあまり嫌がらず写真を撮らせてくれた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ゴミ箱の上でキメ顔" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan08_hu_7312e82ec765ddf4.jpeg 800w, https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan08_hu_891de217f12a1053.jpeg 1600w, https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan08.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="ちょっとダークな表情に見える" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan09.jpeg" srcset="https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan09_hu_cf28b4b2545e177a.jpeg 800w, https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan09_hu_c69c345ec2b82e5c.jpeg 1600w, https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan09.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="はよ終われの顔" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan10.jpeg" srcset="https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan10_hu_f17983e6818ce493.jpeg 800w, https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan10_hu_53ce924b2eae0891.jpeg 1600w, https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan10.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;かわいいねえ&amp;hellip;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;とりあえずご飯をちゃんと食べてくれるようになってよかった。&lt;/p&gt;
&lt;p&gt;これを書いている時点ですでに12月なのだが、今年の残りも健康に暮らせるようにしたい。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="袋大好きねこちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan_hu_2b55497c7957aba8.jpeg 800w, https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan_hu_b25098b0d42e5a05.jpeg 1600w, https://blog.uzimihsr.com/post/2024-12-09-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>Azure DatabricksワークスペースAPIをAPI Management経由で利用する</title><link>https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/</link><pubDate>Wed, 13 Nov 2024 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sotochan.jpeg" alt="Featured image of post Azure DatabricksワークスペースAPIをAPI Management経由で利用する" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;どうしてもDatabricksのワークスペースAPIをAPI Management経由で叩きたかったのだが、&lt;br&gt;
設定が結構大変な上になぞりやすい公式のドキュメントが見つからなかったので&lt;br&gt;
自分が設定できたときの手順を残しておく。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;DatabricksワークスペースAPIをAPI Managementのバックエンドとして利用する際はカスタムURLが使える&lt;/li&gt;
&lt;li&gt;API Managementに持たせる資格情報はDatabricksワークスペースのPATも利用可能だが、&lt;br&gt;よりセキュアにやるならAPI Managementのauthentication-managed-identityポリシーで&lt;code&gt;resource=&amp;quot;2ff814a6-3304-4ab8-85cb-cd0e6f879c1d&amp;quot;&lt;/code&gt;を指定する&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="430px" data-flex-grow="179" height="541" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/components.drawio.png" srcset="https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/components.drawio_hu_d6e5256f07546fe9.png 800w, https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/components.drawio.png 971w" width="971"&gt;&lt;/p&gt;
&lt;h2 id="前提条件"&gt;前提条件
&lt;/h2&gt;&lt;p&gt;Databricks, API Managementは以下の設定で作成済みとする。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Databricks
&lt;ul&gt;
&lt;li&gt;&lt;del&gt;マネージドVNet&lt;strong&gt;ではなく&lt;/strong&gt;カスタムVNetで作成されていること&lt;/del&gt;
&lt;ul&gt;
&lt;li&gt;参考: &lt;a class="link" href="https://learn.microsoft.com/ja-jp/azure/databricks/scenarios/quickstart-create-databricks-workspace-vnet-injection" target="_blank" rel="noopener"
 &gt;https://learn.microsoft.com/ja-jp/azure/databricks/scenarios/quickstart-create-databricks-workspace-vnet-injection&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;必須ではないが、カスタムVNetで立てた方がネットワーク関連の設定がしやすい&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;API Management
&lt;ul&gt;
&lt;li&gt;システム割り当てマネージドIDが有効になっていること
&lt;ul&gt;
&lt;li&gt;参考: &lt;a class="link" href="https://learn.microsoft.com/ja-jp/azure/api-management/api-management-howto-use-managed-service-identity" target="_blank" rel="noopener"
 &gt;https://learn.microsoft.com/ja-jp/azure/api-management/api-management-howto-use-managed-service-identity&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Databricksとの通信をプライベートにする場合は、Developer, Standard v2またはPremiumプラン(送信VNet統合または内部/外部VNetインジェクションをサポートしているプラン)で作成すること
&lt;ul&gt;
&lt;li&gt;参考: &lt;a class="link" href="https://learn.microsoft.com/ja-jp/azure/api-management/virtual-network-concepts" target="_blank" rel="noopener"
 &gt;https://learn.microsoft.com/ja-jp/azure/api-management/virtual-network-concepts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="手順"&gt;手順
&lt;/h2&gt;&lt;h3 id="バックエンドapiを作成"&gt;バックエンドAPIを作成
&lt;/h3&gt;&lt;p&gt;まずはAPI ManagementからDatabricksへ接続するためのバックエンドAPI情報を設定する。&lt;/p&gt;
&lt;p&gt;API Managementの管理画面から「APIs」→「Backends」→「+追加」と進み、&lt;br&gt;
バックエンド(例: dbw-01)を作成する。&lt;br&gt;
ランタイムURLにDatabricksワークスペースURLをぺたっと貼るだけでOK。&lt;br&gt;
(資格情報は後ほど設定する)&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="438px" data-flex-grow="182" height="1846" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc04.png" srcset="https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc04_hu_690e4da85d5b7eb2.png 800w, https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc04_hu_d70ca50b7d4fddba.png 1600w, https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc04_hu_73f069481c6a6b68.png 2400w, https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc04.png 3370w" width="3370"&gt;&lt;/p&gt;
&lt;p&gt;次にAPI定義を作成する。&lt;br&gt;
API Managementの管理画面から「APIs」→「API」→「+Add API」と進み、&lt;br&gt;
API定義(例: dbw-01)を作成する。&lt;br&gt;
名前とAPI URL suffix(例: dbw-01)を設定するだけでよい。&lt;br&gt;
(Web service URLは設定せず、後ほどポリシー式で先ほど作成したバックエンドを指定する)&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="437px" data-flex-grow="182" height="1850" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc05.png" srcset="https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc05_hu_b78412301766b7b9.png 800w, https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc05_hu_32cc797538b72aca.png 1600w, https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc05_hu_c4a2efdf81a79699.png 2400w, https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc05.png 3372w" width="3372"&gt;&lt;/p&gt;
&lt;p&gt;API定義が作成できたら、「Design」→「All operations」→「Design」から全操作(メソッド)共通のポリシー編集画面を開き、&lt;br&gt;
先ほど作成したバックエンドを指定する&lt;a class="link" href="https://learn.microsoft.com/ja-jp/azure/api-management/set-backend-service-policy" target="_blank" rel="noopener"
 &gt;set-backend-service&lt;/a&gt;ポリシーを追加する。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="437px" data-flex-grow="182" height="1850" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc07.png" srcset="https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc07_hu_7ad031a4dbcea23c.png 800w, https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc07_hu_f498abd0b8e9f6f4.png 1600w, https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc07_hu_527f4b8c94197d15.png 2400w, https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc07.png 3372w" width="3372"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="438px" data-flex-grow="182" height="1848" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc06.png" srcset="https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc06_hu_dbf861b1be9337f0.png 800w, https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc06_hu_2bd1af8abc8cd2a4.png 1600w, https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc06_hu_24499c5b8b069620.png 2400w, https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc06.png 3374w" width="3374"&gt;&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/980f538564b4c28c78c6f78764df4c46.js"&gt;&lt;/script&gt;
&lt;p&gt;また、リクエストを受信しバックエンドに流せるようにoperationを追加する。&lt;br&gt;
&lt;a class="link" href="https://docs.databricks.com/api/azure/workspace/introduction" target="_blank" rel="noopener"
 &gt;Azure Databricks REST API reference&lt;/a&gt;等を参考に必要なAPI操作を定義するのがよさげ。&lt;br&gt;
(&lt;a class="link" href="https://learn.microsoft.com/ja-jp/azure/api-management/import-api-from-oas?tabs=portal" target="_blank" rel="noopener"
 &gt;OpenAPI&lt;/a&gt;で定義されたものがあればインポートできるんだけど、自分が探した限りだと見つけられなかった)&lt;/p&gt;
&lt;p&gt;今回は簡単に確認したいだけなので、全てのGETリクエストをそのままのパスで流す&lt;a class="link" href="https://learn.microsoft.com/ja-jp/azure/api-management/add-api-manually#add-and-test-a-wildcard-operation" target="_blank" rel="noopener"
 &gt;ワイルドカード&lt;/a&gt;を設定する。&lt;br&gt;
(ドキュメントの注意事項にもあるように、本来は必要な操作だけをホワイトリスト的に定義した方が安全)&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="437px" data-flex-grow="182" height="1850" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc08.png" srcset="https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc08_hu_7ff8fd620e3d29d2.png 800w, https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc08_hu_18edd1257667b602.png 1600w, https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc08_hu_7ff3730107741558.png 2400w, https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc08.png 3372w" width="3372"&gt;&lt;/p&gt;
&lt;p&gt;これでAPIを利用する準備ができたように見えるが(実際ほぼ終わり)、&lt;br&gt;
資格情報を設定していないので試しにAPI Management越しにリクエストを送っても失敗する。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 変数の設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nv"&gt;apimUrl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;lt;API Managementの管理画面「概要」→「基本」→「ゲートウェイのURL」&amp;gt;&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# 例: https://apim-name.azure-api.net&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nv"&gt;subscriptionKey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;lt;API Managementの管理画面「APIs」→「サブスクリプション」から取得した主キー&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# API Management越しにクラスター一覧APIを呼び出す(Databricks用のキーは付与せず、API Management用のキーのみ設定)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -H &lt;span class="s2"&gt;&amp;#34;Ocp-Apim-Subscription-Key: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;subscriptionKey&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;apimUrl&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;/dbw-01/api/2.1/clusters/list
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;error_code&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;401&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;message&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;Unauthorized&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="api-managementのマネージドidに権限を付与"&gt;API ManagementのマネージドIDに権限を付与
&lt;/h3&gt;&lt;p&gt;次はこの資格情報を設定していく。&lt;/p&gt;
&lt;p&gt;参考: &lt;a class="link" href="https://learn.microsoft.com/ja-jp/azure/databricks/dev-tools/azure-mi-auth" target="_blank" rel="noopener"
 &gt;https://learn.microsoft.com/ja-jp/azure/databricks/dev-tools/azure-mi-auth&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Databricks側で&lt;a class="link" href="https://learn.microsoft.com/ja-jp/azure/databricks/dev-tools/auth/pat" target="_blank" rel="noopener"
 &gt;PAT&lt;/a&gt;発行してそれをAPI ManagementバックエンドのAuthorizationヘッダーに設定、でもいいんだけど、&lt;br&gt;
PATってあんまり推奨されるものでもない(個人の権限ですべての操作が行われてしまう)のでできればマネージドIDでやりたい。&lt;/p&gt;
&lt;p&gt;このため、まずはAPI Managementのシステム割り当てマネージドIDをDatabricksにサービスプリンシパルとして登録(ワークスペースへのアクセス権限を付与)する。&lt;br&gt;
(ドキュメントだとユーザー割り当てマネージドIDが推奨されてるけど、やってみたらシステム割り当てでもできちゃった)&lt;/p&gt;
&lt;p&gt;Databricksワークスペースで「設定」→「IDとアクセス」→「サービスプリンシパル」→「Service Principalを追加」からシステム割り当てマネージドIDを新規追加する。&lt;br&gt;
記載するIDはMicrosoft Entra IDの管理画面から「管理」→「すべてのアプリケーション」から対象のマネージドIDの情報を開き、「アプリケーションID」の値を利用する。&lt;br&gt;
(マネージドIDが見つけづらい場合はAPI Management管理画面(portal)の「セキュリティ」→「マネージドID」→「オブジェクト(プリンシパル)ID」の値を取得し、アプリケーション一覧画面で検索する。)&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="1232px" data-flex-grow="513" height="658" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc11.png" srcset="https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc11_hu_93ee26d17439b0ec.png 800w, https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc11_hu_cfa3cb9d4f99d53d.png 1600w, https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc11_hu_9a321d445ac36b42.png 2400w, https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc11.png 3378w" width="3378"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="419px" data-flex-grow="174" height="1926" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc09.png" srcset="https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc09_hu_8d225fdda5e851ab.png 800w, https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc09_hu_bbdbeee655c7ac93.png 1600w, https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc09_hu_2910e9471253dbce.png 2400w, https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc09.png 3370w" width="3370"&gt;&lt;/p&gt;
&lt;p&gt;必要であれば特定の権限を持つグループに対象のサービスプリンシパルを追加しておくこと。&lt;br&gt;
(今回は雑にadminに追加してしまっているが、本番運用の際はちゃんと専用のグループと権限を設定した方が良い)&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="422px" data-flex-grow="175" height="1918" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc15.png" srcset="https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc15_hu_b27ccd73576ada03.png 800w, https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc15_hu_c0f99c17199f67fe.png 1600w, https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc15_hu_778058f7d4ca7865.png 2400w, https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc15.png 3374w" width="3374"&gt;&lt;/p&gt;
&lt;p&gt;これでAPI ManagementのマネージドIDでDatabricksワークスペースを操作する権限が設定できた。&lt;/p&gt;
&lt;h3 id="api-managementのポリシー設定"&gt;API Managementのポリシー設定
&lt;/h3&gt;&lt;p&gt;マネージドIDに権限を付与できたので、&lt;br&gt;
次はAPI Managementがアクセストークンを取得するための&lt;a class="link" href="https://learn.microsoft.com/ja-jp/azure/api-management/authentication-managed-identity-policy" target="_blank" rel="noopener"
 &gt;authentication-managed-identity&lt;/a&gt;ポリシーを定義する。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;resource&lt;/code&gt;に何を指定すればよいのか迷うところだが、&lt;br&gt;
&lt;a class="link" href="https://learn.microsoft.com/ja-jp/azure/databricks/dev-tools/service-prin-aad-token#--get-a-microsoft-entra-id-access-token-with-the-microsoft-identity-platform-rest-api" target="_blank" rel="noopener"
 &gt;curlでアクセストークンを取得する例&lt;/a&gt;を見る感じ&lt;code&gt;2ff814a6-3304-4ab8-85cb-cd0e6f879c1d&lt;/code&gt;(DatabricksのプログラムID)でよさそう。&lt;br&gt;
(正直ここに気付けなくて1日くらい溶かした)&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="438px" data-flex-grow="182" height="1848" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc10.png" srcset="https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc10_hu_b5426a13327a7f41.png 800w, https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc10_hu_e035cd64a0211c4c.png 1600w, https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc10_hu_631c0d7170695e26.png 2400w, https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sc10.png 3374w" width="3374"&gt;&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/8a1baceaba132e0990ba5d199b6df365.js"&gt;&lt;/script&gt;
&lt;p&gt;ここまでできたら接続設定は完了。&lt;br&gt;
バックエンドAPIの作成後に試した手順で再度リクエストを送ると、&lt;br&gt;
今度は権限が付与されているので成功するようになっている。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -H &lt;span class="s2"&gt;&amp;#34;Ocp-Apim-Subscription-Key: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;subscriptionKey&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;apimUrl&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;/dbw-01/api/2.1/clusters/list
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;next_page_token&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;prev_page_token&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# クラスターを作成していないのでほぼ空っぽだが、APIリファレンス通りのレスポンスが返っているので動作確認は成功&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# https://docs.databricks.com/api/azure/workspace/clusters/list&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;やったぜ。&lt;br&gt;
これでAPI Managementにさえ疎通できればDatabricksワークスペースAPIが使えるようになった。&lt;/p&gt;
&lt;p&gt;後は必要に応じてネットワークを閉域化したり、お好みで&amp;hellip;&lt;/p&gt;
&lt;h3 id="bicep"&gt;bicep
&lt;/h3&gt;&lt;p&gt;今回ブラウザでポチポチした操作をコード(bicep)化するとこんな感じ。↓↓↓&lt;/p&gt;
&lt;p&gt;ネットワークまわりの設定で追加したところがあり、&lt;br&gt;
API Managementは外部モードでデプロイして、&lt;br&gt;
Databricksにはプライベートエンドポイント経由で接続するようにした。&lt;/p&gt;
&lt;p&gt;また、Databricksワークスペースの細かい設定(&lt;a class="link" href="https://blog.uzimihsr.com/post/2024-08-28-azure-databrics-configure-ip-access-list-with-api/" target="_blank" rel="noopener"
 &gt;IPアクセスリスト&lt;/a&gt;だったりサービスプリンシパル)はbicepでは書けないっぽいので(Terraformだといけるかも?)、&lt;br&gt;
手動で実施する必要がある。&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/1ea5de745b73b277e99cbb24cafb5f0c.js"&gt;&lt;/script&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="430px" data-flex-grow="179" height="541" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/components.drawio.png" srcset="https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/components.drawio_hu_d6e5256f07546fe9.png 800w, https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/components.drawio.png 971w" width="971"&gt;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;Azure Databricksが難しすぎて日々泣いている。😭&lt;br&gt;
&lt;a class="link" href="https://www.microsoft.com/ja-jp/events/azurebase/blog/5_reasons_databricks_runs_best_on_azure/" target="_blank" rel="noopener"
 &gt;ファーストパーティサービス&lt;/a&gt;と言いつつRBACはAzureロールと別物だし、サービスエンドポイントはないし&amp;hellip;&lt;br&gt;
同じように泣いている人の助けになれば幸い。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="顔がいいねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sotochan_hu_4b74629fb913bd2d.jpeg 800w, https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sotochan_hu_dc3f846a8cb978c6.jpeg 1600w, https://blog.uzimihsr.com/post/2024-11-13-azure-databricks-api-management/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>9月のそとちゃん(2024)</title><link>https://blog.uzimihsr.com/post/2024-10-30-sotochan/</link><pubDate>Wed, 30 Oct 2024 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2024-10-30-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan.jpeg" alt="Featured image of post 9月のそとちゃん(2024)" /&gt;&lt;h2 id="そとちゃん"&gt;そとちゃん
&lt;/h2&gt;&lt;h3 id="病院"&gt;病院
&lt;/h3&gt;&lt;p&gt;新居の近くに動物病院があるので、&lt;br&gt;
ご挨拶ついでにワクチンを打ちにいった。&lt;br&gt;
(毎年この時期に&lt;a class="link" href="https://blog.uzimihsr.com/post/2023-10-13-sotochan/" target="_blank" rel="noopener"
 &gt;3種混合ワクチン&lt;/a&gt;を打っている)&lt;/p&gt;
&lt;p&gt;&lt;img alt="相変わらずキャリーには自分から入る" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan01_hu_8b72ac3f14d2ebaf.jpeg 800w, https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan01_hu_edddb77ac0391024.jpeg 1600w, https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;そとちゃんは初めての病院でもおとなしく診察を受けててえらかった。👏&lt;br&gt;
診察室を勝手に探検するやんちゃは卒業したっぽい。&lt;/p&gt;
&lt;p&gt;体温はいつも通り38℃で正常。&lt;/p&gt;
&lt;p&gt;体重は環境が変わっても変わらず4.0kgをキープ。&lt;br&gt;
(ごはんちゃんと食べないのに&amp;hellip;🤔)&lt;/p&gt;
&lt;p&gt;毛並みと地肌もとても綺麗とのこと。&lt;br&gt;
(全然ブラシさせてくれないのに&amp;hellip;🤔)&lt;/p&gt;
&lt;p&gt;とりあえず触診は問題なしだった。&lt;/p&gt;
&lt;p&gt;ちょっと問題だったのは歯肉炎。&lt;br&gt;
去年&lt;a class="link" href="https://blog.uzimihsr.com/post/2023-05-05-sotochan/" target="_blank" rel="noopener"
 &gt;抜歯&lt;/a&gt;した右側の歯肉炎がひどいとのこと。&lt;br&gt;
(写真撮り忘れた)&lt;/p&gt;
&lt;p&gt;一応毎日歯みがきシートで拭いてはいたが、&lt;br&gt;
右側はかなり嫌がるのもあってなかなかうまく掃除できていなかったっぽい。😭&lt;/p&gt;
&lt;p&gt;普段からおとなしく掃除させてくれる左側の歯肉は綺麗だったので、&lt;br&gt;
もうちょっと歯みがきをがんばろう&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Vaccinated" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan02_hu_60191207dff7dfdb.jpeg 800w, https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan02_hu_92973d0179be30ca.jpeg 1600w, https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan02_hu_e87dd6c9fe92dd33.jpeg 2400w, https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan02.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;ワクチンはいつも通り数秒で打てたので、&lt;br&gt;
ついでに血液検査もしてもらった。&lt;/p&gt;
&lt;p&gt;引っ越し後初めての病院は約2時間で終了。&lt;br&gt;
家からかなり近くて助かっちゃった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="おつかれさまでした" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan03_hu_1d4269d48c1161a4.jpeg 800w, https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan03_hu_710f2cfd96476926.jpeg 1600w, https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan03.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="ごはん問題"&gt;ごはん問題
&lt;/h3&gt;&lt;p&gt;&lt;del&gt;めっちゃ好き嫌いする&lt;/del&gt;&lt;strong&gt;食のこだわりが強い&lt;/strong&gt;そとちゃん。&lt;/p&gt;
&lt;p&gt;ある日突然ウェットフード(黒缶)を食べなくなってしまった。😭&lt;/p&gt;
&lt;p&gt;&lt;img alt="匂いだけ嗅いでそっぽを向く" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan04_hu_3659bdb08e813eb1.jpeg 800w, https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan04_hu_f39fda7f3f82f0bb.jpeg 1600w, https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;ここ数年の&lt;a class="link" href="https://blog.uzimihsr.com/post/2022-03-10-sotochan/" target="_blank" rel="noopener"
 &gt;そとちゃんのごはん&lt;/a&gt;はずっとこんな感じだった。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;タイミング&lt;/th&gt;
 &lt;th&gt;ごはん&lt;/th&gt;
 &lt;th&gt;食べ方&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;朝&lt;/td&gt;
 &lt;td&gt;&lt;a class="link" href="https://www.royalcanin.com/jp/cats/products/vet-products/gastrointestinal-3905" target="_blank" rel="noopener"
 &gt;ロイヤルカナン 消化器サポート(ドライ)&lt;/a&gt; 10g&lt;/td&gt;
 &lt;td&gt;すぐ完食&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;昼&lt;/td&gt;
 &lt;td&gt;朝と同じカリカリ 10g&lt;/td&gt;
 &lt;td&gt;ちょっとだけ食べて残す&lt;br&gt;めんどくさいと全然食べない&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;夕&lt;/td&gt;
 &lt;td&gt;&lt;a class="link" href="https://www.aixia.jp/kurokan/lineup/" target="_blank" rel="noopener"
 &gt;黒缶パウチ&lt;/a&gt; 1袋&lt;br&gt;+トッピング(かつお節 or ちゅーる)&lt;/td&gt;
 &lt;td&gt;半分くらい食べて残りを朝までだらだら食べる&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;寝る前&lt;/td&gt;
 &lt;td&gt;&lt;a class="link" href="https://www.lion-pet.co.jp/product/petkiss/kinou_cat_niboshi.htm" target="_blank" rel="noopener"
 &gt;にぼし&lt;/a&gt; 1,2本&lt;br&gt;&lt;a class="link" href="https://www.lion-pet.co.jp/product/petkiss/kinou_cat_kani.htm" target="_blank" rel="noopener"
 &gt;かにかま&lt;/a&gt; 少々&lt;/td&gt;
 &lt;td&gt;爆速で食べる&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;現在はこんな感じ。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;タイミング&lt;/th&gt;
 &lt;th&gt;ごはん&lt;/th&gt;
 &lt;th&gt;食べ方&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;朝&lt;/td&gt;
 &lt;td&gt;ロイヤルカナン 消化器サポート(ドライ)&lt;/td&gt;
 &lt;td&gt;すぐ完食&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;昼&lt;/td&gt;
 &lt;td&gt;朝と同じカリカリ 10g&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;すぐ完食&lt;/strong&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;夕&lt;/td&gt;
 &lt;td&gt;黒缶パウチ 1袋&lt;br&gt;+トッピング(かつお節 or ちゅーる)&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;トッピングだけ食べて全残し&lt;/strong&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;寝る前&lt;/td&gt;
 &lt;td&gt;にぼし 1,2本&lt;br&gt;かにかま 少々&lt;/td&gt;
 &lt;td&gt;爆速で食べる&lt;br&gt;+&lt;strong&gt;足りないと文句を言う&lt;/strong&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;どうして&amp;hellip;😭&lt;/p&gt;
&lt;p&gt;&lt;img alt="こんなにガツガツ食べてたのに(数ヶ月前)" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan05_hu_8f286abfcfb40e72.jpeg 800w, https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan05_hu_26cb6427b21b89b.jpeg 1600w, https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan05.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;おやつやトッピングは喜んで食べるので、&lt;br&gt;
食欲がないわけではなさそう。&lt;br&gt;
(なんならおやつはもっとよこせと鳴く😭)&lt;/p&gt;
&lt;p&gt;&lt;img alt="トッピングだけ綺麗に舐めとってあとは全部残す超極悪ねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan06_hu_c14d6d873bcb8483.jpeg 800w, https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan06_hu_64611dd9cd85c968.jpeg 1600w, https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan06.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;病院に行ったときにも相談したが、&lt;br&gt;
「他のごはんやおやつをちゃんと食べるなら単純にウェットだけ飽きたんじゃね？」とのことだった。&lt;/p&gt;
&lt;p&gt;確かに今まで残しがちだったお昼のカリカリを完食するようになっているので、&lt;br&gt;
(今まではカリカリ食べなくて悩んでたくらいなのでこれにはかなり驚いた)&lt;br&gt;
本当に黒缶に飽きてしまったのだろうか&amp;hellip;?&lt;/p&gt;
&lt;p&gt;一応飽きがこないように同じ黒缶でも毎日違う味を4~5種類ローテしていたのだが&amp;hellip;😭&lt;/p&gt;
&lt;p&gt;&lt;img alt="他にもプレーン、ささみ、舌平目、サーモンなどなど試したが全滅" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan07_hu_55f5196d867a8810.jpeg 800w, https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan07_hu_c4d6e20c48b4e7d7.jpeg 1600w, https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan07.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;あまりにも黒缶を残すので、&lt;br&gt;
夜食用に追加でカリカリを出したらそれはちゃんと食べてしまった。&lt;br&gt;
どうしよう&amp;hellip;&lt;/p&gt;
&lt;h3 id="血液検査"&gt;血液検査
&lt;/h3&gt;&lt;p&gt;病院に行ってから1週間ほどで血液検査の結果が返ってきた。&lt;/p&gt;
&lt;p&gt;果たして結果は&amp;hellip;?&lt;/p&gt;
&lt;p&gt;&lt;img alt="すべて正常値" class="gallery-image" data-flex-basis="180px" data-flex-grow="75" height="4032" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan08_hu_4c4998dff8e5dc6f.jpeg 800w, https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan08_hu_17ef27fb15c364e.jpeg 1600w, https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan08_hu_5204921cf77c14cc.jpeg 2400w, https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan08.jpeg 3024w" width="3024"&gt;&lt;/p&gt;
&lt;p&gt;すこぶる健康だった。&lt;/p&gt;
&lt;p&gt;昔ちょっと高い数値が出たことのある腎臓系(クレアチニン)も正常範囲内で、健康優良児とのこと。&lt;/p&gt;
&lt;p&gt;この調子ならシニアねこでも半年に1回くらいの診察で問題ないらしい。&lt;/p&gt;
&lt;p&gt;よかった〜&lt;br&gt;
(ごはんちゃんと食べないのに&amp;hellip;🤔)&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;新しい動物病院も雰囲気がよくていい感じだった。&lt;br&gt;
健康とはいえ、年齢的に精密検査(猫ドック)もおすすめされたのでまた半年後に受けてみようかな&amp;hellip;?&lt;/p&gt;
&lt;p&gt;ごはん問題は結構深刻。&lt;br&gt;
おやつだけお腹いっぱい食べたいそとちゃん&lt;br&gt;
vs&lt;br&gt;
黒缶を食べて欲しい俺&lt;br&gt;
の家庭内戦争が毎晩発生しているので(俺が全敗)どうにか解決せねば&amp;hellip;&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="アンモニャイト" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan_hu_75624cb6c7bd083b.jpeg 800w, https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan_hu_6234b629a70a3317.jpeg 1600w, https://blog.uzimihsr.com/post/2024-10-30-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>8月のそとちゃん(2024)</title><link>https://blog.uzimihsr.com/post/2024-10-04-sotochan/</link><pubDate>Fri, 04 Oct 2024 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2024-10-04-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan.jpeg" alt="Featured image of post 8月のそとちゃん(2024)" /&gt;&lt;h2 id="そとちゃん"&gt;そとちゃん
&lt;/h2&gt;&lt;h3 id="新居を満喫"&gt;新居を満喫
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://blog.uzimihsr.com/post/2024-08-31-sotochan/" target="_blank" rel="noopener"
 &gt;引っ越し&lt;/a&gt;してそこそこ日数か経った。&lt;/p&gt;
&lt;p&gt;そとちゃんは新居に慣れて満喫中。&lt;br&gt;
(初日から我が物顔で振る舞っていたような気もするが)&lt;/p&gt;
&lt;p&gt;&lt;img alt="人間のベッドでごろごろ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan01_hu_b458f561ad473799.jpeg 800w, https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan01_hu_fc99de22b9f5a070.jpeg 1600w, https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;前の物件よりも部屋数が多いので、&lt;br&gt;
いろんな部屋でごろごろしているそとちゃんが見られて楽しい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="リビングでごろごろ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan02_hu_9b25decbdce81658.jpeg 800w, https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan02_hu_867175a6303348ae.jpeg 1600w, https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="仕事部屋でごろごろ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan03_hu_4abc58f46af70305.jpeg 800w, https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan03_hu_579b075ae0514e7d.jpeg 1600w, https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan03.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;こうして見ると右頬を下にして寝てることが多い？&lt;/p&gt;
&lt;p&gt;&lt;img alt="ソファでごろごろ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan04_hu_ebcf37c97aac81a6.jpeg 800w, https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan04_hu_83ed2829a6477bd1.jpeg 1600w, https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;そうでもなかった。&lt;/p&gt;
&lt;h3 id="デカいダンボール"&gt;デカいダンボール
&lt;/h3&gt;&lt;p&gt;作業用のディスプレイを新しく買ったのだが、&lt;br&gt;
その空き箱がそとちゃんのものになってしまった(定期イベント)。&lt;/p&gt;
&lt;p&gt;&lt;img alt="お気に入り" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan05_hu_f3a2612db6d8a5d1.jpeg 800w, https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan05_hu_3b76f5487387c13a.jpeg 1600w, https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan05.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;ディスプレイが約32インチだったのでこの箱が結構でかい。&lt;/p&gt;
&lt;p&gt;そとちゃんと比べても十分な(?)大きさ。&lt;/p&gt;
&lt;p&gt;&lt;img alt="だいぶ余裕のあるサイズ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan06_hu_2a25cf218594a23b.jpeg 800w, https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan06_hu_8d05f4b206070c7d.jpeg 1600w, https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan06.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;これくらい大きいものが置いておけるのも部屋が広くなった恩恵か&amp;hellip;?&lt;/p&gt;
&lt;p&gt;&lt;img alt="暇さえあれば乗ってる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan07_hu_7dadde573de6ce9c.jpeg 800w, https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan07_hu_6a0a418aadb529ef.jpeg 1600w, https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan07.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="家が広くなったのに"&gt;家が広くなったのに
&lt;/h3&gt;&lt;p&gt;繰り返しになってしまうが、&lt;br&gt;
引っ越しして家がめちゃめちゃ広く、部屋数も多くなった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="前の家だとソファとテーブルの距離が全然なかった" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan08_hu_4003d4a2f744de31.jpeg 800w, https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan08_hu_f8ff396ce1116f3c.jpeg 1600w, https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan08.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="電動ねこじゃらしを出しっぱなしにしても気にならない広さ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan09.jpeg" srcset="https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan09_hu_e180301bdd189abc.jpeg 800w, https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan09_hu_db5b01d77d29ee2e.jpeg 1600w, https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan09.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;そとちゃんも部屋をうろうろ移動したりして楽しんでいた。&lt;/p&gt;
&lt;p&gt;はずだった&amp;hellip;&lt;/p&gt;
&lt;p&gt;現在。&lt;/p&gt;
&lt;p&gt;そとちゃんはほとんど俺の仕事部屋(せまい)で過ごしている。&lt;/p&gt;
&lt;p&gt;&lt;img alt="仕事部屋にキャットタワーを置いてしまったのがミスだったか" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan10.jpeg" srcset="https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan10_hu_cc6827b5dd4a1590.jpeg 800w, https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan10_hu_5e81a093a166eb7d.jpeg 1600w, https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan10.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;なんで?&lt;/p&gt;
&lt;p&gt;俺が日中ほとんど仕事部屋にいるので、一緒に居たいのかしら🤔&lt;br&gt;
(そうだったらうれしいし健気でかわいい)&lt;/p&gt;
&lt;p&gt;&lt;img alt="まるでエンジニアみたいな作業環境だ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan11.jpeg" srcset="https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan11_hu_41bb47b43e4faf62.jpeg 800w, https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan11_hu_e4da864c0e2afd63.jpeg 1600w, https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan11.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;前の家でも滅多にやらなかった、&lt;br&gt;
作業の邪魔もしてくる。&lt;/p&gt;
&lt;p&gt;&lt;img alt="作業終わってるのに気付いてないのがかわいい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan12.jpeg" srcset="https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan12_hu_adeddd398ee31af.jpeg 800w, https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan12_hu_b4676375e2175e1f.jpeg 1600w, https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan12.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;かわいいね。&lt;/p&gt;
&lt;h3 id="右目"&gt;右目
&lt;/h3&gt;&lt;p&gt;じめじめしてたせいもあるが、&lt;br&gt;
あんまり右目の調子が良くなかった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="目ヤニ拭いた後が痛そう" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan13.jpeg" srcset="https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan13_hu_cbd51aad022019d7.jpeg 800w, https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan13_hu_5c5095b97cd9cbd1.jpeg 1600w, https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan13.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;目ヤニが出てたらこまめに拭いてはいるものの、&lt;br&gt;
どうしても粘度が強くて地肌に張り付いてしまうので結構痛そうに見える&amp;hellip;😭&lt;/p&gt;
&lt;p&gt;&lt;img alt="綺麗に拭き取るのは大変" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan14.jpeg" srcset="https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan14_hu_396adf63c3769c21.jpeg 800w, https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan14_hu_648107913759caff.jpeg 1600w, https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan14.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;毎年涼しくなると症状が軽くなるので、はやく治ってほしい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="本人(猫)は気にしてなさそう" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan15.jpeg" srcset="https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan15_hu_7f6557e39907fd91.jpeg 800w, https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan15_hu_690456dfe296c579.jpeg 1600w, https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan15.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;ついに1ヶ月遅れですら更新できなくなってしまった😭&lt;/p&gt;
&lt;p&gt;9月分こそは&amp;hellip;&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="更新の遅れに苦言を呈すねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan_hu_f459b5d757b89cce.jpeg 800w, https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan_hu_1d88f797dc8ba389.jpeg 1600w, https://blog.uzimihsr.com/post/2024-10-04-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>7月のそとちゃん(2024)</title><link>https://blog.uzimihsr.com/post/2024-08-31-sotochan/</link><pubDate>Sat, 31 Aug 2024 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2024-08-31-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan.jpeg" alt="Featured image of post 7月のそとちゃん(2024)" /&gt;&lt;h2 id="そとちゃん"&gt;そとちゃん
&lt;/h2&gt;&lt;h3 id="ひっこし"&gt;ひっこし
&lt;/h3&gt;&lt;p&gt;実は(?) 引っ越しをしていた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="段ボールを大量入手" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan01_hu_a113382a40599183.jpeg 800w, https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan01_hu_fa01294863b6b42d.jpeg 1600w, https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;これまで住んでいた物件は日当たりもよく、&lt;br&gt;
立地や設備も文句なしだったのだが&amp;hellip;&lt;/p&gt;
&lt;p&gt;諸事情(※)により住めなくなってしまったので、&lt;br&gt;
仕方なくお引っ越し。😭&lt;br&gt;
(※何がきっかけで叩かれるかわからないので私個人の名誉のために強調しておくが、決して近隣トラブルや契約の不備などではなく別の要因によるものである)&lt;/p&gt;
&lt;p&gt;&lt;img alt="本当に良い部屋でした" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan02_hu_8dce5c9faf278b95.jpeg 800w, https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan02_hu_c01015fe719d51c7.jpeg 1600w, https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;そとちゃんと暮らし始めてからこれで3回目の引っ越し。&lt;/p&gt;
&lt;p&gt;環境が変わることでストレスにならないだろうかと(一応)心配だったが、&lt;br&gt;
やはり流石のそとちゃん、ノリノリである。&lt;/p&gt;
&lt;p&gt;&lt;img alt="段ボールで爪研ぎ" class="gallery-image" data-flex-basis="180px" data-flex-grow="75" height="1984" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan03_hu_171ae668edca3769.jpeg 800w, https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan03.jpeg 1488w" width="1488"&gt;&lt;/p&gt;
&lt;p&gt;まずは荷造りで大興奮。&lt;/p&gt;
&lt;p&gt;&lt;img alt="空っぽの本棚はキャットタワー状態" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan04_hu_b1d9f11b1c282368.jpeg 800w, https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan04_hu_6cde1311eb66374e.jpeg 1600w, https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;荷物を作るたびにできる部屋の隙間と、&lt;br&gt;
段ボールが楽しくてしょうがない。&lt;/p&gt;
&lt;p&gt;&lt;img alt="少しでも隙間を見つけたらチェック" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan05_hu_a85b7d26bcbe588f.jpeg 800w, https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan05_hu_198deba5ef1d5fd2.jpeg 1600w, https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan05.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="組み立てた段ボールにはもれなく入る" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan06_hu_c68d7c22700297f6.jpeg 800w, https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan06_hu_6c2906c7481aab27.jpeg 1600w, https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan06.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;引っ越し当日はやっぱり大騒ぎ。&lt;/p&gt;
&lt;p&gt;車移動が苦手なそとちゃんはわんわん鳴いていた。&lt;br&gt;
(今回はこれまでで最も移動距離が長いのでかわいそうだった&amp;hellip;😭)&lt;/p&gt;
&lt;p&gt;新居についたら早速探検。&lt;/p&gt;
&lt;p&gt;知らない場所でも全然ビビらない性格なのは本当に助かる。&lt;br&gt;
ストレスで吐いたり粗相もなかった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="新居とご対面" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan07_hu_4eb626d96e362186.jpeg 800w, https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan07_hu_583481e67f46b6cb.jpeg 1600w, https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan07.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;引っ越し業者さんに絡んだり、&lt;br&gt;
部屋を一通りチェックして大満足。&lt;/p&gt;
&lt;p&gt;&lt;img alt="荷解きした段ボールもチェック たすかる(?)" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan08_hu_a5b62fdc76f686a0.jpeg 800w, https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan08_hu_7b88f2411c3d8dcc.jpeg 1600w, https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan08.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;部屋。&lt;br&gt;
そう、新居は部屋がめちゃめちゃ広い。&lt;/p&gt;
&lt;p&gt;どれくらいかというと、&lt;strong&gt;今まで住んでた部屋の倍くらい&lt;/strong&gt;の面積となっている。&lt;/p&gt;
&lt;p&gt;これまでは縦長1Kの部屋だったので直線でしか走れなかったのが、&lt;br&gt;
新居は正方形に近く、部屋数も増えたので、いろんな方向に曲がれたりと走り甲斐があるようだ。&lt;/p&gt;
&lt;p&gt;日当たりもよくてねこ大満足。&lt;/p&gt;
&lt;p&gt;&lt;img alt="走りつかれてお腹で息するくらいにはひろい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan09.jpeg" srcset="https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan09_hu_9af7773d75a44e0.jpeg 800w, https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan09_hu_f50140d2b01ba83d.jpeg 1600w, https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan09.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;そんなわけで、今回の引っ越しは大きなトラブルもなく無事に終わった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="たのしそう" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan10.jpeg" srcset="https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan10_hu_a9974fd213c996ae.jpeg 800w, https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan10_hu_51f35f5cb1187bfa.jpeg 1600w, https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan10.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;おつかれさまでした。&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;そんなこんなで最近はドチャクソ忙しかったのだが、なんとか落ちついてきた。&lt;br&gt;
(おかげで書くのがめちゃめちゃ遅くなったが😭)&lt;/p&gt;
&lt;p&gt;新居は広くなったぶん家賃も💸&lt;strong&gt;倍増&lt;/strong&gt;💸してしまったが、&lt;br&gt;
ねこが広い部屋で楽しそうなのでまあヨシ！ 😭&lt;/p&gt;
&lt;p&gt;(リアルフレンドの皆様は是非泊まり/遊びに来ていただきたい。ねこも喜ぶので&amp;hellip;)&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="ひろい部屋で存分にごろごろするねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan_hu_f85edb1df40cc3d3.jpeg 800w, https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan_hu_a328b9b47b3f1e0e.jpeg 1600w, https://blog.uzimihsr.com/post/2024-08-31-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>Azure Databricksワークスペースへアクセス可能なIPアドレスを制限する(curlで設定)</title><link>https://blog.uzimihsr.com/post/2024-08-28-azure-databrics-configure-ip-access-list-with-api/</link><pubDate>Wed, 28 Aug 2024 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2024-08-28-azure-databrics-configure-ip-access-list-with-api/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2024-08-28-azure-databrics-configure-ip-access-list-with-api/sotochan.jpeg" alt="Featured image of post Azure Databricksワークスペースへアクセス可能なIPアドレスを制限する(curlで設定)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Databricks CLIをインストールしてなくても、直接APIを叩いてワークスペースのIPアクセスリストを設定できる&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="経緯"&gt;経緯
&lt;/h2&gt;&lt;p&gt;Azure Databricksのワークスペースについて、&lt;br&gt;
インターネットからアクセスしたいが接続元のIPアドレスは制限したい、ということがあった。&lt;br&gt;
(VPN引いてプライベート接続はお金かかるからあんまりやりたくなかった)&lt;/p&gt;
&lt;p&gt;IPアクセスリストの設定は&lt;a class="link" href="https://learn.microsoft.com/ja-jp/azure/databricks/security/network/front-end/ip-access-list-workspace" target="_blank" rel="noopener"
 &gt;公式の設定手順&lt;/a&gt;はあるが、&lt;br&gt;
Databricks CLI前提の手順になっている+&lt;strong&gt;自分の都合によりどうしてもCLIのインストールができない&lt;/strong&gt;という状況なので、&lt;br&gt;
APIをcurlで叩いて設定してみた。&lt;/p&gt;
&lt;h2 id="手順"&gt;手順
&lt;/h2&gt;&lt;h3 id="ワークスペースurlを取得"&gt;ワークスペースURLを取得
&lt;/h3&gt;&lt;p&gt;APIをたたくのに必要なのでワークスペースURLを取得する。&lt;br&gt;
方法はなんでもいいけど、自分はAzure portalからコピーした。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Azure portalからワークスペースURLを取得" class="gallery-image" data-flex-basis="1030px" data-flex-grow="429" height="786" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-08-28-azure-databrics-configure-ip-access-list-with-api/sc03.png" srcset="https://blog.uzimihsr.com/post/2024-08-28-azure-databrics-configure-ip-access-list-with-api/sc03_hu_79abe3ac502d7852.png 800w, https://blog.uzimihsr.com/post/2024-08-28-azure-databrics-configure-ip-access-list-with-api/sc03_hu_b651c3e7a339dd0.png 1600w, https://blog.uzimihsr.com/post/2024-08-28-azure-databrics-configure-ip-access-list-with-api/sc03_hu_8e78f983e0568dca.png 2400w, https://blog.uzimihsr.com/post/2024-08-28-azure-databrics-configure-ip-access-list-with-api/sc03.png 3374w" width="3374"&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ワークスペースURL&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nv"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;https://adb-00000000000000.00.azuredatabricks.net&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="アクセストークンの取得"&gt;アクセストークンの取得
&lt;/h3&gt;&lt;p&gt;APIを叩くためのアクセストークンを取得する。&lt;br&gt;
&lt;a class="link" href="https://learn.microsoft.com/ja-jp/azure/databricks/dev-tools/auth/pat#--azure-databricks-personal-access-tokens-for-workspace-users" target="_blank" rel="noopener"
 &gt;https://learn.microsoft.com/ja-jp/azure/databricks/dev-tools/auth/pat#--azure-databricks-personal-access-tokens-for-workspace-users&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="アクセストークンの生成" class="gallery-image" data-flex-basis="683px" data-flex-grow="284" height="1182" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-08-28-azure-databrics-configure-ip-access-list-with-api/sc01.png" srcset="https://blog.uzimihsr.com/post/2024-08-28-azure-databrics-configure-ip-access-list-with-api/sc01_hu_6f2c501594f9e567.png 800w, https://blog.uzimihsr.com/post/2024-08-28-azure-databrics-configure-ip-access-list-with-api/sc01_hu_4aa1398cf891a36f.png 1600w, https://blog.uzimihsr.com/post/2024-08-28-azure-databrics-configure-ip-access-list-with-api/sc01_hu_7886147831748958.png 2400w, https://blog.uzimihsr.com/post/2024-08-28-azure-databrics-configure-ip-access-list-with-api/sc01.png 3368w" width="3368"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="生成したトークン" class="gallery-image" data-flex-basis="1130px" data-flex-grow="470" height="716" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-08-28-azure-databrics-configure-ip-access-list-with-api/sc02.png" srcset="https://blog.uzimihsr.com/post/2024-08-28-azure-databrics-configure-ip-access-list-with-api/sc02_hu_856248d35fb415e6.png 800w, https://blog.uzimihsr.com/post/2024-08-28-azure-databrics-configure-ip-access-list-with-api/sc02_hu_46702928b4da876c.png 1600w, https://blog.uzimihsr.com/post/2024-08-28-azure-databrics-configure-ip-access-list-with-api/sc02_hu_799dd24618af33bd.png 2400w, https://blog.uzimihsr.com/post/2024-08-28-azure-databrics-configure-ip-access-list-with-api/sc02.png 3372w" width="3372"&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# アクセストークン&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nv"&gt;token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;dapixxxxxxxxxxxxxxxxx-3&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="ipアクセスリストの作成"&gt;IPアクセスリストの作成
&lt;/h3&gt;&lt;p&gt;IPアクセスリストを作成する。&lt;br&gt;
&lt;a class="link" href="https://docs.databricks.com/api/azure/workspace/ipaccesslists/create" target="_blank" rel="noopener"
 &gt;https://docs.databricks.com/api/azure/workspace/ipaccesslists/create&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# リクエストボディJSON (ip_addressesにアクセスを許可したいIP(v4)のリストをCIDR表記で記載する)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat &lt;span class="s"&gt;&amp;lt;&amp;lt; EOF &amp;gt; ip-access-list.json
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;#34;label&amp;#34;: &amp;#34;My Office&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;#34;list_type&amp;#34;: &amp;#34;ALLOW&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;#34;ip_addresses&amp;#34;: [
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;#34;133.xxx.xxx.xxx/32&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Create access list APIをコール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -X POST -H &lt;span class="s2"&gt;&amp;#34;Content-Type: application/json&amp;#34;&lt;/span&gt; -H &lt;span class="s2"&gt;&amp;#34;Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$token&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="s2"&gt;/api/2.0/ip-access-lists&amp;#34;&lt;/span&gt; -d &lt;span class="s1"&gt;&amp;#39;@ip-access-list.json&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;ip_access_list&amp;#34;&lt;/span&gt;:&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;list_id&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;ec88d280-02f6-4945-84b8-76a7bcdeb05f&amp;#34;&lt;/span&gt;, &lt;span class="s2"&gt;&amp;#34;label&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;My Office&amp;#34;&lt;/span&gt;, &lt;span class="s2"&gt;&amp;#34;ip_addresses&amp;#34;&lt;/span&gt;:&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;133.xxx.xxx.xxx/32&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;address_count&amp;#34;&lt;/span&gt;:1,&lt;span class="s2"&gt;&amp;#34;list_type&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;ALLOW&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;created_at&amp;#34;&lt;/span&gt;:1724834759440,&lt;span class="s2"&gt;&amp;#34;created_by&amp;#34;&lt;/span&gt;:1878671197505866,&lt;span class="s2"&gt;&amp;#34;updated_at&amp;#34;&lt;/span&gt;:1724834759440,&lt;span class="s2"&gt;&amp;#34;updated_by&amp;#34;&lt;/span&gt;:1878671197505866,&lt;span class="s2"&gt;&amp;#34;enabled&amp;#34;&lt;/span&gt;:true&lt;span class="o"&gt;}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ちなみに、&lt;br&gt;
一番最初に作るIPアクセスリストの範囲に現在の自分のIPアドレスが含まれていない場合は怒られてしまうので注意。&lt;br&gt;
(おそらく現在の端末から操作できなくなるのを防ぐため。&lt;br&gt;
自分のIPアドレスからの通信を許可するリストが既に存在すれば、&lt;br&gt;
2つめ以降のリスト作成時には自身のIPが含まれていなくても問題なし。)&lt;/p&gt;
&lt;p&gt;自分のIPアドレスは &lt;a class="link" href="https://checkip.amazonaws.com/" target="_blank" rel="noopener"
 &gt;https://checkip.amazonaws.com/&lt;/a&gt; とか、なんか適当に調べれば出てくるはず。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ip-access-list.jsonのip_addressesに現在の自分のIPアドレスがない場合&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -X POST -H &lt;span class="s2"&gt;&amp;#34;Content-Type: application/json&amp;#34;&lt;/span&gt; -H &lt;span class="s2"&gt;&amp;#34;Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$token&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="s2"&gt;/api/2.0/ip-access-lists&amp;#34;&lt;/span&gt; -d &lt;span class="s1"&gt;&amp;#39;@ip-access-list.json&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;error_code&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;INVALID_STATE&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;message&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;Your current IP 133.xxx.xxx.yyy will not be allowed to access the workspace under current configuration&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="ipアクセスリストを有効化"&gt;IPアクセスリストを有効化
&lt;/h3&gt;&lt;p&gt;IPアクセスリストでのアクセス制限を有効化する。&lt;br&gt;
&lt;a class="link" href="https://docs.databricks.com/api/azure/workspace/workspaceconf/setstatus" target="_blank" rel="noopener"
 &gt;https://docs.databricks.com/api/azure/workspace/workspaceconf/setstatus&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Enable features&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -X PATCH -H &lt;span class="s2"&gt;&amp;#34;Content-Type: application/json&amp;#34;&lt;/span&gt; -H &lt;span class="s2"&gt;&amp;#34;Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$token&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="s2"&gt;/api/2.0/workspace-conf&amp;#34;&lt;/span&gt; -d &lt;span class="s1"&gt;&amp;#39;{&amp;#34;enableIpAccessLists&amp;#34;: &amp;#34;true&amp;#34;}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以上の手順が正しく実施できていれば、&lt;br&gt;
IPアクセスリストにないIPアドレスからワークスペースを開こうとするとちゃんと拒否されるようになる。&lt;br&gt;
やったぜ。&lt;/p&gt;
&lt;p&gt;&lt;img alt="許可されてないIPアドレスだとサインイン画面で怒られる" class="gallery-image" data-flex-basis="239px" data-flex-grow="99" height="554" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-08-28-azure-databrics-configure-ip-access-list-with-api/sc04.png" width="552"&gt;&lt;/p&gt;
&lt;p&gt;一応、IPアクセスリストの状態を確認する方法も貼っておく。&lt;br&gt;
&lt;a class="link" href="https://docs.databricks.com/api/azure/workspace/ipaccesslists/list" target="_blank" rel="noopener"
 &gt;https://docs.databricks.com/api/azure/workspace/ipaccesslists/list&lt;/a&gt;&lt;br&gt;
&lt;a class="link" href="https://docs.databricks.com/api/azure/workspace/workspaceconf/getstatus" target="_blank" rel="noopener"
 &gt;https://docs.databricks.com/api/azure/workspace/workspaceconf/getstatus&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Check configuration status&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -s -H &lt;span class="s2"&gt;&amp;#34;Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$token&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="s2"&gt;/api/2.0/workspace-conf?keys=enableIpAccessLists&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; jq
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;enableIpAccessLists&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;true&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Get access lists&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -s -H &lt;span class="s2"&gt;&amp;#34;Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$token&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="s2"&gt;/api/2.0/ip-access-lists&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; jq
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;ip_access_lists&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;list_id&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;ec88d280-02f6-4945-84b8-76a7bcdeb05f&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;label&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;My Office&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;ip_addresses&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;133.xxx.xxx.xxx/32&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;address_count&amp;#34;&lt;/span&gt;: 1,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;list_type&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;ALLOW&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;created_at&amp;#34;&lt;/span&gt;: 1724834759440,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;created_by&amp;#34;&lt;/span&gt;: 1878671197505866,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;updated_at&amp;#34;&lt;/span&gt;: 1724834759440,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;updated_by&amp;#34;&lt;/span&gt;: 1878671197505866,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;enabled&amp;#34;&lt;/span&gt;: &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;(設定が終わったらアクセストークンの無効化を忘れずに&amp;hellip;)&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;最近生成AIに頼りすぎで、なんか久しぶりにこういうの書いた気がする。&lt;br&gt;
たまにはいいな〜&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="虚無ねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-08-28-azure-databrics-configure-ip-access-list-with-api/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2024-08-28-azure-databrics-configure-ip-access-list-with-api/sotochan_hu_a081dd817640ccee.jpeg 800w, https://blog.uzimihsr.com/post/2024-08-28-azure-databrics-configure-ip-access-list-with-api/sotochan_hu_73363d254c2e5e29.jpeg 1600w, https://blog.uzimihsr.com/post/2024-08-28-azure-databrics-configure-ip-access-list-with-api/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-6776523357552572"
 crossorigin="anonymous"&gt;&lt;/script&gt;
&lt;!-- displayads01 --&gt;
&lt;p&gt;&lt;ins class="adsbygoogle"
style="display:block"
data-ad-client="ca-pub-6776523357552572"
data-ad-slot="7322038275"
data-ad-format="auto"
data-full-width-responsive="true"&gt;&lt;/ins&gt;&lt;/p&gt;
&lt;script&gt;
 (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;</description></item><item><title>6月のそとちゃん(2024)</title><link>https://blog.uzimihsr.com/post/2024-07-25-sotochan/</link><pubDate>Thu, 25 Jul 2024 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2024-07-25-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan.jpeg" alt="Featured image of post 6月のそとちゃん(2024)" /&gt;&lt;h2 id="そとちゃん"&gt;そとちゃん
&lt;/h2&gt;&lt;h3 id="カリカリ"&gt;カリカリ
&lt;/h3&gt;&lt;p&gt;5月末に買った&lt;a class="link" href="https://blog.uzimihsr.com/post/2024-06-06-sotochan/#%E3%82%AB%E3%83%AA%E3%82%AB%E3%83%AA%E3%83%9E%E3%82%B7%E3%83%BC%E3%83%B3" target="_blank" rel="noopener"
 &gt;新しいカリカリマシーン&lt;/a&gt;がいい感じ。&lt;/p&gt;
&lt;p&gt;6月は結構じめじめしていたけど、&lt;br&gt;
湿気対策のおかげでカリカリがちゃんと乾いた状態をキープできていた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ちゃんと食べてえらい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan01_hu_3069eb396cd45ee7.jpeg 800w, https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan01_hu_3018766d425d0d91.jpeg 1600w, https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;そとちゃんも結構食べてくれていて、完食することも多くなってきた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="完食 えらい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan02_hu_7857f53268559f87.jpeg 800w, https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan02_hu_a4916031ae0d3723.jpeg 1600w, https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;一緒に暮らして6年目にしてようやく、カリカリがしけて全然食べない問題がついに解決したっぽい。&lt;/p&gt;
&lt;p&gt;やった〜🎉&lt;br&gt;
(なお、俺が居るとあまり食べないのは変わらず&amp;hellip;)&lt;/p&gt;
&lt;p&gt;&lt;img alt="お留守番のときはもりもり食べる" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="1080" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan03.PNG" srcset="https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan03_hu_391a55963b8c9a90.PNG 800w, https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan03_hu_30ed9b39fa983ea3.PNG 1600w, https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan03.PNG 1920w" width="1920"&gt;&lt;/p&gt;
&lt;h3 id="あつい"&gt;あつい
&lt;/h3&gt;&lt;p&gt;夏が始まった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ねこの開き" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan04_hu_8765ae7ad4dbf200.jpeg 800w, https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan04_hu_dc3d74c0c097c7b9.jpeg 1600w, https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;暑くてたまらない。&lt;/p&gt;
&lt;p&gt;&lt;img alt="暑い" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan05_hu_13788cbd59a1fcb2.jpeg 800w, https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan05_hu_a0364f5affb92e54.jpeg 1600w, https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan05.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;でもそとちゃんは毎日ひなたぼっこ&amp;hellip;&lt;br&gt;
もちろんエアコンはガンガンに回してるけど、それでも窓際は暑いだろうに&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="どうして…" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan06_hu_2fdf80a9fddb6218.jpeg 800w, https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan06_hu_16305123be735747.jpeg 1600w, https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan06.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;流石に1日中窓際という感じでもなく、&lt;br&gt;
たまに廊下に落ちてることもある。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ねこが おちている" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan07_hu_9e92515124ec00a2.jpeg 800w, https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan07_hu_81846b7cde29d43.jpeg 1600w, https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan07.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;だらけきっているねこはとてもかわいい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="やる気なし" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan08_hu_b4e4a55aa6c7e105.jpeg 800w, https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan08_hu_8fbe2727ab78f3ee.jpeg 1600w, https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan08.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;溶けてる顔がたくさん見られてかわいいけど、&lt;br&gt;
それでもやっぱり早く涼しくなってほしい&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="でも窓際でガチ寝するのは怖いからやめてほしい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan09.jpeg" srcset="https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan09_hu_4cf91a7ec2ef6dce.jpeg 800w, https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan09_hu_d8c3ea51ba74ca00.jpeg 1600w, https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan09.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;ちょっといろいろありすぎて、意味わかんないくらい遅筆になってしまった。&lt;br&gt;
来月こそは&amp;hellip;&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="あっついのに毛布で寝るねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan_hu_28a1d210d545d9.jpeg 800w, https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan_hu_9044aae29ae7bb7b.jpeg 1600w, https://blog.uzimihsr.com/post/2024-07-25-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>5月のそとちゃん(2024)</title><link>https://blog.uzimihsr.com/post/2024-06-06-sotochan/</link><pubDate>Thu, 06 Jun 2024 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2024-06-06-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan.JPG" alt="Featured image of post 5月のそとちゃん(2024)" /&gt;&lt;h2 id="そとちゃん"&gt;そとちゃん
&lt;/h2&gt;&lt;h3 id="8さい"&gt;8さい
&lt;/h3&gt;&lt;p&gt;5月生まれ(推定)のそとちゃん。&lt;br&gt;
ついに8さいになった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="誕生日プレゼント" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan01_hu_bbedc5b5a9768442.jpeg 800w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan01_hu_2e8132c411d97fd9.jpeg 1600w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;当然本人(にゃん)にその意識はないが、&lt;br&gt;
おめでたいので勝手にお祝いさせてもらった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="なんかおもちゃが増えたくらいにしか思ってなさそう" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan02_hu_75b57c9c163d8126.jpeg 800w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan02_hu_b82af6ee032f6a16.jpeg 1600w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;去年はキャットタワーだったが、今年はおもちゃをプレゼント。&lt;/p&gt;
&lt;p&gt;まずはでるでる自飯器。&lt;/p&gt;
&lt;p&gt;これはびっくりするくらい食いつかなかった&amp;hellip;😭&lt;/p&gt;
&lt;p&gt;&lt;img alt="出る出る" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan03_hu_63f09928758ed32d.jpeg 800w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan03_hu_ce62fa38766583d1.jpeg 1600w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan03.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;お次は電池で動く虫のおもちゃ。&lt;/p&gt;
&lt;p&gt;残念なことに、おもちゃの仕組み上カーペットの上だと全然動かなかった。&lt;br&gt;
これもハズレ&amp;hellip;😭&lt;/p&gt;
&lt;p&gt;&lt;img alt="虫" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan04_hu_b03ce0a85a710eb5.jpeg 800w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan04_hu_cb9a0dd204fdc8d0.jpeg 1600w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;と思ったらそとちゃんは気に入った様子。&lt;/p&gt;
&lt;p&gt;動けないけどじたばたしている虫にちょっかいを出すのが楽しいらしい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="良い性格してる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan05_hu_108ab7e69e35fb21.jpeg 800w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan05_hu_fc5f63134d8936cf.jpeg 1600w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan05.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;あとはいつものまたたびスプレーと、&lt;/p&gt;
&lt;p&gt;&lt;img alt="パッケージの外からでも匂い嗅ぐの執念じみた何かを感じる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan06_hu_fd9c7acf8d9cbe41.jpeg 800w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan06_hu_203fc63338947045.jpeg 1600w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan06.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;いつものカサカサする猫じゃらしをプレゼント。&lt;/p&gt;
&lt;p&gt;&lt;img alt="結局これが一番楽しい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan07_hu_d2924edfa01536c7.jpeg 800w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan07_hu_f00ebb4977794372.jpeg 1600w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan07.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;最後はいつもよりちょっとおやつ多めのごはんでお祝い。&lt;/p&gt;
&lt;p&gt;&lt;img alt="前科持ちなのでねこ用ケーキは一生買いません" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan08_hu_201185d4dcc96bc4.jpeg 800w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan08_hu_a2e4c8aa7ab98a56.jpeg 1600w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan08.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;よかったね〜〜🎉&lt;/p&gt;
&lt;h3 id="記念写真"&gt;記念写真
&lt;/h3&gt;&lt;p&gt;もう毎年恒例となった誕生日の記念写真。&lt;/p&gt;
&lt;p&gt;今年もいつもの写真屋さんで撮ってもらった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="モデル" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan12.jpeg" srcset="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan12_hu_a2c691f1b8adb79c.jpeg 800w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan12_hu_b0cbe97601d124e0.jpeg 1600w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan12.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;スタジオに放たれたそとちゃんはやっぱり大冒険&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="探検" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan11.jpeg" srcset="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan11_hu_c4ca2400ad7fe9e6.jpeg 800w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan11_hu_13e09939c8937b6b.jpeg 1600w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan11.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;小道具や機材を思う存分存分探検してから撮影開始。&lt;/p&gt;
&lt;p&gt;&lt;img alt="忙しい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan13.jpeg" srcset="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan13_hu_ea80e46b790a84fb.jpeg 800w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan13_hu_26ef65235e8acbb3.jpeg 1600w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan13.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;今年のそとちゃんはあんまり集中力がなくて、&lt;br&gt;
カメラマンさんも大変そうだった😹&lt;/p&gt;
&lt;p&gt;&lt;img alt="奇跡のカメラ目線 美脚だね" class="gallery-image" data-flex-basis="359px" data-flex-grow="149" height="1323" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan14.JPG" srcset="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan14_hu_ce67e9769ed99493.JPG 800w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan14_hu_e697511231cf95ac.JPG 1600w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan14.JPG 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;目線を釣るためのおもちゃを持っていったのだが、&lt;br&gt;
そとちゃんがあまりにも熱中してしまい逆効果だった😭&lt;/p&gt;
&lt;p&gt;&lt;img alt="ねずみとツーショット" class="gallery-image" data-flex-basis="359px" data-flex-grow="149" height="1323" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan15.JPG" srcset="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan15_hu_5627dc4126c26b4b.JPG 800w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan15_hu_eb2ae081fb1b6374.JPG 1600w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan15.JPG 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="カメラそっちのけで遊ぶ" class="gallery-image" data-flex-basis="359px" data-flex-grow="149" height="1323" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan16.JPG" srcset="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan16_hu_a2355027022560a3.JPG 800w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan16_hu_4e5a81d2fa4f78d0.JPG 1600w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan16.JPG 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;こんなこともあろうかと、&lt;br&gt;
ここで秘密兵器のまたたびを投入！&lt;/p&gt;
&lt;p&gt;&amp;hellip;今度はまたたびを持つ俺を追いかけてしまい、&lt;br&gt;
そとちゃん単体でうまく撮れない😭&lt;br&gt;
(画角に俺の手が入ってしまった)&lt;/p&gt;
&lt;p&gt;&lt;img alt="追いかけちゃう" class="gallery-image" data-flex-basis="359px" data-flex-grow="149" height="1323" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan17.JPG" srcset="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan17_hu_97c17e15cc31b1e8.JPG 800w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan17_hu_74063fbe1ecfb9db.JPG 1600w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan17.JPG 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="かわいいけどね もうちょっと協力してほしい" class="gallery-image" data-flex-basis="359px" data-flex-grow="149" height="1323" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan18.JPG" srcset="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan18_hu_1d49c5d177798c23.JPG 800w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan18_hu_d689b0d1a44dc895.JPG 1600w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan18.JPG 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;結局今回はほとんどカメラ目線を貰えずに時間(集中力)切れ&amp;hellip;&lt;br&gt;
つくづくねこ様は人間の思い通りにならないことを再認識した。&lt;/p&gt;
&lt;p&gt;&lt;img alt="でもがんばったからえらい" class="gallery-image" data-flex-basis="359px" data-flex-grow="149" height="1323" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan19.JPG" srcset="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan19_hu_7183283f51d84777.JPG 800w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan19_hu_ed1c1d1c0ee0c86f.JPG 1600w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan19.JPG 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;でも懲りずにまた来年も撮りに行こう&amp;hellip;&lt;/p&gt;
&lt;h3 id="風呂場"&gt;風呂場
&lt;/h3&gt;&lt;p&gt;最近暑いから？そとちゃんがよく風呂場で遊んでいた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="たのしそう" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan21.jpeg" srcset="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan21_hu_26213fa7f80010c7.jpeg 800w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan21_hu_3f0edc9a96f44e9.jpeg 1600w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan21.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;そとちゃんが入れないように普段湯船に載せている風呂フタを立てて乾かしていたら、&lt;br&gt;
いつのまにか侵入されていた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="湯船がすき" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan22.jpeg" srcset="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan22_hu_d0b799615d7155e8.jpeg 800w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan22_hu_50b2b63da80cbd06.jpeg 1600w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan22.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="気に入った" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan23.jpeg" srcset="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan23_hu_f8b5f7f3d99fd776.jpeg 800w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan23_hu_bb36e309dbf0286b.jpeg 1600w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan23.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;一度入った湯船の中が気に入ってしまったようで、&lt;br&gt;
何回引っ張り出してもまた入るようになった😹&lt;/p&gt;
&lt;p&gt;&lt;img alt="かわいいおしり" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan24.jpeg" srcset="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan24_hu_e3b10b7ffd2767f4.jpeg 800w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan24_hu_5de77816c28932a2.jpeg 1600w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan24.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;自分が濡れないのを良いことに、&lt;br&gt;
完全に調子に乗っている。&lt;/p&gt;
&lt;p&gt;今の家に来てからあまりお風呂に入れてないので、&lt;br&gt;
水が出る場所ということもわかってないのかもしれない😂&lt;/p&gt;
&lt;p&gt;&lt;img alt="我が物顔" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan25.jpeg" srcset="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan25_hu_f27c0bdd1a8804ac.jpeg 800w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan25_hu_e8ec81f54d964598.jpeg 1600w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan25.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;夏も近いし、久しぶりにシャンプーしちゃおうかしら&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="そこは寝床じゃないよ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan26.jpeg" srcset="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan26_hu_696499671178c385.jpeg 800w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan26_hu_fd8c54b1faccb4ec.jpeg 1600w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan26.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="カリカリマシーン"&gt;カリカリマシーン
&lt;/h3&gt;&lt;p&gt;今まで4年くらい使っていた&lt;a class="link" href="https://petelect.jp/shop/products/detail/11" target="_blank" rel="noopener"
 &gt;カリカリマシーンSP&lt;/a&gt;がついにお亡くなりになってしまったので、&lt;br&gt;
久しぶりに自動給餌器を買い換えることにした。&lt;/p&gt;
&lt;p&gt;最近はいろんなメーカーのものが出ているが、&lt;br&gt;
結局今まで使っていたメーカーの最新機種を購入。&lt;br&gt;
&lt;a class="link" href="https://petelect.jp/shop/products/detail/62" target="_blank" rel="noopener"
 &gt;カリカリマシーンV2C&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="興味津々" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan31.jpeg" srcset="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan31_hu_c4d46e783f4d1703.jpeg 800w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan31_hu_8ef9faefe53e5f39.jpeg 1600w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan31.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;これが数年でかなり進化していて、&lt;br&gt;
タンクの密閉度が上がり、乾燥剤用のポケットが内側についたのがめちゃめちゃ嬉しい。&lt;/p&gt;
&lt;p&gt;今まではタンクの内側にテープで無理やり乾燥剤を取り付けたり、&lt;br&gt;
タンクをラップで塞いで蓋に本を乗せたりと苦しい湿気対策をしていたが、&lt;br&gt;
これで梅雨の時期にそとちゃんが&lt;a class="link" href="https://blog.uzimihsr.com/post/2022-07-22-sotochan/#%E3%82%AB%E3%83%AA%E3%82%AB%E3%83%AA%E9%A3%9F%E3%81%B9%E3%81%AA%E3%81%84" target="_blank" rel="noopener"
 &gt;カリカリ食べない問題&lt;/a&gt;が解決するかも&amp;hellip;?&lt;/p&gt;
&lt;p&gt;あとはいきなり機械が変わってそとちゃんがびっくりするかとも思ったが、&lt;br&gt;
特に気にせず普通に食べてくれたのでよかった。&lt;br&gt;
こういう図太いところは本当に手がかからなくて助かる&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="カメラの画角が広くなってトレーまで見えたり暗視カメラになったのもアツい" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="1116" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan32.PNG" srcset="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan32_hu_e8e2304cf01f7c19.PNG 800w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan32_hu_be58bd6ff1c3379a.PNG 1600w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan32.PNG 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;これでカリカリいっぱい食べてくれ〜🙏🙏🙏&lt;/p&gt;
&lt;p&gt;&lt;img alt="気に入ってくれたらうれしい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan33.jpeg" srcset="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan33_hu_f40d6df935fcf155.jpeg 800w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan33_hu_8fc2362c73bf5c4a.jpeg 1600w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan33.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;そとちゃんが8さい(推定)になった。&lt;/p&gt;
&lt;p&gt;たぶん3さいでうちにお迎えしたので、&lt;br&gt;
これでもう5年一緒に暮らしていることになる。&lt;/p&gt;
&lt;p&gt;そとちゃんはどう思ってるかわからないが、&lt;br&gt;
俺は毎日一緒にいられて楽しく幸せに過ごしているので、あっという間の5年間だった。&lt;/p&gt;
&lt;p&gt;ここまで大きな病気もなく、まだまだうるさいくらいに元気だけど、&lt;br&gt;
シニアねこであることには違いないのでこれまでよりも一層健康には気をつけていきたい。&lt;/p&gt;
&lt;p&gt;&lt;span style="color:silver"&gt;そとちゃんの猫生なのであまり無理強いするつもりはないんだけど、&lt;br&gt;
個人的には30さいのおばあにゃんになるまで元気でいてほしい&amp;hellip;👵🐈&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;まずは元気な9さいを目指してがんばろう。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="今年のベストショット" class="gallery-image" data-flex-basis="359px" data-flex-grow="149" height="1323" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan.JPG" srcset="https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan_hu_ef846a5d04875239.JPG 800w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan_hu_c3f56088a69262aa.JPG 1600w, https://blog.uzimihsr.com/post/2024-06-06-sotochan/sotochan.JPG 1984w" width="1984"&gt;&lt;/p&gt;
&lt;script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-6776523357552572"
 crossorigin="anonymous"&gt;&lt;/script&gt;
&lt;!-- displayads01 --&gt;
&lt;p&gt;&lt;ins class="adsbygoogle"
style="display:block"
data-ad-client="ca-pub-6776523357552572"
data-ad-slot="7322038275"
data-ad-format="auto"
data-full-width-responsive="true"&gt;&lt;/ins&gt;&lt;/p&gt;
&lt;script&gt;
 (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;</description></item><item><title>4月のそとちゃん(2024)</title><link>https://blog.uzimihsr.com/post/2024-05-02-sotochan/</link><pubDate>Thu, 02 May 2024 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2024-05-02-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan.jpeg" alt="Featured image of post 4月のそとちゃん(2024)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;h3 id="右目"&gt;右目
&lt;/h3&gt;&lt;p&gt;冬の間調子が良かったそとちゃんの右目。&lt;/p&gt;
&lt;p&gt;最近少し暖かくなってきて、&lt;br&gt;
また目ヤニがひどくなってしまった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="猫風邪の後遺症で涙腺が詰まっている" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan01_hu_f3eddd03053d7c2.jpeg 800w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan01_hu_f1737526159ae37c.jpeg 1600w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;こまめに専用のウェットシートで拭いているのだが、&lt;br&gt;
これがそとちゃんは気に入らない。&lt;br&gt;
(昔は嫌がらず拭かせてくれたのに&amp;hellip;)&lt;/p&gt;
&lt;p&gt;&lt;img alt="最近はシートを見ただけで逃げる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan02_hu_cc861afde46ac416.jpeg 800w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan02_hu_f27d63caf54f7355.jpeg 1600w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;とはいえ目ヤニを放置するわけにもいかないのでなんとか耐えてもらう。&lt;/p&gt;
&lt;p&gt;毛の根元にこびりついた目ヤニがなかなか取れないのだが、&lt;br&gt;
強く拭くと肌がすぐ赤くなってしまうので、これがとても難しい&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="強く拭くといたそう" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan03_hu_1bb644f4325c6ce9.jpeg 800w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan03_hu_3f53242a1559742d.jpeg 1600w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan03.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;月末ごろから少し目ヤニが収まってきてまたいい感じなので、&lt;br&gt;
どうにかこの調子が続くとそとちゃんも俺も助かる。&lt;/p&gt;
&lt;p&gt;毎年梅雨の時期が一番ひどいので、そうならないことを祈りたい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ちょっとマシになった" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan04_hu_29d9cb5fe6d03ec7.jpeg 800w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan04_hu_3e7c21b6df29426a.jpeg 1600w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="箱"&gt;箱
&lt;/h3&gt;&lt;p&gt;3月に通販でいろいろ買う機会があり、&lt;br&gt;
久しぶりにそれなりの大きさの段ボールが手に入った。&lt;/p&gt;
&lt;p&gt;袋派なはずのそとちゃん、意外にもこれに食いついた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="いいらしい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan05_hu_d6e69ca6d882d671.jpeg 800w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan05_hu_fd8151eba33673f9.jpeg 1600w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan05.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;このごろ部屋に箱を置いてなかったので珍しいのかもしれない。&lt;/p&gt;
&lt;p&gt;&lt;img alt="おもちゃが入ってるのがいい感じ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan06_hu_a5d44965d022e87d.jpeg 800w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan06_hu_34b846de53ea1b07.jpeg 1600w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan06.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;よく入ってガサゴソしている。&lt;/p&gt;
&lt;p&gt;&lt;img alt="夢中" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan07_hu_deddfd3ba0363d43.jpeg 800w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan07_hu_9d942ca4bfc83d08.jpeg 1600w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan07.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;だいぶ箱が好きになったのか、&lt;br&gt;
ねこ用ではない(ねこ用段ボールとは?)箱をたまたま放置していたらそれにも入ってくれた。&lt;/p&gt;
&lt;p&gt;かわいい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ちょっと小さいけど" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan08_hu_6f71c6784143b1e5.jpeg 800w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan08_hu_2465a37f627fbe67.jpeg 1600w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan08.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&amp;hellip;&lt;br&gt;
放置していた袋(これもねこ用ではない)にも入ってくれた。&lt;/p&gt;
&lt;p&gt;かわいいね。&lt;/p&gt;
&lt;p&gt;&lt;img alt="やっぱり袋も好き" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan09.jpeg" srcset="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan09_hu_ae2ffd4731da7c2d.jpeg 800w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan09_hu_917ff45b27936a73.jpeg 1600w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan09.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="ユニフォーム"&gt;ユニフォーム
&lt;/h3&gt;&lt;p&gt;我が千葉ロッテマリーンズに&lt;a class="link" href="https://w.wiki/9x6E" target="_blank" rel="noopener"
 &gt;ソト&lt;/a&gt;選手が入団した。&lt;/p&gt;
&lt;p&gt;&lt;img alt="目指せホームラン王" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan10.jpeg" srcset="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan10_hu_749734fb66123105.jpeg 800w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan10_hu_b8a0142dc9c7db8e.jpeg 1600w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan10.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;それだけ。&lt;/p&gt;
&lt;p&gt;&lt;img alt="MARINES IS YOU!(千葉の方言で「ようこそ」の意味)" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan11.jpeg" srcset="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan11_hu_55e47242a104c36f.jpeg 800w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan11_hu_6caab4d16bf0c87f.jpeg 1600w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan11.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="こたつ"&gt;こたつ
&lt;/h3&gt;&lt;p&gt;4月は新生活の時期ということで、&lt;br&gt;
出しっぱなしだったこたつ布団を撤去することにした。&lt;/p&gt;
&lt;p&gt;&lt;img alt="この冬はあんまり入らなかったが…" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan12.jpeg" srcset="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan12_hu_f9f1579a47073406.jpeg 800w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan12_hu_89bdce38e9233fed.jpeg 1600w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan12.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;正直この冬はエアコンを多用していてあまり電源を入れなかったので、&lt;br&gt;
そとちゃんもあっさり受け入れてくれるかと思ったが&amp;hellip;&lt;/p&gt;
&lt;p&gt;そこはねこが相手なので、思い通りにはいかない。&lt;br&gt;
&lt;a class="link" href="https://blog.uzimihsr.com/post/2023-12-31-sotochan/" target="_blank" rel="noopener"
 &gt;湯たんぽ&lt;/a&gt;を入れた時以外入ってなかったくせに&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="急に抵抗し始める" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan13.jpeg" srcset="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan13_hu_82a1a44b54d19e1c.jpeg 800w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan13_hu_4fb1d385e0894bcc.jpeg 1600w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan13.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;十数分の説得(※物理含む)の末、&lt;br&gt;
布団の撤去に成功。&lt;/p&gt;
&lt;p&gt;&lt;img alt="机にしがみついて抵抗する住民(うそです)" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan14.jpeg" srcset="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan14_hu_9a8f2eb1cca19364.jpeg 800w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan14_hu_bd2c5bd5e5dab869.jpeg 1600w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan14.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="なくなった" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan15.jpeg" srcset="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan15_hu_aa10210d8e39ed4e.jpeg 800w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan15_hu_6452023db6a54e13.jpeg 1600w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan15.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;部屋はだいぶスッキリしたが、&lt;br&gt;
そとちゃんはちょっといじけてしまった。&lt;/p&gt;
&lt;p&gt;外した布団に恨めしそうに乗る姿がなんとも言えない。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ごめんって" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan16.jpeg" srcset="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan16_hu_6cea74c04b10982.jpeg 800w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan16_hu_3ddaa6585010b0c6.jpeg 1600w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan16.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;湯たんぽは残すので、どうにか機嫌を治してほしいところ&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="くっついててかわいい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan17.jpeg" srcset="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan17_hu_ac61cc68d8e368d3.jpeg 800w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan17_hu_3088a70a06c8a9e4.jpeg 1600w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan17.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;ねこにとってかなしい出来事はちょこちょこあったが、4月もそとちゃんは楽しそうだった。&lt;br&gt;
多少嫌なことがあっても自分ですぐ機嫌を治せてえらいな〜〜！&lt;/p&gt;
&lt;p&gt;5月には誕生日(元野良なので推測)が来るが、変わらず元気で楽しく過ごしてほしい。&lt;br&gt;
(これを書いてる時点ではもう8歳になりました)&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="あったかくなってきてごきげんなねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan_hu_9a5d141bab97dd89.jpeg 800w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan_hu_db6170277ef695e0.jpeg 1600w, https://blog.uzimihsr.com/post/2024-05-02-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-6776523357552572"
 crossorigin="anonymous"&gt;&lt;/script&gt;
&lt;!-- displayads01 --&gt;
&lt;p&gt;&lt;ins class="adsbygoogle"
style="display:block"
data-ad-client="ca-pub-6776523357552572"
data-ad-slot="7322038275"
data-ad-format="auto"
data-full-width-responsive="true"&gt;&lt;/ins&gt;&lt;/p&gt;
&lt;script&gt;
 (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;</description></item><item><title>3月のそとちゃん(2024)</title><link>https://blog.uzimihsr.com/post/2024-04-19-sotochan/</link><pubDate>Fri, 19 Apr 2024 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2024-04-19-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan.jpeg" alt="Featured image of post 3月のそとちゃん(2024)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;h3 id="いたずら"&gt;いたずら
&lt;/h3&gt;&lt;p&gt;そとちゃんがまた仕事机に登るようになってしまった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="キーボードは押しっぱなし" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan01_hu_3e636a01de1c8e6d.jpeg 800w, https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan01_hu_bfd1f2753a4d46a9.jpeg 1600w, https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan01_hu_d182a85be49dee6e.jpeg 2400w, https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan01.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;ここ数年はパソコンの邪魔をすることもあまりなかったのに、&lt;br&gt;
何がきっかけかわからないけど最近になってまたいたずら三昧。&lt;/p&gt;
&lt;p&gt;&lt;img alt="イヤホン落としのプロ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan06_hu_32176b6c6c8394e4.jpeg 800w, https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan06_hu_5c0fa0edafec0e79.jpeg 1600w, https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan06_hu_6afcc3901bedc66f.jpeg 2400w, https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan06.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;マウスやイヤホン、紙類をちょいちょいいじるのが楽しくてしょうがない。&lt;br&gt;
かわいいおててでしっかり床に落とす。&lt;/p&gt;
&lt;p&gt;&lt;img alt="小物を奥に叩き落として大満足" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan02_hu_c724c3cd8bb68833.jpeg 800w, https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan02_hu_5e230ba5619ee3bc.jpeg 1600w, https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan02_hu_dd6c4369cdd96983.jpeg 2400w, https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan02.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;仕事中にも乗ってくるのですごい迷惑。&lt;br&gt;
降ろしてもめげずにまた登ってくる。&lt;/p&gt;
&lt;p&gt;&lt;img alt="褒めてないです" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan03_hu_860b391ae9f128b9.jpeg 800w, https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan03_hu_c056ba8dfef5c6d3.jpeg 1600w, https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan03_hu_b018bec8cd3a69b2.jpeg 2400w, https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan03.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;こまった&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="悪いことをしている自覚すらない" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan04_hu_2757c77c42a1c677.jpeg 800w, https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan04_hu_b414f1859996af00.jpeg 1600w, https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan04_hu_133dcaddf006480.jpeg 2400w, https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan04.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;h3 id="爆鳴き"&gt;爆鳴き
&lt;/h3&gt;&lt;p&gt;最近のそとちゃんは机の上に登るだけじゃなくて、めちゃめちゃ鳴く。&lt;br&gt;
とてもうるさい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="下駄箱の中で鳴くとけっこう響く" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan05_hu_60199aef2804a5b1.jpeg 800w, https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan05_hu_e4d4b6530713ec4e.jpeg 1600w, https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan05_hu_7477dbdb5c67151b.jpeg 2400w, https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan05.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;特徴的なのが、わざわざ俺から離れたところで爆鳴きすること。&lt;br&gt;
仕方ないので席を立って撫でにいくとすごい満足そうにして、&lt;br&gt;
また離れた場所に移動して再度爆鳴きする。&lt;br&gt;
すごいかまってちゃん。&lt;/p&gt;
&lt;p&gt;&lt;img alt="玄関で爆鳴き" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan07_hu_aac94ea072728827.jpeg 800w, https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan07_hu_92d714fd57f44dc9.jpeg 1600w, https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan07_hu_d6417bc649660fb1.jpeg 2400w, https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan07.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;疲れれば大人しくなると思っておもちゃを投げてもあんまり遊んでくれない。&lt;br&gt;
本当にこっちの気を引きたいだけらしい&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="かまうとそれはそれで塩対応" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan08_hu_22985668d474ec67.jpeg 800w, https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan08_hu_d82efe644ccd199e.jpeg 1600w, https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan08_hu_71056a4dbfc18392.jpeg 2400w, https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan08.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;あとは仕事で通話してるときにすごく積極的に発言する。&lt;br&gt;
たまに研修用の動画にも反応するので、たぶん人間の声に反応するのが好きなんだと思う。&lt;/p&gt;
&lt;p&gt;&lt;img alt="キャットタワーの上からビデオ会議にリモート参加する" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan09.jpeg" srcset="https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan09_hu_50ddc21d04e453b1.jpeg 800w, https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan09_hu_456f5372aa5ea795.jpeg 1600w, https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan09_hu_57f8b72edc375795.jpeg 2400w, https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan09.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;元気なのは良いことだけど、&lt;br&gt;
仕事中はもうすこしちゃんとお昼寝してくれると助かるなあ&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="昼間も元気いっぱい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan10.jpeg" srcset="https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan10_hu_c7b582636f8bbe23.jpeg 800w, https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan10_hu_47a2c444df2ee725.jpeg 1600w, https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan10_hu_b05772e57819b6e5.jpeg 2400w, https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan10.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;そとちゃんは相変わらず元気いっぱい。&lt;/p&gt;
&lt;p&gt;というか年々わんぱくになってるような気がする。&lt;/p&gt;
&lt;p&gt;今年で推定8歳になるはずなんですが、シニアねことは&amp;hellip;?&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="ゆたんぽとくっついて寝るねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan_hu_464042bb10afaa80.jpeg 800w, https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan_hu_6365663985dc44ed.jpeg 1600w, https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan_hu_14cc5c5ebb5c710c.jpeg 2400w, https://blog.uzimihsr.com/post/2024-04-19-sotochan/sotochan.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-6776523357552572"
 crossorigin="anonymous"&gt;&lt;/script&gt;
&lt;!-- displayads01 --&gt;
&lt;p&gt;&lt;ins class="adsbygoogle"
style="display:block"
data-ad-client="ca-pub-6776523357552572"
data-ad-slot="7322038275"
data-ad-format="auto"
data-full-width-responsive="true"&gt;&lt;/ins&gt;&lt;/p&gt;
&lt;script&gt;
 (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;</description></item><item><title>2月のそとちゃん(2024)</title><link>https://blog.uzimihsr.com/post/2024-03-19-sotochan/</link><pubDate>Tue, 19 Mar 2024 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2024-03-19-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan.jpeg" alt="Featured image of post 2月のそとちゃん(2024)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;h3 id="見張り"&gt;見張り
&lt;/h3&gt;&lt;p&gt;2月は窓につけてあるねこ用ハンモックがそとちゃんのお気に入りだった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="とくいげ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan01_hu_b025d277f445d34b.jpeg 800w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan01_hu_60b8a841e2a471a7.jpeg 1600w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;ここにはそとちゃんが好きなブランケットを敷いているので、&lt;br&gt;
寒い日でも全然平気らしい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="乗ってる間は機嫌が良い" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan02_hu_1e30c2c69a8a178f.jpeg 800w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan02_hu_ca1888f3e72e10de.jpeg 1600w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;ブランケットだけでなく、&lt;br&gt;
もちろん外の景色を見るのも大好き。&lt;/p&gt;
&lt;p&gt;&lt;img alt="太陽出待ち" class="gallery-image" data-flex-basis="319px" data-flex-grow="133" height="1654" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan03_hu_cc770830ff39be90.jpeg 800w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan03_hu_88877844700961cb.jpeg 1600w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan03.jpeg 2205w" width="2205"&gt;&lt;/p&gt;
&lt;p&gt;毎朝欠かさず、日が登るのを監視している。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ねむい" class="gallery-image" data-flex-basis="319px" data-flex-grow="133" height="1654" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan04_hu_180df24a6dba5ce7.jpeg 800w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan04_hu_aaf2f0bf787a9c33.jpeg 1600w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan04.jpeg 2205w" width="2205"&gt;&lt;/p&gt;
&lt;p&gt;毎朝欠かさず。&lt;/p&gt;
&lt;p&gt;それはすなわち、寝ている俺を毎朝踏み台にしているということ。&lt;br&gt;
ベッドとハンモックの間は別に自力で跳べる高さのはずなのに、&lt;br&gt;
わざわざ寝ている俺の腹の上に乗ってからジャンプして登っている。&lt;/p&gt;
&lt;p&gt;&lt;img alt="抗議は受け付けない" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan05_hu_700130e53b8dd03c.jpeg 800w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan05_hu_ee44539fe7a2a259.jpeg 1600w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan05.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;体重4kgしかないそとちゃんとはいえ、&lt;br&gt;
たった数cm程度の足で全体重をかけて踏み切られると結構重いし痛い。&lt;/p&gt;
&lt;p&gt;&lt;img alt="そんなことより外が気になる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan06_hu_3440f1d4e65dfb18.jpeg 800w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan06_hu_bde27c66c4e7ea28.jpeg 1600w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan06.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;踏み台にするだけならまだしも、&lt;br&gt;
降りるときも最近は躊躇なく俺の腹に着地してくる。&lt;br&gt;
昔はそんなひどいことしなかったのにどうして&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="腹の上とハンモックを往復しがち" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan07_hu_b72725f9eb8f4133.jpeg 800w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan07_hu_ca78efdd4c5788b1.jpeg 1600w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan07.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;もう一個低いハンモック買おうかな&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="ねてる" class="gallery-image" data-flex-basis="319px" data-flex-grow="133" height="1654" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan08_hu_b7caff2cf1c86af6.jpeg 800w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan08_hu_bd042e574143b293.jpeg 1600w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan08.jpeg 2205w" width="2205"&gt;&lt;/p&gt;
&lt;h3 id="しろたん"&gt;しろたん
&lt;/h3&gt;&lt;p&gt;そとちゃんが一番すきな寝床は、本棚の上のしろたん。&lt;br&gt;
夜中に寝床を移動することはあるが、だいたい最初はここで眠りについて朝もここで眼を覚ます。&lt;/p&gt;
&lt;p&gt;&lt;img alt="おちつく" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan09.jpeg" srcset="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan09_hu_670bdb6138551d5e.jpeg 800w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan09_hu_7db1a990ce282805.jpeg 1600w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan09.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;が、このしろたんもだいぶ汚れてきていて、&lt;br&gt;
色もグレーになり、なによりも毛だらけ&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="きたない" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan10.jpeg" srcset="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan10_hu_8ca5d55b37d8217f.jpeg 800w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan10_hu_ad2fafe573482405.jpeg 1600w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan10.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;というわけで久しぶりにしろたんを洗うことにした。&lt;/p&gt;
&lt;p&gt;&lt;img alt="拒否" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan11.jpeg" srcset="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan11_hu_d6d004b0975c9db1.jpeg 800w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan11_hu_837b398ce0930b31.jpeg 1600w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan11.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;決死の説得も虚しく武力衝突が起こってしまったが、&lt;br&gt;
なんとか汚れたしろたんを回収。&lt;/p&gt;
&lt;p&gt;&lt;img alt="徹底抗戦するねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan12.jpeg" srcset="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan12_hu_6a9c6e5de5d21067.jpeg 800w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan12_hu_556dd20ea9f10569.jpeg 1600w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan12.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;抱きぐるみを洗うといっても着脱式なので、&lt;br&gt;
カバーを外して洗濯機で回すだけで綺麗になった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="だいぶ白くなった" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan13.jpeg" srcset="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan13_hu_3754d18df940356.jpeg 800w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan13_hu_bfef88db542c331d.jpeg 1600w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan13.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;ここで(予想通り？)問題が発生。&lt;/p&gt;
&lt;p&gt;そとちゃん7歳(ねこ)、多感なお年頃、洗われたしろたんが気に食わない&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="近づきはするけど登らない" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan14.jpeg" srcset="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan14_hu_aa9261c19961bf49.jpeg 800w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan14_hu_1248a326947b2511.jpeg 1600w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan14.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;勝手に洗われたことに怒っているのか、自分の匂いが消えて不安なのか、&lt;br&gt;
全然使ってくれなくなってしまった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="いじけてる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan15.jpeg" srcset="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan15_hu_e246ad92d9b7dea9.jpeg 800w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan15_hu_af3e1f0ee84fd2e7.jpeg 1600w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan15.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;これまで引っ越しや病院でもすぐに新しい環境に適応し、&lt;br&gt;
ねこらしからぬ度胸を見せていたそとちゃんがここまで露骨に落ち込むのを見るとかわいそうになってくる。&lt;/p&gt;
&lt;p&gt;&lt;img alt="キャットタワーの小部屋に避難(？)" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan16.jpeg" srcset="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan16_hu_87fc4e4e100fcce9.jpeg 800w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan16_hu_e1a2e84b5ea5a6b7.jpeg 1600w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan16.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;それでもいつまでも乗らないと匂いもつかないので、&lt;br&gt;
何回か抱っこして無理やり乗せてみた。&lt;br&gt;
が、ダメ&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="「ちょっとちがう」" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan17.jpeg" srcset="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan17_hu_e2c360a59df68a21.jpeg 800w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan17_hu_cc02bee666693fef.jpeg 1600w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan17.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;と思ったらあれ？&lt;br&gt;
ある日気づくとあっさり寝ていた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="普通に寝てた" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan18.jpeg" srcset="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan18_hu_e52e1ca5304f73cb.jpeg 800w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan18_hu_10386fdfc40cc7.jpeg 1600w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan18.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;いったいなにがきっかけで気に入ったのか&amp;hellip;?&lt;br&gt;
よくわからないけど使ってくれてよかった。&lt;/p&gt;
&lt;p&gt;とはいえ今回あまりにもかわいそうだったので、今後はもう洗わないかな&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="スヤスヤ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan19.jpeg" srcset="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan19_hu_9cd586107fe8d014.jpeg 800w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan19_hu_92b6c19c6ae4a929.jpeg 1600w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan19.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;ちょっと身の回りでいろいろあってクッソ遅筆になってしまった。&lt;/p&gt;
&lt;p&gt;次回こそは&amp;hellip;&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="ハンモックで寝落ちするねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan_hu_a05ba4b3819c69f4.jpeg 800w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan_hu_c545ee8e2b3ae089.jpeg 1600w, https://blog.uzimihsr.com/post/2024-03-19-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>SSWAを受験した</title><link>https://blog.uzimihsr.com/post/2024-02-23-sswa/</link><pubDate>Fri, 23 Feb 2024 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2024-02-23-sswa/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2024-02-23-sswa/sotochan.jpeg" alt="Featured image of post SSWAを受験した" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;最強の資格SSWAを受験した。その体験記。&lt;/p&gt;
&lt;h3 id="sswaとは"&gt;SSWAとは
&lt;/h3&gt;&lt;p&gt;IT系のエンジニアとして働く上で資格いるいらない論争はたまによくある。&lt;/p&gt;
&lt;p&gt;「資格なんて要らん！実務での経験が重要だ！」という方は多いだろうし、&lt;br&gt;
履歴書盛るために資格だけやたらと持ってる未経験者、みたいなのは自分も「？」と思うことはあるが、&lt;br&gt;
「最低限の学習意欲の証明にはなるので無いよりはマシ、ただし持ってるから偉いということはない。」&lt;br&gt;
くらいに考えている。&lt;/p&gt;
&lt;p&gt;実際自分もいくつか&lt;a class="link" href="https://blog.uzimihsr.com/post/2021-09-14-cka/" target="_blank" rel="noopener"
 &gt;資格は持っている&lt;/a&gt;し、&lt;br&gt;
雰囲気で触っていたものについて体系的に学び直せることはメリットが多いと思うので、&lt;br&gt;
年に数回ほど新しいものを取得している。&lt;/p&gt;
&lt;p&gt;そこで重要になってくるのが「どの資格を選ぶのか」だと思う。&lt;br&gt;
I○A, ○isco, Ora○le, AW○, CN○F, etc&amp;hellip;&lt;br&gt;
世の中にはたくさんの資格がある。でも人生の時間は限られている。&lt;br&gt;
学ぶなら&lt;strong&gt;自分にとって本当に価値のある資格&lt;/strong&gt;を選ぶべきだ。&lt;/p&gt;
&lt;p&gt;&lt;img alt="世の中にあるたくさんのすばらしい資格たち" class="gallery-image" data-flex-basis="407px" data-flex-grow="169" height="433" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-23-sswa/vendors.png" width="735"&gt;&lt;/p&gt;
&lt;p&gt;そんな中で今回私が選んだのが、&lt;strong&gt;SSWA(Sauna Spa Wellness Advisor)&lt;/strong&gt; だ。&lt;/p&gt;
&lt;p&gt;SSWA&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;とはJSSA(Japan Sauna Spa Association)&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;が認定している、&lt;br&gt;
サウナやスパに関する正しい知識の活用を目的とした温浴施設の従業員や利用者向けの資格である。&lt;br&gt;
つまり俺みたいな&lt;strong&gt;サウナ好きのおっさんのための最強の資格&lt;/strong&gt;だ。&lt;br&gt;
なんとあの厚生労働省が支援しているらしい。&lt;br&gt;
&lt;del&gt;(支援って具体的に何？？)&lt;/del&gt;&lt;/p&gt;
&lt;p&gt;今回はその受験記である。&lt;/p&gt;
&lt;p&gt;&lt;del&gt;金さえ払えば取れるガバ資格&lt;/del&gt;とか&lt;del&gt;怪しい利権団体&lt;/del&gt;とか言うやつは俺がぶっとばす。&lt;/p&gt;
&lt;p&gt;(技術要素は)ないです&lt;/p&gt;
&lt;h3 id="受験申し込み"&gt;受験申し込み
&lt;/h3&gt;&lt;p&gt;どんな資格も受験の申し込みをしないと始まらない。&lt;/p&gt;
&lt;p&gt;まずは&lt;a class="link" href="https://www.sauna.or.jp/adviser/" target="_blank" rel="noopener"
 &gt;公式サイト&lt;/a&gt;にアクセスする。&lt;/p&gt;
&lt;p&gt;&lt;img alt="引用元: https://www.sauna.or.jp/adviser/" class="gallery-image" data-flex-basis="142px" data-flex-grow="59" height="1283" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-23-sswa/sc01.png" width="762"&gt;&lt;/p&gt;
&lt;p&gt;なんと安心感のあるWebページだろうか。&lt;br&gt;
スクリプトは必要最小限、適度なイラストと必要な説明だけが記載されておりとても美しい。&lt;br&gt;
テキストの内容を&lt;a class="link" href="https://www.sauna.or.jp/adviser/images/WA_text.pdf" target="_blank" rel="noopener"
 &gt;チラ見&lt;/a&gt;することもできる。&lt;br&gt;
俺こういうの大好き。&lt;/p&gt;
&lt;p&gt;ちなみにこのページ、なんと英語対応もされている。&lt;br&gt;
画面右上の&lt;code&gt;English&lt;/code&gt;をクリックすると&lt;a class="link" href="https://www.sauna.or.jp/english/English.html" target="_blank" rel="noopener"
 &gt;英語版ページ&lt;/a&gt;が表示される。&lt;/p&gt;
&lt;p&gt;&lt;img alt="引用元: https://www.sauna.or.jp/english/English.html" class="gallery-image" data-flex-basis="375px" data-flex-grow="156" height="1013" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-23-sswa/sc02.png" srcset="https://blog.uzimihsr.com/post/2024-02-23-sswa/sc02_hu_8c17805878e78a43.png 800w, https://blog.uzimihsr.com/post/2024-02-23-sswa/sc02.png 1583w" width="1583"&gt;&lt;/p&gt;
&lt;p&gt;英語版はHTMLほぼ直書きの漢らしいページだ。&lt;br&gt;
&lt;strong&gt;こういうのでいいんだよ。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;余談はこれくらいにして、&lt;br&gt;
受験の申し込みは&lt;a class="link" href="https://www.sauna.or.jp/adviser/" target="_blank" rel="noopener"
 &gt;公式サイト&lt;/a&gt;下部の&lt;a class="link" href="https://www.sauna.or.jp/adviser/contact_form/index.html" target="_blank" rel="noopener"
 &gt;お申込みフォーム&lt;/a&gt;から行える。&lt;br&gt;
リンク先のフォームで下記の項目を入力して送信するだけで手続きは完了だ。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;名前(ふりがな)&lt;/li&gt;
&lt;li&gt;住所&lt;/li&gt;
&lt;li&gt;電話番号&lt;/li&gt;
&lt;li&gt;メールアドレス&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="申し込み完了画面" class="gallery-image" data-flex-basis="211px" data-flex-grow="88" height="684" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-23-sswa/sc03.jpeg" width="602"&gt;&lt;/p&gt;
&lt;p&gt;そう。&lt;br&gt;
&lt;strong&gt;クレジットカードを登録する必要がないのである。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;ではどうやって受験料を支払うのだろうか？&lt;/p&gt;
&lt;p&gt;&lt;img alt="確認メール" class="gallery-image" data-flex-basis="214px" data-flex-grow="89" height="785" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-23-sswa/sc04.png" width="703"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;代引きである。&lt;/strong&gt;&lt;br&gt;
この令和の時代に代引き。&lt;br&gt;
万が一のサイバー攻撃にも備えてクレカ情報を自社側で持たないようにするセキュリティ意識の高さが伺える。&lt;/p&gt;
&lt;p&gt;ちなみに代引きの支払いにはクレジットカードが使える。便利。&lt;br&gt;
そういえば受験料は代引き手数料込みで5330円だった。&lt;br&gt;
&lt;strong&gt;受験料がアホみたいに高いベンダー系の試験に比べてなんとお手頃だろう。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;ただ、この代引きというのは厄介でもある。&lt;br&gt;
宅配ボックスは使えず、支払いのために直接受け取らないといけないのだから不便だ。&lt;/p&gt;
&lt;p&gt;俺の場合は幸運なことに在宅勤務なので無事に一発で受け取れたが、&lt;br&gt;
特に1人暮らしで毎日出勤する社会人の場合はこの受け取りこそが&lt;strong&gt;本資格で最も難しい問題&lt;/strong&gt;だと言えよう。&lt;/p&gt;
&lt;p&gt;今回は申し込みから5日くらいで封筒が届いた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="本当に届いた" class="gallery-image" data-flex-basis="407px" data-flex-grow="169" height="603" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-23-sswa/photo01.jpeg" srcset="https://blog.uzimihsr.com/post/2024-02-23-sswa/photo01_hu_476148571c2ce154.jpeg 800w, https://blog.uzimihsr.com/post/2024-02-23-sswa/photo01.jpeg 1024w" width="1024"&gt;&lt;/p&gt;
&lt;p&gt;中身はこんな感じ。&lt;/p&gt;
&lt;p&gt;&lt;img alt="テキストと問題、返信用の封筒" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="768" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-23-sswa/photo02.jpeg" srcset="https://blog.uzimihsr.com/post/2024-02-23-sswa/photo02_hu_a8c371039867178a.jpeg 800w, https://blog.uzimihsr.com/post/2024-02-23-sswa/photo02.jpeg 1024w" width="1024"&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;公式テキスト&lt;/li&gt;
&lt;li&gt;試験問題&lt;/li&gt;
&lt;li&gt;返信封筒&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ここで気になるのが返信封筒。&lt;br&gt;
宛先の&lt;a class="link" href="https://www.chintai-jimusho.com/item/100974/" target="_blank" rel="noopener"
 &gt;物件情報&lt;/a&gt;をみると築39年のオフィスビル、約10坪ほどの事務所で運営されているらしい。&lt;br&gt;
それほど人数の多い団体ではなさそうだ。&lt;br&gt;
&lt;del&gt;怪しい利権団体&lt;/del&gt;とか言うやつは俺がぶっとばす。&lt;/p&gt;
&lt;h3 id="試験対策"&gt;試験対策
&lt;/h3&gt;&lt;p&gt;SSWA試験の流れとしては&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;テキストを読む&lt;/li&gt;
&lt;li&gt;試験問題を解く(制限時間60分)&lt;/li&gt;
&lt;li&gt;回答用紙を記入して郵送&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;というかんじ。&lt;/p&gt;
&lt;p&gt;驚いたのは試験官など監視の仕組みがないこと。&lt;br&gt;
これではカンニングし放題、制限時間破り放題(?)ではないか。&lt;/p&gt;
&lt;p&gt;否。&lt;br&gt;
サウナを愛する人間は皆善人である。&lt;br&gt;
サウナを愛する人間がカンニングなどするはずがない。&lt;br&gt;
&lt;strong&gt;カンニングして合格するような人間にサウナを愛する資格はない。&lt;/strong&gt;&lt;br&gt;
JSSAはそう言うことが言いたいんだと思う。&lt;br&gt;
&lt;del&gt;金さえ払えば取れるガバ資格&lt;/del&gt;とか言うやつは俺がぶっとばす。&lt;/p&gt;
&lt;p&gt;というわけでテキストを真面目に読んでいく。&lt;/p&gt;
&lt;p&gt;&lt;img alt="全てはテキストにある" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="768" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-23-sswa/photo03.jpeg" srcset="https://blog.uzimihsr.com/post/2024-02-23-sswa/photo03_hu_15773707cee92467.jpeg 800w, https://blog.uzimihsr.com/post/2024-02-23-sswa/photo03.jpeg 1024w" width="1024"&gt;&lt;/p&gt;
&lt;p&gt;テキストはB5サイズ、63ページほどの冊子だ。&lt;br&gt;
内容は&lt;a class="link" href="https://www.sauna.or.jp/adviser/images/WA_text.pdf" target="_blank" rel="noopener"
 &gt;サンプル&lt;/a&gt;の通りで、&lt;br&gt;
三章構成となっている。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;第一章　サウナ・スパ健康法
&lt;ul&gt;
&lt;li&gt;お風呂、サウナの効果や健康に良い入り方、サウナの歴史など&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;第二章　サウナ・スパ後のボディケア
&lt;ul&gt;
&lt;li&gt;入浴後に効果的なマッサージなど&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;第三章　サウナ・スパ施設内での応急手当
&lt;ul&gt;
&lt;li&gt;サウナやお風呂で人が倒れた際の救急隊員に引き渡すまでの処置手順&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;第一章はとても勉強になる。この試験のメインテーマと言って良いだろう。&lt;br&gt;
入浴法の具体的な手順まで紹介されていてタメになる。&lt;/p&gt;
&lt;p&gt;第三章の心肺蘇生法などは自動車教習所で教わるものとほぼ同じなのであまり深く読む必要はなさそうだが、&lt;br&gt;
やけどや脳貧血など、サウナならではの症状に応じた手当の方法は勉強になる。&lt;/p&gt;
&lt;p&gt;一番難しいのは第二章、特にPart.2の「温まった体に効果的なツボ指圧 20選」である。&lt;br&gt;
東洋医学のツボの名前と効能が列挙されており、これを一発で全て覚えるのはとても大変だ。&lt;br&gt;
他の章の内容と比較してもおそらく試験で難しい問題があるとしたらこのパートの内容だろうと考え、&lt;br&gt;
自分の場合はここを3周した。&lt;/p&gt;
&lt;h3 id="試験"&gt;試験
&lt;/h3&gt;&lt;p&gt;1,2時間程度でテキストを読み終わったら早速試験問題に取り掛かる。&lt;/p&gt;
&lt;p&gt;公平性のために試験問題の内容全ては公開できないが、&lt;br&gt;
テキストの内容に関連する3択問題の合計25問で構成されている。&lt;/p&gt;
&lt;p&gt;&lt;img alt="回答用紙" class="gallery-image" data-flex-basis="180px" data-flex-grow="75" height="1024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-23-sswa/photo04.jpeg" width="768"&gt;&lt;/p&gt;
&lt;p&gt;テキストの指示に従い、60分タイマーをセット。&lt;br&gt;
バリバリ問題を解いていく。&lt;/p&gt;
&lt;p&gt;長らく味わってこなかった、エンピツで筆記問題を解く感覚。&lt;br&gt;
学生時代にはあまり好きではなかった暖かみのある作業が今はとても楽しい。&lt;/p&gt;
&lt;p&gt;問題の内容としてはテキストを読んでいれば正解がわかるものばかり。&lt;br&gt;
ただし意地悪というほどでもないが、漢字や数値が違うだけの選択肢などがあり、&lt;br&gt;
ケアレスミスには注意が必要である。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ちなみに自分がしっかり対策したツボの名前に関する問題は1つも出なかった。&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;試験問題を使い回しているとは到底考えづらいが、&lt;/strong&gt;&lt;br&gt;
ある回の試験で1問も出なかった、というのは今後の受験生の判断材料の1つになると思い書いておく。&lt;/p&gt;
&lt;p&gt;回答にかかった時間は&lt;strong&gt;5分。&lt;/strong&gt;&lt;br&gt;
制限時間60分とはなんだったのか。&lt;/p&gt;
&lt;p&gt;&lt;img alt="早く解けたからってイキっていいのは小学生までです" class="gallery-image" data-flex-basis="209px" data-flex-grow="87" height="1286" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-23-sswa/sc05.PNG" srcset="https://blog.uzimihsr.com/post/2024-02-23-sswa/sc05_hu_9fd47c85e76ff015.PNG 800w, https://blog.uzimihsr.com/post/2024-02-23-sswa/sc05.PNG 1125w" width="1125"&gt;&lt;/p&gt;
&lt;p&gt;あとは回答用紙を封筒に入れて投函して試験は終了。&lt;br&gt;
あらかじめ切手が貼ってあるのがありがたい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="受かりますように" class="gallery-image" data-flex-basis="179px" data-flex-grow="74" height="1890" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-23-sswa/photo05.jpeg" srcset="https://blog.uzimihsr.com/post/2024-02-23-sswa/photo05_hu_1aec4b7ca0572453.jpeg 800w, https://blog.uzimihsr.com/post/2024-02-23-sswa/photo05.jpeg 1417w" width="1417"&gt;&lt;/p&gt;
&lt;h3 id="結果"&gt;結果
&lt;/h3&gt;&lt;p&gt;テストセンター等で受けるIT系の試験とは異なり、&lt;br&gt;
合否がわかるまでにはかなりの時間がかかる。&lt;br&gt;
&lt;strong&gt;きっと厳正な審査、採点がされていることだろう。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;自分の場合は回答を投函してから10日ほどで何やら緑色の大きい封筒が届いた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="大きい封筒は緑保留くらいの信頼度" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-23-sswa/photo06.jpeg" srcset="https://blog.uzimihsr.com/post/2024-02-23-sswa/photo06_hu_e88f955e17817fa7.jpeg 800w, https://blog.uzimihsr.com/post/2024-02-23-sswa/photo06_hu_19cdaab2f1d360bb.jpeg 1600w, https://blog.uzimihsr.com/post/2024-02-23-sswa/photo06.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;結果は&amp;hellip;?&lt;/p&gt;
&lt;p&gt;&lt;img alt="🎉🎉🎉" class="gallery-image" data-flex-basis="198px" data-flex-grow="82" height="1027" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-23-sswa/SSWA_passed.png" srcset="https://blog.uzimihsr.com/post/2024-02-23-sswa/SSWA_passed_hu_23883d7097c9d6ca.png 800w, https://blog.uzimihsr.com/post/2024-02-23-sswa/SSWA_passed.png 850w" width="850"&gt;&lt;/p&gt;
&lt;p&gt;合格だった。&lt;/p&gt;
&lt;p&gt;合格のご褒美として以下のものを受領した。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;認定証&lt;/li&gt;
&lt;li&gt;資格カード&lt;/li&gt;
&lt;li&gt;ピンバッジ&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="認定証" class="gallery-image" data-flex-basis="169px" data-flex-grow="70" height="802" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-23-sswa/SSWA.png" width="567"&gt;&lt;/p&gt;
&lt;p&gt;認定証は卒業証書みたいな良さげな紙でできている。&lt;br&gt;
あんまりこういうのもらったことないからうれしい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="資格カード" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-23-sswa/photo09.jpeg" srcset="https://blog.uzimihsr.com/post/2024-02-23-sswa/photo09_hu_3902b14387f84dc5.jpeg 800w, https://blog.uzimihsr.com/post/2024-02-23-sswa/photo09_hu_891cd152a91da922.jpeg 1600w, https://blog.uzimihsr.com/post/2024-02-23-sswa/photo09.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;資格カードは免許証サイズ。&lt;br&gt;
こいつには後で重要な役割が待っている。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ピンバッジ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-23-sswa/photo07.jpeg" srcset="https://blog.uzimihsr.com/post/2024-02-23-sswa/photo07_hu_1025689cd68c5333.jpeg 800w, https://blog.uzimihsr.com/post/2024-02-23-sswa/photo07_hu_7dd1ac4a3b768954.jpeg 1600w, https://blog.uzimihsr.com/post/2024-02-23-sswa/photo07.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;ピンバッジ&amp;hellip;&lt;br&gt;
&lt;del&gt;これいる？&lt;/del&gt;&lt;/p&gt;
&lt;p&gt;ちなみに得点が何点だったかはわからないようになっていた。&lt;br&gt;
&lt;del&gt;金さえ払えば取れるテキトー採点のガバ資格&lt;/del&gt;とか言うやつは俺がぶっとばす。&lt;/p&gt;
&lt;h3 id="sswaのメリット"&gt;SSWAのメリット
&lt;/h3&gt;&lt;p&gt;このSSWA、合格して認定証をもらって終わりの資格ではない。&lt;br&gt;
なんと合格者は資格カードを見せると&lt;a class="link" href="https://www.sauna.or.jp/adviser/discount/index.html" target="_blank" rel="noopener"
 &gt;全国各地の協賛店で割引サービス&lt;/a&gt;が受けられるのだ。&lt;/p&gt;
&lt;p&gt;&lt;img alt="引用元: https://www.sauna.or.jp/adviser/discount/index.html" class="gallery-image" data-flex-basis="263px" data-flex-grow="109" height="1206" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-23-sswa/sc06.png" srcset="https://blog.uzimihsr.com/post/2024-02-23-sswa/sc06_hu_18fd03df0573e946.png 800w, https://blog.uzimihsr.com/post/2024-02-23-sswa/sc06.png 1325w" width="1325"&gt;&lt;/p&gt;
&lt;p&gt;それも名店とされるスパ、スーパー銭湯、カプセルホテルばかりである。&lt;br&gt;
&lt;strong&gt;正直なところこの特典目当てで受験した。&lt;/strong&gt;&lt;br&gt;
約5000円の受験料も、そのうち元が取れるだろう&amp;hellip;&lt;/p&gt;
&lt;p&gt;と思いきや、 &lt;br&gt;
よく行く店舗は既に会員になってしまっていたり(割引の併用ができない)、&lt;br&gt;
俺がよく使う短時間コースは対象外だったりで、&lt;br&gt;
取得してから今日までまだ割引の恩恵を受けられていない。😭&lt;br&gt;
どうして&amp;hellip;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;SSWAに合格した。
やったぜ。&lt;/p&gt;
&lt;p&gt;特典の恩恵は受けられていないが、&lt;br&gt;
これまで雰囲気で入っていたサウナに対して学ぶ良い機会となった。&lt;br&gt;
1人のサウナ好きとして大いに自慢したい。&lt;br&gt;
俺は一般の人よりサウナに詳しいんだ。&lt;strong&gt;資格を取った俺は偉いんだ。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;また、SSWAより上位の資格として&lt;a class="link" href="https://www.sauna.or.jp/professional/index.html" target="_blank" rel="noopener"
 &gt;SSPM(Sauna Spa Professional Manager)&lt;/a&gt;というものがあるらしい。&lt;br&gt;
SSWA資格者しか受験できないということなので、機会があればぜひ受験したい。&lt;br&gt;
(なお受験料は3倍の15000円💸)&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="風呂上がりの人間やタオルをガン舐めするのが好きなねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-23-sswa/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2024-02-23-sswa/sotochan_hu_7ccd571ea671b375.jpeg 800w, https://blog.uzimihsr.com/post/2024-02-23-sswa/sotochan_hu_c0b5612811bde9e0.jpeg 1600w, https://blog.uzimihsr.com/post/2024-02-23-sswa/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a class="link" href="https://www.sauna.or.jp/adviser/" target="_blank" rel="noopener"
 &gt;サウナ・スパ 健康アドバイザー&lt;/a&gt;&lt;br&gt;
アルファベットの方がなんかかっこいいので本記事ではSSWAと呼称する。&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;a class="link" href="https://www.sauna.or.jp/index.html" target="_blank" rel="noopener"
 &gt;公益社団法人 日本サウナ・スパ協会&lt;/a&gt;&lt;br&gt;
同じく。&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>1月のそとちゃん(2024)</title><link>https://blog.uzimihsr.com/post/2024-02-02-sotochan/</link><pubDate>Fri, 02 Feb 2024 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2024-02-02-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan.jpeg" alt="Featured image of post 1月のそとちゃん(2024)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;h3 id="湯たんぽ"&gt;湯たんぽ
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://blog.uzimihsr.com/post/2023-12-31-sotochan/" target="_blank" rel="noopener"
 &gt;クリスマスプレゼント&lt;/a&gt;で献上したねこ型湯たんぽが結構いい感じ。&lt;br&gt;
期待していた通り、くっついて(乗っかって)仲良くしてくれている。&lt;/p&gt;
&lt;p&gt;&lt;img alt="なかよし" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan01_hu_585d485a2333d887.jpeg 800w, https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan01_hu_d3a5748e64ed4f08.jpeg 1600w, https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;横に並べてみると本当にねこが2匹いるみたいでめちゃめちゃかわいい。&lt;br&gt;
本当に買ってよかった&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="ねこ2ひき" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan02_hu_d234cc6df57b0c42.jpeg 800w, https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan02_hu_a8acfce740c097ec.jpeg 1600w, https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;ただ、そとちゃんが自分から横に並ぶのは稀で、&lt;br&gt;
どちらかというと上に乗っかることが多い。&lt;/p&gt;
&lt;p&gt;寒いときに湯たんぽをひざに載せていると普通にそとちゃんが上から乗っかりにくる。&lt;/p&gt;
&lt;p&gt;&lt;img alt="割と躊躇なく踏む" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan03_hu_6c839db870e5c03a.jpeg 800w, https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan03_hu_89875fee7a5a872.jpeg 1600w, https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan03.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;たまに猫の上に乗る猫の動画とか見かけるけど、&lt;br&gt;
ねこは下の子が重くてかわいそう的なことは考えないんだろうか&amp;hellip;？&lt;/p&gt;
&lt;p&gt;もしくは、そとちゃんはかしこいのでこれがねこじゃないことに気づいていて、&lt;br&gt;
クッション感覚で乗っているのかもしれない。&lt;br&gt;
毛繕いとかもしないし&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="降ろされた" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan04_hu_3690b180dc637123.jpeg 800w, https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan04_hu_f629e8b6d9bf8872.jpeg 1600w, https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;まあかわいければなんでもOKです。&lt;/p&gt;
&lt;p&gt;&lt;img alt="やっぱりこたつの中が定位置" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan05_hu_f4385ab765366366.jpeg 800w, https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan05_hu_c9c046fef80abc21.jpeg 1600w, https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan05.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="あまえんぼ"&gt;あまえんぼ
&lt;/h3&gt;&lt;p&gt;理由は謎だけど、&lt;br&gt;
最近そとちゃんの甘えがはげしい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="あまえんぼちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan06_hu_360b6fa7e5485d58.jpeg 800w, https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan06_hu_e934d8c9314e4afb.jpeg 1600w, https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan06.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;いわゆる要求鳴きが多い。&lt;br&gt;
ドアを開けて欲しいときとかにわんわん鳴く。&lt;/p&gt;
&lt;p&gt;&lt;img alt="このあと開けたけど寒くてすぐ戻ってきた" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan07_hu_36f5c23d8bbd4e6f.jpeg 800w, https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan07_hu_bce0c9698867cc36.jpeg 1600w, https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan07.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;ドアはそとちゃんが開けられないからしょうがないんだけど、&lt;br&gt;
なんだか要求がエスカレートしてしまってついにはこたつの布団の前でも鳴くようになった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="入れないアピール" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan08_hu_fbad86918251d67f.jpeg 800w, https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan08_hu_ae6b7d067120f7c7.jpeg 1600w, https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan08.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;ふとんを持ち上げろということらしい。&lt;br&gt;
元々自力で潜ってたのに&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="上げるとすぐ入る" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan09.jpeg" srcset="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan09_hu_78743420f4b25418.jpeg 800w, https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan09_hu_a84658eb6cfa7325.jpeg 1600w, https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan09.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;こたつに入るときだけならいいものの、&lt;br&gt;
出たい時にも鳴くことがある。&lt;br&gt;
俺はドアマンか&amp;hellip;？&lt;/p&gt;
&lt;p&gt;&lt;img alt="「ごくろう」" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan16.jpeg" srcset="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan16_hu_bcbf81ee44adb5c.jpeg 800w, https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan16_hu_839123bcf9a7cdca.jpeg 1600w, https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan16.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;あとはひなたぼっこしたいのに太陽が出てないときにもよく鳴く。&lt;br&gt;
俺が悪いみたいな雰囲気だしてくるけどこればっかりはどうしようもない。&lt;/p&gt;
&lt;p&gt;&lt;img alt="めっちゃ文句言う" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan10.jpeg" srcset="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan10_hu_5470ea6d868bd693.jpeg 800w, https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan10_hu_7eb1074507b3001c.jpeg 1600w, https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan10.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;仕方がないのでおもちゃで遊んでごまかす。&lt;br&gt;
簡単にごまかされちゃうのもかわいい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="一度にひとつのことしか考えられない" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan11.jpeg" srcset="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan11_hu_62102c4e589cc0e3.jpeg 800w, https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan11_hu_daa544bd6f3307ff.jpeg 1600w, https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan11.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="太陽が出るとおとなしくなる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan12.jpeg" srcset="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan12_hu_5e3562124bc0c9e4.jpeg 800w, https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan12_hu_1bf4bd8ee257df2b.jpeg 1600w, https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan12.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;一番のあまえんぼポイントはやっぱりひざに乗ってくるところ。&lt;/p&gt;
&lt;p&gt;ソファでだらだらしてるとすかさず乗ってくる。&lt;/p&gt;
&lt;p&gt;&lt;img alt="絶対来る" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan13.jpeg" srcset="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan13_hu_6f8043cd2a2320fd.jpeg 800w, https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan13_hu_8c9b67489490a803.jpeg 1600w, https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan13.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;一度ひざに乗ると長くて、&lt;br&gt;
だいたい10分くらい、長い時は30分以上乗っている。&lt;br&gt;
(不思議と脚はしびれない)&lt;/p&gt;
&lt;p&gt;&lt;img alt="溶けてる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan14.jpeg" srcset="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan14_hu_16ac3cf4030a1cce.jpeg 800w, https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan14_hu_fb8ccc121699d870.jpeg 1600w, https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan14.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;長く居て欲しいときはなでたりおしりを叩いたりするといい感じになる。&lt;br&gt;
問題は早めに降りて欲しくなったときの手段がないこと&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="溶けてる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan15.jpeg" srcset="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan15_hu_c6be99aeb691f280.jpeg 800w, https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan15_hu_37dcb01496747bc4.jpeg 1600w, https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan15.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;年は明けたけど、そとちゃんは相変わらずのんびりだらだら過ごしている。&lt;br&gt;
毎日がお正月みたいなものでとてもうらやましい。&lt;/p&gt;
&lt;p&gt;そろそろ寒さもピークを過ぎるはずなので、&lt;br&gt;
また近所で抱っこ散歩とかできるといいな&amp;hellip;&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="毎日がお正月で夏休みで冬休みのねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan_hu_df6f19498881b8d2.jpeg 800w, https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan_hu_2075f67beb371b35.jpeg 1600w, https://blog.uzimihsr.com/post/2024-02-02-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>12月のそとちゃん(2023)</title><link>https://blog.uzimihsr.com/post/2023-12-31-sotochan/</link><pubDate>Sun, 31 Dec 2023 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2023-12-31-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan.jpeg" alt="Featured image of post 12月のそとちゃん(2023)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;h3 id="カーテン"&gt;カーテン
&lt;/h3&gt;&lt;p&gt;そとちゃんは&lt;a class="link" href="https://blog.uzimihsr.com/post/2023-07-17-sotochan/#%E3%82%AB%E3%83%BC%E3%83%86%E3%83%B3" target="_blank" rel="noopener"
 &gt;カーテン&lt;/a&gt;が好き。&lt;/p&gt;
&lt;p&gt;&lt;img alt="幸せそう" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan01_hu_b25f39335b1acaa0.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan01_hu_5a97b5251ef2b77.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;カーテンの薄い生地がきもちいいみたいで普段から裾をベッドの上に広げてあるのだが、&lt;br&gt;
よくここでゴロゴロしている。&lt;/p&gt;
&lt;p&gt;&lt;img alt="半目開いちゃうくらい気持ちいい?" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan02_hu_de64d7b5a1d7d16.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan02_hu_76ed297649ca1e82.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;でもそとちゃんが自力でカーテンを持ち上げることはできないので、&lt;br&gt;
俺が裾をベッドに広げ忘れているとお昼頃にすごく文句を言ってきてうるさい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="カーテンに乗れるとおとなしくなる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan03_hu_ae98ff17231d18ff.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan03_hu_d658829290a2ec8.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan03.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;カーテン越しにちょっと光を浴びるのが好きなのかな？&lt;br&gt;
ちょっと変なクセだと思うけどかわいい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="カーテンに乗れるとおとなしくなる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan04_hu_b90e8041cc9cb1b0.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan04_hu_f78023b79d187f7.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="毛布"&gt;毛布
&lt;/h3&gt;&lt;p&gt;今月はちょこちょこ人を泊めることがあったので、&lt;br&gt;
(ちなみにそとちゃんはお客さんが大好き!誰でもすぐに膝に乗る)&lt;br&gt;
普段使っていなかったもう1枚の毛布を引っ張り出した。&lt;/p&gt;
&lt;p&gt;すぐにそとちゃんに気に入られてしまった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="これはねこのもの" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan05_hu_54c90c1515de744a.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan05_hu_a14c573c14e3f01.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan05.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;あまりにもお気に入りなので、&lt;br&gt;
その後もそとちゃんが乗れるように畳んでソファに置いている。　　&lt;/p&gt;
&lt;p&gt;&lt;img alt="一度乗るとなかなか動かない" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan06_hu_8ebc75ff0e8b266d.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan06_hu_83454693325338c1.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan06.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;当分の間片付けるつもりはないのに、&lt;br&gt;
そとちゃんが必死に場所を守ろうとしているのが健気でかわいい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="絶対うごかない" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan07_hu_b5967a7cbae80de0.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan07_hu_2621760feac19a8.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan07.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="やっぱりこたつ"&gt;やっぱりこたつ
&lt;/h3&gt;&lt;p&gt;カーテン、布団、毛布とお気に入りスポットがたくさんあるそとちゃん。&lt;/p&gt;
&lt;p&gt;それでもやっぱり寒い日はこたつが好き。&lt;/p&gt;
&lt;p&gt;&lt;img alt="だいすき" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan08_hu_5936d1ac7b4cba89.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan08_hu_686dc092e12d28fc.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan08.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;あれ？ねこいないな？と思ったらだいたいこたつの中で寝ている。&lt;/p&gt;
&lt;p&gt;&lt;img alt="まるい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan09.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan09_hu_457934b5e754987d.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan09_hu_5951e5ba7b918793.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan09.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;丸まってるおしりとこたつ布団の境目が個人的にめちゃめちゃかわいい。&lt;/p&gt;
&lt;p&gt;いいね〜&lt;/p&gt;
&lt;p&gt;&lt;img alt="はみ出そう" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan10.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan10_hu_8cab7bfdc05698ea.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan10_hu_974184000040ceb6.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan10.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="クリスマス"&gt;クリスマス
&lt;/h3&gt;&lt;p&gt;今年もそとちゃんにサンタマントを着てもらった。&lt;br&gt;
めちゃめちゃかわいいねえ&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="サンタさん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan11.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan11_hu_ec39b974698ff825.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan11_hu_e7f306a49a621501.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan11.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://blog.uzimihsr.com/post/2023-11-05-sotochan/#%E3%83%8F%E3%83%AD%E3%82%A6%E3%82%A3%E3%83%B3" target="_blank" rel="noopener"
 &gt;ハロウィンの時のマント&lt;/a&gt;もそうだけど、&lt;br&gt;
やっぱり軽めの素材だとあまり気にならない様子。&lt;br&gt;
嫌がらずに協力してくれた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="おとなしい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan12.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan12_hu_c6ef4dc7d6b9b3a8.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan12_hu_70ee94ea012b2457.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan12.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;しっかりカメラ目線くれてたすかる。&lt;br&gt;
(おもちゃで釣ったけど&amp;hellip;)&lt;/p&gt;
&lt;p&gt;&lt;img alt="やる気" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan13.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan13_hu_77256d6925cd5f39.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan13_hu_64309c9ffe390a3c.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan13.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;そんな今年のそとちゃんへのクリスマスプレゼントは&amp;hellip;?&lt;/p&gt;
&lt;p&gt;&lt;img alt="けっこうでかい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan14.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan14_hu_ecb8b7a16043f76e.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan14_hu_ae6fa3f5bb0377a5.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan14.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://lifeonproducts.co.jp/product/lcawa004/" target="_blank" rel="noopener"
 &gt;ねこ湯たんぽ&lt;/a&gt;でした。&lt;/p&gt;
&lt;p&gt;&lt;img alt="まだ何かわかってなさそう" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan15.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan15_hu_2860959858eece83.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan15_hu_822ce9dfd0efcb64.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan15.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;そとちゃんがおるすばんのときは事故が怖くてこたつの電源を入れられないんだけど、&lt;br&gt;
湯たんぽならこたつよりも安全に暖が取れると思い購入。&lt;/p&gt;
&lt;p&gt;&lt;img alt="そんなことより袋のヒモに夢中" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan16.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan16_hu_11b5794386b71bbc.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan16_hu_af9915eadcad2452.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan16.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;開けてみるとこんな感じ。&lt;br&gt;
お店で見たときはそとちゃんくらいの大きさかな？と思ってたんだけど、&lt;br&gt;
実際はかなり大きかった&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="そとちゃんが小さい説もある" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan17.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan17_hu_4dcc8e78da931bfb.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan17_hu_b2b89725f68ff7de.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan17.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;気に入ってくれるかわからないけど、&lt;br&gt;
とりあえず温めてこたつに入れてみた。&lt;/p&gt;
&lt;p&gt;楽勝でした。&lt;/p&gt;
&lt;p&gt;&lt;img alt="お気に召した" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan18.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan18_hu_45a3acdc428f0703.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan18_hu_7830628344bce4d3.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan18.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;この湯たんぽが結構暖かくて、&lt;br&gt;
こたつの中がほかほかになるのでそとちゃん的にもいい感じらしい。&lt;/p&gt;
&lt;p&gt;なによりもねこが2匹くっついてるみたいでかわいい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="なかよし" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan19.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan19_hu_2a1b4feff03e4088.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan19_hu_e31bce7296a818f6.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan19.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;よかったね〜&lt;/p&gt;
&lt;p&gt;&lt;img alt="かわいい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan20.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan20_hu_3a6f9464da66b47.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan20_hu_7248ca926f5d2176.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan20.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;今年もそとちゃんは元気でいい子だった。&lt;/p&gt;
&lt;p&gt;大きなアクシデントもなく、&lt;br&gt;
毎日遊んで食べて寝て楽しそうだったので本当によかった。&lt;/p&gt;
&lt;p&gt;シニアねこになって流石にちょっと落ち着いてくるかと思ったけど、&lt;br&gt;
全然そんなことはなく元気に騒いで遊んで何よりだった。&lt;br&gt;
ちょっとお昼寝の時間が長くなったかな？というくらい。&lt;/p&gt;
&lt;p&gt;来年もそとちゃんが変わらず楽しく過ごせるよう、俺も頑張りたい。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="今年も1年いい子だったねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan_hu_8eff850dfe6e5342.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan_hu_5f923dd6ba9ba2d.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-31-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>Azureのリソースグループ名に日本語を使うのはやめよう</title><link>https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/</link><pubDate>Tue, 12 Dec 2023 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sotochan.jpeg" alt="Featured image of post Azureのリソースグループ名に日本語を使うのはやめよう" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Azureのリソースグループ名に日本語(英数字以外の文字)を使用するとAzure内部での一部API呼び出し時にエラーが発生する&lt;/li&gt;
&lt;li&gt;ASCIIで表記できる文字(英数字と簡単な記号だけ)を使おう&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="経緯"&gt;経緯
&lt;/h2&gt;&lt;p&gt;Azure Data Factoryを試したくてリソースを作成していたときのこと。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://learn.microsoft.com/ja-jp/azure/data-factory/data-factory-private-link?WT.mc_id=Portal-Microsoft_Azure_DataFactory" target="_blank" rel="noopener"
 &gt;Azure Data Factory 用の Azure Private Link&lt;/a&gt;を参考に、&lt;br&gt;
同時にプライベートエンドポイントを作成しようとした。&lt;/p&gt;
&lt;p&gt;&lt;img alt="プライベートエンドポイントの作成" class="gallery-image" data-flex-basis="442px" data-flex-grow="184" height="922" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc01.png" srcset="https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc01_hu_aff1e1c2304f7bc.png 800w, https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc01_hu_bca946f2586e1361.png 1600w, https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc01.png 1700w" width="1700"&gt;&lt;/p&gt;
&lt;p&gt;各項目の設定はほぼデフォルトで、問題なくデプロイが開始した&amp;hellip;と思ったら、&lt;br&gt;
Data Factory自体のデプロイはできたもののプライベートエンドポイントの作成がコケてしまった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="なんだァ? てめェ…" class="gallery-image" data-flex-basis="593px" data-flex-grow="247" height="719" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc02.png" srcset="https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc02_hu_9a905cba2e4306b3.png 800w, https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc02_hu_dda1d15e92b4e66c.png 1600w, https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc02.png 1777w" width="1777"&gt;&lt;/p&gt;
&lt;p&gt;なにいってだこいつ&amp;hellip;&lt;/p&gt;
&lt;p&gt;俺は愚かなお猿さんなので、&lt;br&gt;
これを一時的なエラーと決めつけて脳死で再試行を10回程度繰り返したが、&lt;br&gt;
一度も成功することはなかった&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;del&gt;〜fin〜&lt;/del&gt;&lt;/p&gt;
&lt;h2 id="原因調査"&gt;原因調査
&lt;/h2&gt;&lt;p&gt;俺は人類の誇りを取り戻し、&lt;br&gt;
おとなしくエラーの内容を読むことにした。&lt;/p&gt;
&lt;p&gt;表示されたエラーはこんな感じ。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;code&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;DeploymentFailed&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;target&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/subscriptions/xxxxxxxxxxxxxxxxxxxxx/resourceGroups/ふがふが/providers/Microsoft.Resources/deployments/Microsoft.DataFactory-20231212010148&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;message&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;At least one resource deployment operation failed. Please list deployment operations for details. Please see https://aka.ms/arm-deployment-operations for usage details.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;details&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;code&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;ResourceDeploymentFailure&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;target&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/subscriptions/xxxxxxxxxxxxxxxxxxxxx/resourceGroups/ふがふが/providers/Microsoft.Resources/deployments/deployPrivateEndpoint-fugafuga-df-01-private-endpoint&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;message&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;The resource write operation failed to complete successfully, because it reached terminal provisioning state &amp;#39;Failed&amp;#39;.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;blockquote&gt;
 &lt;p&gt;Call to Microsoft.DataFactory/factories failed. Error message: The request URI &amp;lsquo;&lt;a class="link" href="https://management.azure.com:443/subscriptions/xxxxxxxxxxxxxxxxxxxxx/resourcegroups/%25E3%2581%25B5%25E3%2581%258C%25E3%2581%25B5%25E3%2581%258C/providers/Microsoft.DataFactory/factories/fugafuga-df-01/privateEndpointConnectionProxies/fugafuga-df-01-private-endpoint.f596276c-4285-425c-9019-b5553ce6006e/operationstatuses/da7d1374-a224-428c-a13e-81c969ac4fa6?api-version=2018-06-01%27" target="_blank" rel="noopener"
 &gt;https://management.azure.com:443/subscriptions/xxxxxxxxxxxxxxxxxxxxx/resourcegroups/%25E3%2581%25B5%25E3%2581%258C%25E3%2581%25B5%25E3%2581%258C/providers/Microsoft.DataFactory/factories/fugafuga-df-01/privateEndpointConnectionProxies/fugafuga-df-01-private-endpoint.f596276c-4285-425c-9019-b5553ce6006e/operationstatuses/da7d1374-a224-428c-a13e-81c969ac4fa6?api-version=2018-06-01'&lt;/a&gt; is not valid, because it contains double encoding sequence &amp;lsquo;%25&amp;rsquo;. (コード: InvalidDoubleEncodedRequestUri)&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;重要そうなのは2つ目のエラー文の&lt;code&gt;InvalidDoubleEncodedRequestUri&lt;/code&gt;の部分。&lt;br&gt;
なんかデプロイ時に内部で叩かれてそうなAPIのURLに&lt;code&gt;%25&lt;/code&gt;が含まれているのが問題と言われている(気がする)。&lt;/p&gt;
&lt;p&gt;ここで怒られているURLをJSONのエラーメッセージに含まれるURLと比較すると、&lt;br&gt;
&lt;code&gt;%25E3%2581%25B5%25E3%2581%258C%25E3%2581%25B5%25E3%2581%258C&lt;/code&gt;と&lt;code&gt;ふがふが&lt;/code&gt;の部分が対応してそうというか、&lt;br&gt;
&lt;code&gt;ふがふが&lt;/code&gt;が&lt;a class="link" href="https://ja.wikipedia.org/wiki/%E3%83%91%E3%83%BC%E3%82%BB%E3%83%B3%E3%83%88%E3%82%A8%E3%83%B3%E3%82%B3%E3%83%BC%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0" target="_blank" rel="noopener"
 &gt;URLエンコード&lt;/a&gt;されたものがそれっぽい。&lt;/p&gt;
&lt;p&gt;実際に試してみると、&lt;code&gt;ふがふが&lt;/code&gt;を2回エンコードしたものがまさに一致した。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# jqでURLエンコード&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;ふがふが&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; jq -Rr @uri
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;%E3%81%B5%E3%81%8C%E3%81%B5%E3%81%8C
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2回エンコードしたら&amp;#39;%25&amp;#39;を含むエラーメッセージのURLと同じものが出てきた&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;%E3%81%B5%E3%81%8C%E3%81%B5%E3%81%8C&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; jq -Rr @uri
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;%25E3%2581%25B5%25E3%2581%258C%25E3%2581%25B5%25E3%2581%258C
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;エラーの名前的にもこいつが原因と見て間違いなさそう。&lt;br&gt;
(エラー名も&lt;code&gt;InvalidDoubleEncodedRequestUri:リクエストURIの不正な二重エンコード(意訳)&lt;/code&gt;だし)&lt;/p&gt;
&lt;p&gt;じゃあこの&lt;code&gt;ふがふが&lt;/code&gt;はどこからきているのかというと、&lt;br&gt;
リソース作成時に指定するリソースグループの名前だった。&lt;/p&gt;
&lt;p&gt;つまり&amp;hellip;&lt;br&gt;
&lt;strong&gt;リソースグループ名にマルチバイト文字を使用していると、&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;それがAPIのURLにエンコードされた時にエラーが発生する&lt;/strong&gt;&lt;br&gt;
&amp;hellip;ってコト!?&lt;/p&gt;
&lt;h2 id="修正"&gt;修正
&lt;/h2&gt;&lt;p&gt;ならリソースグループ名がURLエンコードが発生しない文字、&lt;br&gt;
すなわち半角英数ならいいんじゃね？&lt;/p&gt;
&lt;p&gt;&lt;img alt="半角英数のリソースグループ名で再挑戦" class="gallery-image" data-flex-basis="397px" data-flex-grow="165" height="917" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc03.png" srcset="https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc03_hu_d61f79cd6f8d9f86.png 800w, https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc03.png 1517w" width="1517"&gt;&lt;/p&gt;
&lt;p&gt;できちゃったねぇ&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="デプロイ通った" class="gallery-image" data-flex-basis="494px" data-flex-grow="205" height="737" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc04.png" srcset="https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc04_hu_ca07d00da047552a.png 800w, https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc04.png 1517w" width="1517"&gt;&lt;/p&gt;
&lt;p&gt;というわけで、&lt;br&gt;
Azureのリソースグループ名に全角文字を使うのはやめようと心に誓った。&lt;/p&gt;
&lt;h2 id="他のケース"&gt;他のケース
&lt;/h2&gt;&lt;p&gt;上記の例はかなりわかりやすかったが、&lt;br&gt;
他のところでも全角文字が原因でData Factoryがうまく動かないことがあった。&lt;br&gt;
(というか、本当のところはプライベートエンドポイントではなくこっちでめちゃめちゃ時間消費してこの問題に気づいた)&lt;/p&gt;
&lt;p&gt;問題が起きたのは&lt;a class="link" href="https://learn.microsoft.com/ja-jp/azure/data-factory/connector-azure-blob-storage?tabs=data-factory" target="_blank" rel="noopener"
 &gt;Azure Data Factory または Azure Synapse Analytics を使用して Azure Blob Storage のデータをコピーし変換する&lt;/a&gt;などを参考にAzure Blob Storage上のExcelデータをData Factoryで整形するフローを作っていた時のこと。&lt;/p&gt;
&lt;p&gt;Azure Blob Storage上のExcelをデータセットとして参照できる状態で、&lt;br&gt;
それをデータフローのソースとして参照すると接続時にエラーが発生してしまった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="データセットは接続できる" class="gallery-image" data-flex-basis="492px" data-flex-grow="205" height="802" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc05.png" srcset="https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc05_hu_d3ed88a862b69f1c.png 800w, https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc05_hu_ae4dcf2bde2bc3b8.png 1600w, https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc05.png 1645w" width="1645"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="データフローで参照しようとするとコケる" class="gallery-image" data-flex-basis="559px" data-flex-grow="233" height="705" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc06.png" srcset="https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc06_hu_8b94361b5218a348.png 800w, https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc06_hu_b0da1a4d1c2f26e.png 1600w, https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc06.png 1644w" width="1644"&gt;&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;Request headers must contain only ASCII characters. - RunId: 69672633-6312-4832-95fc-90a3d2b54678&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;なにいってだこいつ&amp;hellip;&lt;br&gt;
他にエラーログが出ていないのでこのメッセージしかヒントにならないが、&lt;br&gt;
どうやら文字コードで怒られている様子。&lt;/p&gt;
&lt;p&gt;一瞬Excelのデータに全角文字列があるから&amp;hellip;? と思ったが、&lt;br&gt;
.xlsx形式で保存するときは文字コード選べないし、&lt;br&gt;
そもそもデータセットとして.xlsxが参照できるようになっている時点でデータ中身の文字コードが原因とは考えづらい。&lt;br&gt;
(実際.xlsx内の文字列を英数のみに替えたり、UTF-8で.csvとして出力したファイルに変えても変わらなかった)&lt;/p&gt;
&lt;p&gt;リクエストヘッダがどうとか言ってるし、&lt;br&gt;
これも内部で叩こうとしてるアクセス先(Azure Blob Storage)のURLにASCIIで表現できない全角文字のリソースグループ名(&lt;code&gt;ふがふが&lt;/code&gt;)が入ってるからでは&amp;hellip;?&lt;/p&gt;
&lt;p&gt;&lt;img alt="リンクサービスでは\"fugafugablob01\"を参照している" class="gallery-image" data-flex-basis="357px" data-flex-grow="148" height="1066" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc07.png" srcset="https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc07_hu_b9974806fffa43a5.png 800w, https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc07.png 1588w" width="1588"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="“fugafugablob01\"はリソースグループが全角文字の\"ふがふが”" class="gallery-image" data-flex-basis="889px" data-flex-grow="370" height="366" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc08.png" srcset="https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc08_hu_555005ce28b5b876.png 800w, https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc08.png 1356w" width="1356"&gt;&lt;/p&gt;
&lt;p&gt;もしこの読みが正しいなら、&lt;br&gt;
リソースグループ名を英数字に変えたらうまくいくんじゃね&amp;hellip;?&lt;/p&gt;
&lt;p&gt;&lt;img alt="リソースグループ名がASCIIで表現できる\"hogehoge\"なAzure Blob Storageを用意" class="gallery-image" data-flex-basis="892px" data-flex-grow="372" height="365" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc09.png" srcset="https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc09_hu_a748e3abb7c5efe3.png 800w, https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc09.png 1358w" width="1358"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="リンクサービスで\"hogehogeblob01\"を選択" class="gallery-image" data-flex-basis="357px" data-flex-grow="148" height="1068" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc10.png" srcset="https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc10_hu_27458b2c08798cf5.png 800w, https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc10.png 1591w" width="1591"&gt;&lt;/p&gt;
&lt;p&gt;できちゃったねえ&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="データフローで参照できた" class="gallery-image" data-flex-basis="448px" data-flex-grow="186" height="881" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc11.png" srcset="https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc11_hu_6c168e8865c995e4.png 800w, https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc11_hu_da4c0862329c3c0f.png 1600w, https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc11.png 1645w" width="1645"&gt;&lt;/p&gt;
&lt;h2 id="お気持ち"&gt;お気持ち
&lt;/h2&gt;&lt;p&gt;実際のところリソースグループ名に使える文字に制限はあるのだろうか。&lt;br&gt;
公式ドキュメントを漁って調べてみた。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://learn.microsoft.com/ja-jp/azure/azure-resource-manager/management/resource-name-rules#microsoftresources" target="_blank" rel="noopener"
 &gt;Azure リソースの名前付け規則と制限事項&lt;/a&gt;によると、&lt;br&gt;
一応リソースグループ名に使用できる文字は&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;アンダースコア、ハイフン、ピリオド、括弧と、&lt;a class="link" href="https://learn.microsoft.com/ja-jp/dotnet/api/system.char.isletterordigit" target="_blank" rel="noopener"
 &gt;Char.IsLetterOrDigit&lt;/a&gt;関数で定義されている文字または数字。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;となっているので、おそらくちゃんと読まずに日本語でふざけたリソースグループ名をつけた俺が100%悪い。&lt;/p&gt;
&lt;p&gt;&lt;img alt="文字の制限はちゃんと書かれていた" class="gallery-image" data-flex-basis="254px" data-flex-grow="105" height="819" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc12.png" srcset="https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc12_hu_35b54d7bfeefa51c.png 800w, https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc12.png 867w" width="867"&gt;&lt;/p&gt;
&lt;p&gt;&amp;hellip;が、ちょっともやもやするのはリソースグループ作成時に普通にマルチバイト文字が指定できちゃうこと。&lt;/p&gt;
&lt;p&gt;リソースグループ名の入力時と作成前の検証ステップで何も怒ってくれないのはどうなんだろう&amp;hellip;?&lt;br&gt;
バリデーションは機能しているのだろうか&amp;hellip;?&lt;/p&gt;
&lt;p&gt;&lt;img alt="リソースグループ名がマルチバイト文字でも検証が成功しちゃうのどうなん？" class="gallery-image" data-flex-basis="381px" data-flex-grow="158" height="490" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sc13.png" width="778"&gt;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;Azure初心者すぎてこんなところでコケてそこそこの時間を無駄にしてしまったので、&lt;br&gt;
戒めとして書いてみた。&lt;/p&gt;
&lt;p&gt;もちろんちゃんとルールを把握せず雰囲気で触った俺が100%悪いんだけど、&lt;br&gt;
システムを壊すような操作はそもそもバリデーション等でユーザーがいじれないようにするべきだと思っているのでやっぱりもやもやする。&lt;br&gt;
Azureとは仲良くなれなさそうだな&amp;hellip;&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="元々マルチバイト文字(日本語)が理解できない(する気がない)ねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sotochan_hu_d6e35b48b3a008ea.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sotochan_hu_d6e5367ca51b8e58.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-12-do-not-use-japanese-for-azure-resource-group-names/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>11月のそとちゃん(2023)</title><link>https://blog.uzimihsr.com/post/2023-12-03-sotochan/</link><pubDate>Sun, 03 Dec 2023 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2023-12-03-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan.jpeg" alt="Featured image of post 11月のそとちゃん(2023)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;h3 id="こたつ"&gt;こたつ
&lt;/h3&gt;&lt;p&gt;我が家もついにこたつを解禁！&lt;/p&gt;
&lt;p&gt;&lt;img alt="解禁" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan01_hu_a21106091a75506f.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan01_hu_5c0b403b99447fc4.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;10月中から寒さ(?)を訴えてきたそとちゃん。&lt;/p&gt;
&lt;p&gt;&lt;img alt="寒さを訴える様子(室温25℃)" class="gallery-image" data-flex-basis="410px" data-flex-grow="170" height="1161" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan02_hu_e4a0115b15b5bc54.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan02_hu_c36fca2942fe531.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;11月中旬から急に冷え込んできたこともあり、&lt;br&gt;
念願かなって今年のこたつを手に入れた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="洗い立てのふかふかこたつ布団をチェックするねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan03_hu_5880a0ac9c3a74a8.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan03_hu_ddada6b927771e83.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan03.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;解禁直後のそとちゃんの様子↓&lt;/p&gt;
&lt;div class="video-wrapper"&gt;
 &lt;iframe loading="lazy" 
 src="https://www.youtube.com/embed/ewLYg-lohbk" 
 allowfullscreen 
 title="YouTube Video"
 &gt;
 &lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;よほど嬉しかったのか、&lt;br&gt;
ぷーぷー言いながら潜っていくのがかわいい。&lt;/p&gt;
&lt;p&gt;ふとんを内側に寄せて、その上に座るのがやっぱり好きらしい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="こたつのプロ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan04_hu_e0641e9850ad2ea8.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan04_hu_f7874033e6b16ed6.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="ナイトモードで撮影" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan05_hu_296522720caf179.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan05_hu_e6fadef2d2bd2a53.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan05.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;人間が先に入っていると、&lt;br&gt;
こたつ布団の上から膝に乗ってくるのがかわいい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="人間はソファに座って脚だけ突っ込んでいます" class="gallery-image" data-flex-basis="332px" data-flex-grow="138" height="740" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan06.JPG" srcset="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan06_hu_ce9441bc8adf4e5b.JPG 800w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan06.JPG 1024w" width="1024"&gt;&lt;/p&gt;
&lt;p&gt;よかったね〜&lt;/p&gt;
&lt;p&gt;&lt;img alt="たまにしっぽだけはみ出てる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan07_hu_76993d80f4d538ca.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan07_hu_f6a1211214f75616.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan07.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="ふとん"&gt;ふとん
&lt;/h3&gt;&lt;p&gt;そとちゃんがこたつを手に入れた裏で、&lt;br&gt;
人間用のふとんも冬用のものに変えていた。&lt;/p&gt;
&lt;p&gt;ニトリの&lt;a class="link" href="https://www.nitori-net.jp/ec/product/7525411s/" target="_blank" rel="noopener"
 &gt;毛布にもなる掛け布団カバー&lt;/a&gt;を買ってみたのだが、&lt;br&gt;
なんとこれが一瞬でそとちゃんのものになってしまった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="超お気に入り" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan08_hu_e6393b08b94c4cef.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan08_hu_90163b9347e312a9.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan08.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;肌触りが気に入ったのかな？&lt;br&gt;
昼間はよくこの上でひなたぼっこしている。&lt;/p&gt;
&lt;p&gt;&lt;img alt="気持ちよさそう" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan09.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan09_hu_bac45e0dbdc6a21b.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan09_hu_ef3456a321dacd74.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan09.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="爆睡" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan10.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan10_hu_4d7a37c620aaedda.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan10_hu_b871daa9ffac2611.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan10.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;こたつを手に入れて満足したはずのそとちゃんだったが、&lt;br&gt;
気づけばこたつよりもこの布団の上にいる方が多くなってしまった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="完全にねこのもの" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan11.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan11_hu_f00ab5aff0549570.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan11_hu_e9a5525681cfe986.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan11.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;やけど防止で最近はこたつの電源を入れずにエアコンで部屋を温めるようにしているので、&lt;br&gt;
下はNウォームの発熱、上はエアコンの温風で十分暖かいのかもしれない。&lt;/p&gt;
&lt;p&gt;とりあえずねこが幸せならそれでOKです。&lt;/p&gt;
&lt;p&gt;&lt;img alt="人間はどこで寝ればいいの？" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan12.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan12_hu_7f445b9787820742.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan12_hu_80b283f6f0712d95.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan12.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="いもむし"&gt;いもむし
&lt;/h3&gt;&lt;p&gt;冬用ふとんに替えてからというもの、&lt;br&gt;
たまに謎のいもむしが部屋に出現するようになった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="新種のいもむし？" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan13.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan13_hu_a211d7f5668a2359.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan13_hu_cfdbaba9d2c98e2.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan13.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;体の表面に手脚のようなものは見当たらず、&lt;br&gt;
特に動く様子はない。&lt;/p&gt;
&lt;p&gt;&lt;img alt="頭のような部分と胴体の部分の境目が曖昧" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan14.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan14_hu_58c794a84476851b.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan14_hu_bbbc85e6c89d1719.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan14.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;近づいてよくみてみると体表は毛皮で覆われており、&lt;br&gt;
撫でてみるとゴロゴロ、プープーといった音を出す。&lt;/p&gt;
&lt;p&gt;いもむしが発生するタイミングは完全にランダムだが、&lt;br&gt;
俺が朝起きると腹の上にくっついていることがある。&lt;br&gt;
結構暖かくてきもちいい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="重さは4kgくらい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan15.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan15_hu_2b83d0d0a0fe0d62.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan15_hu_99571eb23db15e19.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan15.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;まれにいもむしの別個体のような丸い毛玉が出現することもある。&lt;/p&gt;
&lt;p&gt;&lt;img alt="すごくまるい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan16.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan16_hu_25d5e99c58e0f2dd.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan16_hu_1554ce980d37d7ff.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan16.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;この毛玉はいもむしよりもさらに動きが少ないが、&lt;br&gt;
お腹のような部分が一定のリズムで膨らんだりしぼんだりしていて、&lt;br&gt;
肺呼吸に近い動きをしていることがよくわかる。&lt;/p&gt;
&lt;p&gt;&lt;img alt="貝のようにも見える" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan17.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan17_hu_fdda0933ba6398df.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan17_hu_a1e7f526a53df72b.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan17.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;特に害があるわけでもないので今のところ駆除はせずに撫でているが、&lt;br&gt;
一体何者なんだ&amp;hellip;?&lt;/p&gt;
&lt;p&gt;&lt;img alt="いもむしの 正体見たり 眠るねこ" class="gallery-image" data-flex-basis="401px" data-flex-grow="167" height="1186" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan18.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan18_hu_9dadccc9664a19c9.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan18_hu_f831cc9da355b061.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan18.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;10月は暖かすぎてついに日本も熱帯地域になったのか&amp;hellip;と思っていたが、&lt;br&gt;
11月中旬からしっかり寒気がやってきた。&lt;/p&gt;
&lt;p&gt;そとちゃんは暖かい部屋でぬくぬく過ごしている。&lt;/p&gt;
&lt;p&gt;野良猫時代は冬の時期も屋外で生活していたことを考えると、&lt;br&gt;
その生活の過酷さを想像すると共に、今後は一生この生活をさせてあげたいと再認識する。&lt;/p&gt;
&lt;p&gt;でも、ちょっと野生の誇りみたいなのを忘れてるんじゃないかな&amp;hellip;?&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="真円に近いねこ" class="gallery-image" data-flex-basis="350px" data-flex-grow="145" height="1360" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan_hu_62bc263648e2acc0.jpeg 800w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan_hu_8cb1cf06f142b9d2.jpeg 1600w, https://blog.uzimihsr.com/post/2023-12-03-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>このブログをGithub PagesからFirebase Hostingに移行する</title><link>https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/</link><pubDate>Wed, 29 Nov 2023 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sotochan.jpeg" alt="Featured image of post このブログをGithub PagesからFirebase Hostingに移行する" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;ブログのお引越しをした。&lt;br&gt;
(old) &lt;a class="link" href="https://uzimihsr.github.io/" target="_blank" rel="noopener"
 &gt;https://uzimihsr.github.io/&lt;/a&gt; → (new) &lt;a class="link" href="https://blog.uzimihsr.com/" target="_blank" rel="noopener"
 &gt;https://blog.uzimihsr.com/&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GitHub Pagesでホスティングしていたこのブログのサイズが1GBを超えて更新できなくなってしまった&lt;/li&gt;
&lt;li&gt;Firebase Hostingにブログを移行した&lt;/li&gt;
&lt;li&gt;GitHub Actions上でのHugoビルドとFirebase Hostingへの自動デプロイを設定した&lt;/li&gt;
&lt;li&gt;Cloudflare Registrarで取得したドメインをFirebase Hostingで使えるようにした&lt;/li&gt;
&lt;li&gt;移行元のGitHub Pagesから移行先のFirebase HostingにJavaScriptでリダイレクトさせた&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="経緯"&gt;経緯
&lt;/h2&gt;&lt;p&gt;薄々気づいてはいたが、Hugo+GitHub Pagesで作ってるこのブログ(&lt;a class="link" href="https://uzimihsr.github.io/" target="_blank" rel="noopener"
 &gt;https://uzimihsr.github.io/&lt;/a&gt;)の合計サイズがかなり大きくなっていて、&lt;br&gt;
GitHub Pagesのビルドにめっちゃ時間がかかったり、たまにコケたりするようになった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="GitHub Pagesのビルド画面(これはたまたま成功したやつ)" class="gallery-image" data-flex-basis="318px" data-flex-grow="132" height="1046" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc01.png" srcset="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc01_hu_6944a2505a23f9d0.png 800w, https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc01.png 1388w" width="1388"&gt;&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;Uploaded artifact size of 1111429120 bytes exceeds the allowed size of 1 GB. Deployment might fail.&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;&lt;a class="link" href="https://docs.github.com/ja/pages/getting-started-with-github-pages/about-github-pages#github-pages%E3%81%AE%E5%88%A9%E7%94%A8%E4%B8%8A%E3%81%AE%E5%88%B6%E9%99%90" target="_blank" rel="noopener"
 &gt;GitHub Pagesの利用上の制限&lt;/a&gt;のページにもGitHub Pagesサイトのサイズは1GBが上限とちゃんと書いてある。&lt;br&gt;
(読んでなかったか、読んだことを忘れていた。ごめんなさい&amp;hellip;)&lt;/p&gt;
&lt;p&gt;かといってこれまで書き殴ってきた記事を消したりするのもあまり嬉しくないので、&lt;br&gt;
おとなしく別の場所にお引越しする。&lt;/p&gt;
&lt;h2 id="やること"&gt;やること
&lt;/h2&gt;&lt;p&gt;Webサイトのお引越し、あまりやったことがないのでほぼ手探りだが以下のような作業を想定している。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;移行先の選定
&lt;ul&gt;
&lt;li&gt;どこにお引越しするか決める&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;移行先にページを作成
&lt;ul&gt;
&lt;li&gt;実際にお引越し先にページを置いてみる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;(やる気があれば)移行先でのCI/CD設定
&lt;ul&gt;
&lt;li&gt;お引越し先でも自動でページがデプロイされるようにする&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;(やる気があれば)移行先のドメイン設定
&lt;ul&gt;
&lt;li&gt;自分の好きなドメイン名でアクセスできるようにする&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;移行元(GitHub Pages)から移行先へのリダイレクト設定
&lt;ul&gt;
&lt;li&gt;元のページを辿ってきた人が迷わないようにする&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="移行先の選定"&gt;移行先の選定
&lt;/h3&gt;&lt;p&gt;まずは移行先を決める。&lt;/p&gt;
&lt;p&gt;令和の時代、Webサイトのホスティングサービスは星の数ほど存在する。&lt;br&gt;
&amp;ldquo;Webホスティングサービス 比較&amp;quot;とかで検索すれば候補がいくらでも出てくるが、&lt;br&gt;
自分の要件とコストに合ったものを選ぶべき&amp;hellip;&lt;/p&gt;
&lt;p&gt;なのだが、今回は脳死でGoogle Cloudに乗っかることにする。&lt;br&gt;
理由は単純で、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;規模がデカくて当分サ終しなさそうだから&lt;/li&gt;
&lt;li&gt;個人的な事情(ひみつ)によりGoogle Cloudの&lt;a class="link" href="https://cloud.google.com/billing/docs/how-to/manual-payment?hl=ja" target="_blank" rel="noopener"
 &gt;クレジット&lt;/a&gt;が溜まっているから&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;という感じ。&lt;br&gt;
こんなテキトーでいいのかな？いいよ(個人の趣味だし)&lt;/p&gt;
&lt;p&gt;ただ、&lt;a class="link" href="https://cloud.google.com/solutions/web-hosting?hl=ja" target="_blank" rel="noopener"
 &gt;Google Cloudでのホスティング方法&lt;/a&gt;にも色々ある。&lt;br&gt;
一応クラウドをお仕事にしてきたエンジニアなので、&lt;br&gt;
練習としてCompute EngineやCloud Runでサーバ(コンテナ)を立ててデプロイや運用を頑張るべきなのでは&amp;hellip;とも思ったが、&lt;br&gt;
静的サイトなのにそんなことするの無駄に感じちゃったのと、&lt;br&gt;
何より運用を頑張りたくないから&lt;a class="link" href="https://firebase.google.com/products/hosting?hl=ja" target="_blank" rel="noopener"
 &gt;Firebase Hosting&lt;/a&gt;を採用する。&lt;br&gt;
&lt;a class="link" href="https://firebase.google.com/pricing?hl=ja" target="_blank" rel="noopener"
 &gt;料金&lt;/a&gt;を見た感じ10GBまでなら無料枠で使えそうなのもGood。&lt;/p&gt;
&lt;h3 id="移行先にページを作成"&gt;移行先にページを作成
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://gohugo.io/hosting-and-deployment/hosting-on-firebase/" target="_blank" rel="noopener"
 &gt;Hugo公式&lt;/a&gt;でHugo製のページをFirebase Hostingに載せる手順が紹介されているのでそれに従う。&lt;/p&gt;
&lt;p&gt;まずはブログ用のFirebaseプロジェクトを新規に作成。&lt;br&gt;
&lt;a class="link" href="https://firebase.google.com/docs/web/setup?hl=ja" target="_blank" rel="noopener"
 &gt;UIから作る方法&lt;/a&gt;は世の中にいっぱい転がってそうなので敢えてCLIで作ってみる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Firebase CLIの更新&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ npm install -g firebase-tools
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# CLIバージョン確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ firebase --version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;12.9.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ログイン&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ firebase login --reauth
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;プロジェクト作成。&lt;br&gt;
全世界で一意なプロジェクトIDを先に指定しなきゃいけないのが若干面倒。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 適当なIDでプロジェクトを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;project ID&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ firebase projects:create &lt;span class="nv"&gt;$PROJECT_ID&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;? What would you like to call your project? &lt;span class="o"&gt;(&lt;/span&gt;defaults to your project ID&lt;span class="o"&gt;)&lt;/span&gt; blog
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;✔ Creating Google Cloud Platform project
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;✔ Adding Firebase resources to Google Cloud Platform project
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🎉🎉🎉 Your Firebase project is ready! 🎉🎉🎉
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Project information:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - Project ID: &lt;span class="o"&gt;(&lt;/span&gt;project ID&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - Project Name: blog
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Firebase console is available at
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://console.firebase.google.com/project/&lt;span class="o"&gt;(&lt;/span&gt;project ID&lt;span class="o"&gt;)&lt;/span&gt;/overview
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;世の中に同じプロジェクトID(他の人が先に作ったやつ)がある場合はこんな感じで怒られるので、&lt;br&gt;
どうにかして一意なやつを考える必要がある。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ firebase projects:create &lt;span class="nv"&gt;$PROJECT_ID&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;? What would you like to call your project? &lt;span class="o"&gt;(&lt;/span&gt;defaults to your project ID&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;✖ Creating Google Cloud Platform project
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Error: Failed to create project because there is already a project with ID &lt;span class="o"&gt;(&lt;/span&gt;project ID&lt;span class="o"&gt;)&lt;/span&gt;. Please try again with a unique project ID.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Having trouble? Try again or contact support with contents of firebase-debug.log
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;次にHugoプロジェクトのディレクトリでFirebaseプロジェクトを初期化する。&lt;br&gt;
Firebase featuresは&lt;code&gt;Hosting: Configure files for Firebase Hosting and (optionally) set up GitHub Action deploys&lt;/code&gt;を選択。&lt;br&gt;
Firebaseプロジェクトは先ほど作成したものを選択。&lt;br&gt;
HugoでビルドしたページのHTMLとかは&lt;code&gt;public&lt;/code&gt;ディレクトリに出力されているのでそれをそのまま使う。&lt;br&gt;
CI/CDの設定は一旦スキップし、&lt;br&gt;
ページを上書きする系の質問はなんとなくNoとした。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ firebase init
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;######## #### ######## ######## ######## ### ###### ########&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;## ## ## ## ## ## ## ## ## ## ##&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;###### ## ######## ###### ######## ######### ###### ######&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;## ## ## ## ## ## ## ## ## ## ##&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;## #### ## ## ######## ######## ## ## ###### ########&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;You&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;re about to initialize a Firebase project in this directory:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; /path/to/blog
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;? Which Firebase features &lt;span class="k"&gt;do&lt;/span&gt; you want to &lt;span class="nb"&gt;set&lt;/span&gt; up &lt;span class="k"&gt;for&lt;/span&gt; this directory? Press Space to &lt;span class="k"&gt;select&lt;/span&gt; features, &lt;span class="k"&gt;then&lt;/span&gt; Enter to confirm your choices. Hosting: Configure files &lt;span class="k"&gt;for&lt;/span&gt; Firebase Hosting and &lt;span class="o"&gt;(&lt;/span&gt;optionally&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt; up GitHub Action &lt;span class="nv"&gt;deploys&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;===&lt;/span&gt; Project Setup
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;First, let&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;s associate this project directory with a Firebase project.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;You can create multiple project aliases by running firebase use --add,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;but &lt;span class="k"&gt;for&lt;/span&gt; now we&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;ll just &lt;span class="nb"&gt;set&lt;/span&gt; up a default project.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;? Please &lt;span class="k"&gt;select&lt;/span&gt; an option: Use an existing project
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;? Select a default Firebase project &lt;span class="k"&gt;for&lt;/span&gt; this directory: &lt;span class="o"&gt;(&lt;/span&gt;project ID&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;blog&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;i Using project &lt;span class="o"&gt;(&lt;/span&gt;project ID&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;blog&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;===&lt;/span&gt; Hosting Setup
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Your public directory is the folder &lt;span class="o"&gt;(&lt;/span&gt;relative to your project directory&lt;span class="o"&gt;)&lt;/span&gt; that
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;will contain Hosting assets to be uploaded with firebase deploy. If you
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;have a build process &lt;span class="k"&gt;for&lt;/span&gt; your assets, use your build&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;s output directory.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;? What &lt;span class="k"&gt;do&lt;/span&gt; you want to use as your public directory? public
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;? Configure as a single-page app &lt;span class="o"&gt;(&lt;/span&gt;rewrite all urls to /index.html&lt;span class="o"&gt;)&lt;/span&gt;? No
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;? Set up automatic builds and deploys with GitHub? No
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;? File public/404.html already exists. Overwrite? No
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;i Skipping write of public/404.html
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;? File public/index.html already exists. Overwrite? No
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;i Skipping write of public/index.html
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;i Writing configuration info to firebase.json...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;i Writing project information to .firebaserc...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;✔ Firebase initialization complete!
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;そうするとこんなファイルが生成されている。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.firebaserc&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;projects&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;default&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;(project ID)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;firebase.json&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;hosting&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;public&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;public&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;ignore&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;firebase.json&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;**/.*&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;**/node_modules/**&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;本当は文法とかちゃんと勉強するべきだろうけど、&lt;br&gt;
なんとなく&lt;code&gt;.firebaserc&lt;/code&gt;でFirebaseプロジェクトのIDを指定していて、&lt;br&gt;
&lt;code&gt;firebase.json&lt;/code&gt;でFirebase featureの種類と公開用ディレクトリの場所、&lt;br&gt;
ホスティングしないファイルのパターンが指定されてそう。&lt;/p&gt;
&lt;p&gt;早速Firebaseへのデプロイを試してみる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ hugo &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; firebase deploy
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Start building sites …
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hugo v0.98.0+extended darwin/arm64 &lt;span class="nv"&gt;BuildDate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;unknown
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;|&lt;/span&gt; EN
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-------------------+-------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Pages &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;236&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Paginator pages &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;123&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Non-page files &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;753&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Static files &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Processed images &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;1982&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Aliases &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;44&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Sitemaps &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Cleaned &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Total in &lt;span class="m"&gt;5024&lt;/span&gt; &lt;span class="nv"&gt;ms&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;===&lt;/span&gt; Deploying to &lt;span class="s1"&gt;&amp;#39;(project ID)&amp;#39;&lt;/span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;i deploying hosting
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;i hosting&lt;span class="o"&gt;[(&lt;/span&gt;project ID&lt;span class="o"&gt;)]&lt;/span&gt;: beginning deploy...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;i hosting&lt;span class="o"&gt;[(&lt;/span&gt;project ID&lt;span class="o"&gt;)]&lt;/span&gt;: found &lt;span class="m"&gt;5998&lt;/span&gt; files in public
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;✔ hosting&lt;span class="o"&gt;[(&lt;/span&gt;project ID&lt;span class="o"&gt;)]&lt;/span&gt;: file upload &lt;span class="nb"&gt;complete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;i hosting&lt;span class="o"&gt;[(&lt;/span&gt;project ID&lt;span class="o"&gt;)]&lt;/span&gt;: finalizing version...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;✔ hosting&lt;span class="o"&gt;[(&lt;/span&gt;project ID&lt;span class="o"&gt;)]&lt;/span&gt;: version finalized
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;i hosting&lt;span class="o"&gt;[(&lt;/span&gt;project ID&lt;span class="o"&gt;)]&lt;/span&gt;: releasing new version...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;✔ hosting&lt;span class="o"&gt;[(&lt;/span&gt;project ID&lt;span class="o"&gt;)]&lt;/span&gt;: release &lt;span class="nb"&gt;complete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;✔ Deploy complete!
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Project Console: https://console.firebase.google.com/project/&lt;span class="o"&gt;(&lt;/span&gt;project ID&lt;span class="o"&gt;)&lt;/span&gt;/overview
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Hosting URL: https://&lt;span class="o"&gt;(&lt;/span&gt;project ID&lt;span class="o"&gt;)&lt;/span&gt;.web.app
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;指定された&lt;code&gt;Hosting URL&lt;/code&gt;を開くとページが閲覧できるようになっている。&lt;/p&gt;
&lt;p&gt;&lt;img alt="すげー" class="gallery-image" data-flex-basis="297px" data-flex-grow="124" height="1527" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc02.png" srcset="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc02_hu_f3276ee6dc0d9d9c.png 800w, https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc02_hu_d549977e4bd6cfbb.png 1600w, https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc02.png 1894w" width="1894"&gt;&lt;/p&gt;
&lt;p&gt;やった〜。&lt;/p&gt;
&lt;h3 id="cicdの設定"&gt;CI/CDの設定
&lt;/h3&gt;&lt;p&gt;ページの手動デプロイができたので、&lt;br&gt;
さらに自動で簡単にデプロイできるようCI/CDを設定する。&lt;br&gt;
&lt;code&gt;firebase init&lt;/code&gt;を再度実行し、今度は&lt;code&gt;Hosting: Set up GitHub Action deploys&lt;/code&gt;を選択する。&lt;br&gt;
途中でGitHubへのログインを求められるが、&lt;br&gt;
これに応えることでFirebaseへのリリース権限を持つTokenがGitHub ActionsのSecrets(&lt;code&gt;FIREBASE_SERVICE_ACCOUNT_(project ID)&lt;/code&gt;)に自動登録される。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ firebase init
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;######## #### ######## ######## ######## ### ###### ########&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;## ## ## ## ## ## ## ## ## ## ##&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;###### ## ######## ###### ######## ######### ###### ######&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;## ## ## ## ## ## ## ## ## ## ##&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;## #### ## ## ######## ######## ## ## ###### ########&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;You&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;re about to initialize a Firebase project in this directory:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; /path/to/uzimihsr/blog
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Before we get started, keep in mind:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; * You are initializing within an existing Firebase project directory
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;? Which Firebase features &lt;span class="k"&gt;do&lt;/span&gt; you want to &lt;span class="nb"&gt;set&lt;/span&gt; up &lt;span class="k"&gt;for&lt;/span&gt; this directory? Press Space to &lt;span class="k"&gt;select&lt;/span&gt; features, &lt;span class="k"&gt;then&lt;/span&gt; Enter to confirm your choices. Hosting: Set up GitHub Action &lt;span class="nv"&gt;deploys&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;===&lt;/span&gt; Project Setup
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;First, let&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;s associate this project directory with a Firebase project.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;You can create multiple project aliases by running firebase use --add,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;but &lt;span class="k"&gt;for&lt;/span&gt; now we&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;ll just &lt;span class="nb"&gt;set&lt;/span&gt; up a default project.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;i Using project &lt;span class="o"&gt;(&lt;/span&gt;project ID&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;blog&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;===&lt;/span&gt; Hosting:github Setup
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;i Detected a .git folder at /path/to/uzimihsr/blog
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;i Authorizing with GitHub to upload your service account to a GitHub repository&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;s secrets store.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Visit this URL on this device to log in:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://github.com/login/oauth/authorize?client_id&lt;span class="o"&gt;=&lt;/span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Waiting &lt;span class="k"&gt;for&lt;/span&gt; authentication...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;✔ Success! Logged into GitHub as uzimihsr
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;? For which GitHub repository would you like to &lt;span class="nb"&gt;set&lt;/span&gt; up a GitHub workflow? &lt;span class="o"&gt;(&lt;/span&gt;format: user/repository&lt;span class="o"&gt;)&lt;/span&gt; uzimihsr/blog
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;✔ Created service account github-action-201048321 with Firebase Hosting admin permissions.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;✔ Uploaded service account JSON to GitHub as secret FIREBASE_SERVICE_ACCOUNT_&lt;span class="o"&gt;(&lt;/span&gt;project ID&lt;span class="o"&gt;)&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;i You can manage your secrets at https://github.com/uzimihsr/blog/settings/secrets.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;? Set up the workflow to run a build script before every deploy? No
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;✔ Created workflow file /path/to/uzimihsr/blog/.github/workflows/firebase-hosting-pull-request.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;? Set up automatic deployment to your site&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;s live channel when a PR is merged? Yes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;? What is the name of the GitHub branch associated with your site&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;s live channel? master
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;✔ Created workflow file /path/to/uzimihsr/blog/.github/workflows/firebase-hosting-merge.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;i Action required: Visit this URL to revoke authorization &lt;span class="k"&gt;for&lt;/span&gt; the Firebase CLI GitHub OAuth App:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://github.com/settings/connections/applications/...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;i Action required: Push any new workflow file&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; to your repo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;i Writing configuration info to firebase.json...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;i Writing project information to .firebaserc...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;✔ Firebase initialization complete!
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;指示にしたがって最後まで進めると今度は次のようなファイルが生成される。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.github/workflows/firebase-hosting-merge.yml&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# This file was auto-generated by the Firebase CLI&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# https://github.com/firebase/firebase-tools&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Deploy to Firebase Hosting on merge&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;#39;on&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;push&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;branches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;master&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;build_and_deploy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/checkout@v3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;FirebaseExtended/action-hosting-deploy@v0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;repoToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;${{ secrets.GITHUB_TOKEN }}&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;firebaseServiceAccount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;${{ secrets.FIREBASE_SERVICE_ACCOUNT_(project ID) }}&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;channelId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;live&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;projectId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;(project ID)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;.github/workflows/firebase-hosting-pull-request.yml&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# This file was auto-generated by the Firebase CLI&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# https://github.com/firebase/firebase-tools&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Deploy to Firebase Hosting on PR&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;#39;on&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;pull_request&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;build_and_preview&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;if&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;${{ github.event.pull_request.head.repo.full_name == github.repository }}&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/checkout@v3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;FirebaseExtended/action-hosting-deploy@v0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;repoToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;${{ secrets.GITHUB_TOKEN }}&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;firebaseServiceAccount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;${{ secrets.FIREBASE_SERVICE_ACCOUNT_(project ID) }}&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;projectId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;(project ID)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これらの変更をcommitしてmasterブランチに取り込む。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git add .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git commit -m &lt;span class="s2"&gt;&amp;#34;Firebase&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git push origin master
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;masterブランチにcommitが取り込まれると、早速&lt;code&gt;.github/workflows/firebase-hosting-merge.yml&lt;/code&gt;で定義されたGitHub Actionsが実行される。&lt;/p&gt;
&lt;p&gt;&lt;img alt="GitHub Actionsがうごいた" class="gallery-image" data-flex-basis="699px" data-flex-grow="291" height="476" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc03.png" srcset="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc03_hu_d9e3d745c4128711.png 800w, https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc03.png 1387w" width="1387"&gt;&lt;/p&gt;
&lt;p&gt;これだけだとちょっとわかりづらいが、&lt;br&gt;
Firebase側で確認すると確かにGitHub Actionsからリリースが走ったことが確認できる。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Firebase側にGitHub ActionsのService Accountっぽいやつがリリースした形跡がある" class="gallery-image" data-flex-basis="414px" data-flex-grow="172" height="747" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc04.png" srcset="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc04_hu_fc4cc4823131b76a.png 800w, https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc04.png 1290w" width="1290"&gt;&lt;/p&gt;
&lt;p&gt;が、ここで問題が&amp;hellip;&lt;br&gt;
さっきまで見えていたFirebaseのページが&lt;code&gt;Page Not Found&lt;/code&gt;になってしまった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="かなC" class="gallery-image" data-flex-basis="326px" data-flex-grow="135" height="781" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc05.png" srcset="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc05_hu_b31f1b70230a4f6a.png 800w, https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc05.png 1062w" width="1062"&gt;&lt;/p&gt;
&lt;p&gt;元々このディレクトリでは&lt;code&gt;public&lt;/code&gt;ディレクトリの内容をGitHub Pages用のリポジトリ(uzimihsr/uzimihsr.github.io)に反映させるためにsubmodule化しており、&lt;br&gt;
おそらくGitHub Actions上ではこのディレクトリのファイルがファイルとして参照できてない?ような気がする。&lt;br&gt;
(ローカルで&lt;code&gt;firebase deploy&lt;/code&gt;したときは&lt;code&gt;public&lt;/code&gt;内のファイルが参照できていたのでリリース後にページが見られた)&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/actions/checkout" target="_blank" rel="noopener"
 &gt;actions/checkout&lt;/a&gt;のREADMEを確認したところ、&lt;br&gt;
&lt;code&gt;submodules&lt;/code&gt;というパラメータを指定することでsubmodule先のリポジトリが参照できるらしい。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.github/workflows/firebase-hosting-merge.yml&lt;/code&gt;を次のように変更、masterにpushして再挑戦。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Deploy to Firebase Hosting on merge&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;on&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;push&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;branches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;master&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;build_and_deploy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/checkout@v4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# v3→v4に変更&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;submodules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;recursive&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# submodulesを参照するためのパラメータ&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;FirebaseExtended/action-hosting-deploy@v0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;repoToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;${{ secrets.GITHUB_TOKEN }}&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;firebaseServiceAccount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;${{ secrets.FIREBASE_SERVICE_ACCOUNT_(project ID) }}&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;channelId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;live&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;projectId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;(project ID)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img alt="なんか権限足りてないっぽい" class="gallery-image" data-flex-basis="351px" data-flex-grow="146" height="1022" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc06.png" srcset="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc06_hu_d8f61ff0d8570e49.png 800w, https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc06.png 1495w" width="1495"&gt;&lt;/p&gt;
&lt;p&gt;今度はActionsがコケてしまった。&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;repository &amp;lsquo;&lt;a class="link" href="https://github.com/uzimihsr/uzimihsr.github.io.git/%27" target="_blank" rel="noopener"
 &gt;https://github.com/uzimihsr/uzimihsr.github.io.git/'&lt;/a&gt; not found
clone of &amp;lsquo;&lt;a class="link" href="mailto:git@github.com" &gt;git@github.com&lt;/a&gt;:uzimihsr/uzimihsr.github.io.git&amp;rsquo; into submodule path &amp;lsquo;/home/runner/work/blog/blog/public&amp;rsquo; failed&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;エラーメッセージ的に対象のリポジトリが参照できずエラーになっているっぽい。&lt;br&gt;
ここで思い出したのだが、対象のリポジトリ(uzimihsr/uzimihsr.github.io)はPrivateリポジトリだった。&lt;/p&gt;
&lt;p&gt;こういうときどうすんだろう&amp;hellip;と思い再度&lt;a class="link" href="https://github.com/actions/checkout#checkout-multiple-repos-private" target="_blank" rel="noopener"
 &gt;actions/checkout&lt;/a&gt;のREADMEを確認するとちゃんと答えがあった。&lt;br&gt;
checkout対象のPrivateリポジトリに関する権限を持つトークンを&lt;code&gt;token&lt;/code&gt;パラメータで指定すればいいらしい。&lt;br&gt;
本当は真面目に&lt;a class="link" href="https://github.com/actions/create-github-app-token#use-app-token-with-actionscheckout" target="_blank" rel="noopener"
 &gt;GitHub App作るべき&lt;/a&gt;な気もするが、&lt;br&gt;
今回はサクッと&lt;a class="link" href="https://docs.github.com/ja/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-fine-grained-personal-access-token" target="_blank" rel="noopener"
 &gt;Fine-grained PAT&lt;/a&gt;で対象Repoに対するRead権限を持つトークンを作成する。&lt;/p&gt;
&lt;p&gt;&lt;img alt="対象repoのみread権限を持つPAT" class="gallery-image" data-flex-basis="319px" data-flex-grow="133" height="958" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc07.png" srcset="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc07_hu_90bd23b53701910c.png 800w, https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc07.png 1275w" width="1275"&gt;&lt;/p&gt;
&lt;p&gt;このトークンをGitHub Actionsを実行するリポジトリのSecretsに追加。&lt;/p&gt;
&lt;p&gt;&lt;img alt="PATをActions Secretsとして保存" class="gallery-image" data-flex-basis="264px" data-flex-grow="110" height="1163" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc08.png" srcset="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc08_hu_41b4a00ba81f3cc3.png 800w, https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc08.png 1280w" width="1280"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.github/workflows/firebase-hosting-merge.yml&lt;/code&gt;にこのSecretを参照する記述を追加して再挑戦。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Deploy to Firebase Hosting on merge&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;on&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;push&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;branches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;master&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;build_and_deploy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/checkout@v4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;submodules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;recursive&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;${{ secrets.PRIVATE_REPO_READ_TOKEN }}&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Secretsに追加したFine-grained PAT&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;FirebaseExtended/action-hosting-deploy@v0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;repoToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;${{ secrets.GITHUB_TOKEN }}&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;firebaseServiceAccount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;${{ secrets.FIREBASE_SERVICE_ACCOUNT_(project ID) }}&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;channelId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;live&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;projectId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;(project ID)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img alt="うおおおおおおおおおお" class="gallery-image" data-flex-basis="473px" data-flex-grow="197" height="647" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc09.png" srcset="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc09_hu_cd6199c8ac327927.png 800w, https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc09.png 1277w" width="1277"&gt;&lt;/p&gt;
&lt;p&gt;今度はActionsが通った。&lt;br&gt;
Firebase上のページも404が解消されてコンテンツが表示できている。&lt;/p&gt;
&lt;p&gt;&lt;img alt="うれC" class="gallery-image" data-flex-basis="332px" data-flex-grow="138" height="1311" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc10.png" srcset="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc10_hu_a915db4c1b2189e6.png 800w, https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc10_hu_96173eea2a9cab82.png 1600w, https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc10.png 1814w" width="1814"&gt;&lt;/p&gt;
&lt;p&gt;やった〜。&lt;/p&gt;
&lt;p&gt;&amp;hellip;と思ったけど、ここで気になったことが1点。&lt;br&gt;
ビルドしたページを格納する&lt;code&gt;public&lt;/code&gt;ディレクトリをgit repoで管理し続ける必要ってあるんだろうか&amp;hellip;?&lt;/p&gt;
&lt;p&gt;Hugo公式のCI/CD設定手順でも&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;Don’t forget to update your static pages before push!&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;と紹介されているように、&lt;br&gt;
この手順だとmarkdownの更新とhugoによるページのビルド(&lt;code&gt;public&lt;/code&gt;ディレクトリの更新)は変わらずローカルPCで実施する必要がある。&lt;/p&gt;
&lt;p&gt;どうせGitHub Actionsを使うなら、&lt;br&gt;
Actions上でhugoを動かして&lt;code&gt;public&lt;/code&gt;ディレクトリを更新するようにして、&lt;br&gt;
ローカルでの作業はmarkdownの更新とgit pushだけにできないだろうか&amp;hellip;?&lt;br&gt;
(要はローカルPCからhugoを抜いても困らないようにしたい)&lt;/p&gt;
&lt;p&gt;GitHub Actions上でHugoを動かす方法についてちょっと調べると&lt;a class="link" href="https://github.com/peaceiris/actions-hugo" target="_blank" rel="noopener"
 &gt;peaceiris/actions-hugo@v2&lt;/a&gt;というものが出てきた。&lt;br&gt;
(&lt;a class="link" href="https://gohugo.io/hosting-and-deployment/hosting-on-github/" target="_blank" rel="noopener"
 &gt;Hugo公式のGitHub Pages対応ページ&lt;/a&gt;でもGitHub Actions上でHugoを動かす例はあるんだけど、今回はこのActionsを利用することにする)&lt;/p&gt;
&lt;p&gt;READMEにしたがって&lt;code&gt;.github/workflows/firebase-hosting-merge.yml&lt;/code&gt;に追記してみる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Deploy to Firebase Hosting on merge&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;on&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;push&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;branches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;master&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;build_and_deploy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/checkout@v4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;submodules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;recursive&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;${{ secrets.PRIVATE_REPO_READ_TOKEN }}&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;peaceiris/actions-hugo@v2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Actions上でのHugoセットアップ&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;hugo-version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;0.119.0&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;extended&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;hugo --minify&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Hugoビルドの実施&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;FirebaseExtended/action-hosting-deploy@v0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;repoToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;${{ secrets.GITHUB_TOKEN }}&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;firebaseServiceAccount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;${{ secrets.FIREBASE_SERVICE_ACCOUNT_(project ID) }}&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;channelId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;live&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;projectId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;(project ID)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;public&lt;/code&gt;ディレクトリ(submodule)が残ってると邪魔そうなのでついでに消す。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git submodule
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; e328611c605affe6d4672527704f3f5c730f5289 public &lt;span class="o"&gt;(&lt;/span&gt;heads/master&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 907f881f5d773d9d94a470fa5643fcaade904555 themes/hugo-theme-stack &lt;span class="o"&gt;(&lt;/span&gt;v1.1.0-282-g907f881&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git submodule deinit -f public
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Cleared directory &lt;span class="s1"&gt;&amp;#39;public&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Submodule &lt;span class="s1"&gt;&amp;#39;public&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;git@github.com:uzimihsr/uzimihsr.github.io.git&lt;span class="o"&gt;)&lt;/span&gt; unregistered &lt;span class="k"&gt;for&lt;/span&gt; path &lt;span class="s1"&gt;&amp;#39;public&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git submodule
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-e328611c605affe6d4672527704f3f5c730f5289 public
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 907f881f5d773d9d94a470fa5643fcaade904555 themes/hugo-theme-stack &lt;span class="o"&gt;(&lt;/span&gt;v1.1.0-282-g907f881&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git rm public
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rm &lt;span class="s1"&gt;&amp;#39;public&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ rm -rf .git/modules/public
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git submodule
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 907f881f5d773d9d94a470fa5643fcaade904555 themes/hugo-theme-stack &lt;span class="o"&gt;(&lt;/span&gt;v1.1.0-282-g907f881&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この状態でmaster pushしてみるとどうなるか&amp;hellip;?&lt;/p&gt;
&lt;p&gt;&lt;img alt="GitHub Actions上でHugoビルドできちゃった" class="gallery-image" data-flex-basis="432px" data-flex-grow="180" height="670" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc11.png" srcset="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc11_hu_280864c15c28da3b.png 800w, https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc11.png 1206w" width="1206"&gt;&lt;/p&gt;
&lt;p&gt;やった〜。&lt;/p&gt;
&lt;p&gt;最終的なGitHub Actionsの設定ファイルはこんな感じ。&lt;br&gt;
結局Privateリポジトリへの参照が要らなくなったのでPAT(Secrets)は削除した。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.github/workflows/firebase-hosting-merge.yml&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Deploy to Firebase Hosting on merge&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;on&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;push&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;branches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;master&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;build_and_deploy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/checkout@v4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;submodules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;recursive&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;peaceiris/actions-hugo@v2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;hugo-version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;0.119.0&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;extended&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;hugo --minify&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;FirebaseExtended/action-hosting-deploy@v0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;repoToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;${{ secrets.GITHUB_TOKEN }}&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;firebaseServiceAccount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;${{ secrets.FIREBASE_SERVICE_ACCOUNT_(project ID) }}&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;channelId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;live&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;projectId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;(project ID)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;.github/workflows/firebase-hosting-pull-request.yml&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Deploy to Firebase Hosting on PR&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;#34;on&amp;#34;: &lt;/span&gt;&lt;span class="l"&gt;pull_request&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;build_and_preview&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;if&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;${{ github.event.pull_request.head.repo.full_name == github.repository }}&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/checkout@v4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;submodules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;recursive&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;peaceiris/actions-hugo@v2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;hugo-version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;0.119.0&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;extended&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;hugo -D --minify&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;FirebaseExtended/action-hosting-deploy@v0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;repoToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;${{ secrets.GITHUB_TOKEN }}&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;firebaseServiceAccount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;${{ secrets.FIREBASE_SERVICE_ACCOUNT_(project ID) }}&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;projectId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;(project ID)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="ドメインの設定"&gt;ドメインの設定
&lt;/h3&gt;&lt;p&gt;Firebaseで公開したページはデフォルトで無料のドメイン&lt;code&gt;(project ID).web.app&lt;/code&gt;が付与されている。&lt;br&gt;
これがプロジェクト作成時にidをユニークにしたために結構ダサい名前になってしまったので、&lt;br&gt;
いい感じのドメインに変えてあげたい。&lt;br&gt;
(HTTPS化されてればドメインはあんまり気にしないつもりだったけど、idが想像以上にダサかったので&amp;hellip;)&lt;/p&gt;
&lt;p&gt;ドメイン取得はGoogle Domainsでやりたかったが、サ終しているので他を探す。&lt;br&gt;
いろいろ探した結果、&lt;a class="link" href="https://www.cloudflare.com/products/registrar/" target="_blank" rel="noopener"
 &gt;Cloudflare Registrar&lt;/a&gt;が一番安くてUIもしっかりしているので採用。&lt;br&gt;
&lt;strong&gt;uzimihsr.com&lt;/strong&gt;を取得した。&lt;br&gt;
(手順のメモを忘れたけど、クレカの登録ができれば後はとにかく簡単だった。費用は1年で$9.77くらい。)&lt;/p&gt;
&lt;p&gt;Firebase公式の&lt;a class="link" href="https://firebase.google.com/docs/hosting/custom-domain" target="_blank" rel="noopener"
 &gt;カスタム ドメインを接続する&lt;/a&gt;を参考に進めてみる。&lt;/p&gt;
&lt;p&gt;まずはFirebase Hosting側で先ほど取得したドメインを追加する。&lt;/p&gt;
&lt;p&gt;&lt;img alt="カスタムドメイン追加" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="406" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc12.png" width="722"&gt;&lt;/p&gt;
&lt;p&gt;この状態で続行するとDNSに登録すべきレコードが表示される。&lt;/p&gt;
&lt;p&gt;&lt;img alt="このレコードを登録すればいい" class="gallery-image" data-flex-basis="151px" data-flex-grow="63" height="947" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc13.png" width="597"&gt;&lt;/p&gt;
&lt;p&gt;この表示されているレコードをCloudflare側でDNSに追加する。&lt;/p&gt;
&lt;p&gt;&lt;img alt="UIからレコードをポチポチ追加" class="gallery-image" data-flex-basis="337px" data-flex-grow="140" height="965" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc14.png" srcset="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc14_hu_fa77b3766160b43d.png 800w, https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc14.png 1358w" width="1358"&gt;&lt;/p&gt;
&lt;p&gt;TXTレコードの設定をしてから反映されるまでにちょっと時間がかかる。&lt;br&gt;
30分くらい経つと&lt;code&gt;ドメインの準備&lt;/code&gt;が完了し、&lt;br&gt;
&lt;code&gt;ホスティングへの誘導&lt;/code&gt;で追加のレコードが表示されるのでこれを再度DNS側で追加する。&lt;/p&gt;
&lt;p&gt;&lt;img alt="追加で登録するレコードが出てきた" class="gallery-image" data-flex-basis="241px" data-flex-grow="100" height="594" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc15.png" width="597"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Aレコードを追加" class="gallery-image" data-flex-basis="634px" data-flex-grow="264" height="513" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc16.png" srcset="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc16_hu_cce35918317e362.png 800w, https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc16.png 1356w" width="1356"&gt;&lt;/p&gt;
&lt;p&gt;ここからの待ち時間が結構長い。&lt;br&gt;
最大24時間かかると言われたが、それ以上待っても状況が変化しなかった。&lt;/p&gt;
&lt;p&gt;泣きながら色々調べたらこんなのを発見。&lt;br&gt;
&lt;a class="link" href="https://community.cloudflare.com/t/flexible-ssl-redirect-loop-with-google-firebase/2063/3" target="_blank" rel="noopener"
 &gt;https://community.cloudflare.com/t/flexible-ssl-redirect-loop-with-google-firebase/2063/3&lt;/a&gt;&lt;br&gt;
&lt;a class="link" href="https://developers.cloudflare.com/ssl/troubleshooting/too-many-redirects/#flexible-encryption-mode" target="_blank" rel="noopener"
 &gt;https://developers.cloudflare.com/ssl/troubleshooting/too-many-redirects/#flexible-encryption-mode&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;どうやらオリジン(今回はFirebase Hosting)側でhttp→httpsへのリダイレクト設定がある状態でCloudflare側のSSL/TLS暗号化モードが&lt;code&gt;フレキシブル&lt;/code&gt;(デフォルト)だとリダイレクトループが発生するらしい。&lt;br&gt;
解決するにはこの暗号化モードを&lt;code&gt;フル&lt;/code&gt;に変更すれば良いとのこと。&lt;/p&gt;
&lt;p&gt;&lt;img alt="フレキシブル→フルに変更" class="gallery-image" data-flex-basis="468px" data-flex-grow="195" height="695" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc17.png" srcset="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc17_hu_621a9c94b45b21be.png 800w, https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc17.png 1357w" width="1357"&gt;&lt;/p&gt;
&lt;p&gt;するとあっさり&lt;code&gt;ホスティングへの誘導&lt;/code&gt;が完了し、対象のドメイン名でページが表示できるようになった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="うまくいったっぽい" class="gallery-image" data-flex-basis="812px" data-flex-grow="338" height="393" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc18.png" srcset="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc18_hu_c8de54abc54ab5d8.png 800w, https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc18.png 1331w" width="1331"&gt;&lt;/p&gt;
&lt;p&gt;0.00001%くらいの確率で今度ブログ以外にもページを作りたくなるかも&amp;hellip;と思ったので、&lt;br&gt;
ブログ専用のサブドメイン(&lt;strong&gt;blog.uzimihsr.com&lt;/strong&gt;)なども同様の手順で追加した。&lt;br&gt;
&lt;a class="link" href="https://blog.uzimihsr.com/" target="_blank" rel="noopener"
 &gt;https://blog.uzimihsr.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;最終的な設定はこんな感じ。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Firebase Hosting側のドメイン設定" class="gallery-image" data-flex-basis="575px" data-flex-grow="239" height="555" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc19.png" srcset="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc19_hu_7b1e327e8254eba.png 800w, https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc19.png 1330w" width="1330"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Cloudflare側のDNS設定" class="gallery-image" data-flex-basis="523px" data-flex-grow="218" height="622" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc20.png" srcset="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc20_hu_74aac9baca05586c.png 800w, https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc20.png 1357w" width="1357"&gt;&lt;/p&gt;
&lt;h3 id="移行元から移行先へのリダイレクト設定"&gt;移行元から移行先へのリダイレクト設定
&lt;/h3&gt;&lt;p&gt;ブログの移行ができたので、いよいよ移行元のGitHub Pagesが不要になった。&lt;/p&gt;
&lt;p&gt;本当はいきなり爆破できれば楽なんだけど、&lt;br&gt;
割といろんなところに記事のリンクを貼って(貼られて)しまっているので404になるのは好ましくない。&lt;/p&gt;
&lt;p&gt;というわけで移行元のURLでアクセスされたときに移行先の同じページにリダイレクトするようなページを作成して、&lt;br&gt;
既存のGitHub Pagesを差し替えるようにしたい。&lt;br&gt;
(例) &lt;a class="link" href="https://uzimihsr.github.io/post/2023-11-11-handmade-pc/" target="_blank" rel="noopener"
 &gt;https://uzimihsr.github.io/post/2023-11-11-handmade-pc/&lt;/a&gt; → &lt;a class="link" href="https://blog.uzimihsr.com/post/2023-11-11-handmade-pc/" target="_blank" rel="noopener"
 &gt;https://blog.uzimihsr.com/post/2023-11-11-handmade-pc/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ちょっとググってみたところGitHub Pagesでは&lt;code&gt;.htaccess&lt;/code&gt;が使えず301リダイレクトができないっぽいので、&lt;br&gt;
脳死でJavaScriptを使ったリダイレクトを試してみる。&lt;br&gt;
参考: &lt;a class="link" href="https://www.w3docs.com/snippets/javascript/how-to-redirect-a-web-page-with-javascript.html" target="_blank" rel="noopener"
 &gt;https://www.w3docs.com/snippets/javascript/how-to-redirect-a-web-page-with-javascript.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;index.html&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;en&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; &lt;span class="na"&gt;charset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;UTF-8&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Moved!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Moved!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;You will be redirected in 5 seconds...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;If you are not redirected, &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://blog.uzimihsr.com&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;click here&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newHost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://blog.uzimihsr.com&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;newHost&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;404.html&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;en&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; &lt;span class="na"&gt;charset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;UTF-8&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Moved!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Moved!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;newUrl&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;You will be redirected in 5 seconds...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;If you are not redirected, &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://blog.uzimihsr.com&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;click here&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newHost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://blog.uzimihsr.com&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;redirectUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;origin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;newHost&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;newUrl&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;new URL: &amp;#34;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;redirectUrl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;redirectUrl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;あとはGitHub Pagesにこの2枚のHTMLだけを残し、それ以外のファイルを全削除。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;pwd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/path/to/uzimihsr/uzimihsr.github.io
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls -a1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;..
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.git
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;404.html
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;index.html
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git add . 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git commit -m &lt;span class="s2"&gt;&amp;#34;bye-bye GitHub Pages&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git push origin master
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;元の&lt;a class="link" href="https://uzimihsr.github.io/" target="_blank" rel="noopener"
 &gt;https://uzimihsr.github.io/&lt;/a&gt;を開くと&lt;code&gt;index.html&lt;/code&gt;が開かれて
こんな感じになる。&lt;/p&gt;
&lt;p&gt;&lt;img alt="uzimihsr.github.io" class="gallery-image" data-flex-basis="363px" data-flex-grow="151" height="1005" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc21.png" srcset="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc21_hu_6752cf62c9ec63bd.png 800w, https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc21.png 1522w" width="1522"&gt;&lt;/p&gt;
&lt;p&gt;5秒放置すると&lt;a class="link" href="https://blog.uzimihsr.com/" target="_blank" rel="noopener"
 &gt;https://blog.uzimihsr.com/&lt;/a&gt;にジャンプ(リダイレクト)する。&lt;br&gt;
(JavaScriptが無効だと動かないけど)&lt;/p&gt;
&lt;p&gt;&lt;img alt="blog.uzimihsr.comにリダイレクトした" class="gallery-image" data-flex-basis="363px" data-flex-grow="151" height="1005" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc22.png" srcset="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc22_hu_40ec55740dc7b02b.png 800w, https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc22.png 1522w" width="1522"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2023-11-11-handmade-pc/" target="_blank" rel="noopener"
 &gt;https://uzimihsr.github.io/post/2023-11-11-handmade-pc/&lt;/a&gt;みたいにホスト名以降のパスが指定されている場合、&lt;code&gt;404.html&lt;/code&gt;によって&lt;a class="link" href="https://blog.uzimihsr.com/post/2023-11-11-handmade-pc/" target="_blank" rel="noopener"
 &gt;https://blog.uzimihsr.com/post/2023-11-11-handmade-pc/&lt;/a&gt;にリダイレクトする。&lt;/p&gt;
&lt;p&gt;&lt;img alt="旧ドメインで記事ごとのパスが指定された場合" class="gallery-image" data-flex-basis="363px" data-flex-grow="151" height="1005" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc23.png" srcset="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc23_hu_391abb0a264ea416.png 800w, https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc23.png 1522w" width="1522"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="ちゃんとblog.uzimihsr.comの同じ記事にリダイレクトした" class="gallery-image" data-flex-basis="363px" data-flex-grow="151" height="1005" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc24.png" srcset="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc24_hu_59f9815accee7d0.png 800w, https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sc24.png 1522w" width="1522"&gt;&lt;/p&gt;
&lt;p&gt;これで移行元から移行先へのリダイレクト設定もできた。&lt;/p&gt;
&lt;p&gt;ブログのお引越し作業は以上で終わり。&lt;/p&gt;
&lt;p&gt;おつかれさまでした&amp;hellip;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;手探りでめちゃめちゃ時間はかかったが、&lt;br&gt;
なんとかブログのお引越しができた(はず)。&lt;/p&gt;
&lt;p&gt;たいへんだった〜。&lt;br&gt;
Firebase Hostingならページのサイズは10Gまで無料だし、&lt;br&gt;
それを超えても課金すれば継続して利用できるはずなので&lt;br&gt;
きっと二度とやることはないでしょう&amp;hellip;🚩&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="お引越しは結構得意なねこ" class="gallery-image" data-flex-basis="392px" data-flex-grow="163" height="1094" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sotochan_hu_dfa0cd9dc6c11c53.jpeg 800w, https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sotochan_hu_dd84e014f6b846f3.jpeg 1600w, https://blog.uzimihsr.com/post/2023-11-29-moving-from-github-pages-to-firebase-hosting/sotochan.jpeg 1788w" width="1788"&gt;&lt;/p&gt;</description></item><item><title>自作PCを組んだ</title><link>https://blog.uzimihsr.com/post/2023-11-11-handmade-pc/</link><pubDate>Sat, 11 Nov 2023 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2023-11-11-handmade-pc/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2023-11-11-handmade-pc/sotochan.jpeg" alt="Featured image of post 自作PCを組んだ" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;初めて(ちゃんとした)自作PCを組んでみた。&lt;br&gt;
その過程で自作初心者の自分が考えたこととかのメモ。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;種類&lt;/th&gt;
 &lt;th&gt;名前+型番&lt;/th&gt;
 &lt;th&gt;税込価格(円)&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;CPU&lt;/td&gt;
 &lt;td&gt;&lt;a class="link" href="https://www.intel.co.jp/content/www/jp/ja/products/sku/230580/intel-core-i513500-processor-24m-cache-up-to-4-80-ghz/specifications.html" target="_blank" rel="noopener"
 &gt;Intel® Core™ i5-13500&lt;/a&gt;&lt;/td&gt;
 &lt;td&gt;34,980&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;マザーボード&lt;/td&gt;
 &lt;td&gt;&lt;a class="link" href="https://www.asus.com/jp/motherboards-components/motherboards/tuf-gaming/tuf-gaming-b660-plus-wifi-d4/" target="_blank" rel="noopener"
 &gt;ASUS TUF GAMING B660-PLUS WIFI D4&lt;/a&gt; (CPUとセット売り)&lt;/td&gt;
 &lt;td&gt;20,000&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;グラフィックボード&lt;/td&gt;
 &lt;td&gt;&lt;a class="link" href="https://jp.msi.com/Graphics-Card/GeForce-RTX-4070-VENTUS-2X-12G-OC" target="_blank" rel="noopener"
 &gt;MSI GeForce RTX™ 4070 VENTUS 2X 12G OC&lt;/a&gt;&lt;/td&gt;
 &lt;td&gt;85,800&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;CPUクーラー&lt;/td&gt;
 &lt;td&gt;&lt;a class="link" href="https://jp.deepcool.com/products/Cooling/cpuaircoolers/AK400-Performance-CPU-Cooler-1700-AM5/2021/15349.shtml" target="_blank" rel="noopener"
 &gt;DeepCool AK400 R-AK400-BKNNMN-G-1&lt;/a&gt;&lt;/td&gt;
 &lt;td&gt;3,480&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;メモリ&lt;/td&gt;
 &lt;td&gt;&lt;a class="link" href="https://www.crucial.jp/memory/ddr4/ct2k32g4dfd832a" target="_blank" rel="noopener"
 &gt;Crucial 64GB Kit (2 x 32GB) DDR4-3200 UDIMM CT2K32G4DFD832A&lt;/a&gt;&lt;/td&gt;
 &lt;td&gt;16,500&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;SSD&lt;/td&gt;
 &lt;td&gt;&lt;a class="link" href="https://www.westerndigital.com/ja-jp/products/internal-drives/wd-black-sn850x-nvme-ssd?sku=WDS100T2X0E" target="_blank" rel="noopener"
 &gt;Western Digital WD_BLACK SN850X NVMe™ SSD WDS100T2X0E&lt;/a&gt;&lt;/td&gt;
 &lt;td&gt;12,980&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;電源&lt;/td&gt;
 &lt;td&gt;&lt;a class="link" href="https://www.kuroutoshikou.com/product/detail/krpw-ga750w-90-.html" target="_blank" rel="noopener"
 &gt;玄人志向 KRPW-GA750W/90+&lt;/a&gt;&lt;/td&gt;
 &lt;td&gt;13,480&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;ケース&lt;/td&gt;
 &lt;td&gt;&lt;a class="link" href="https://www.xpg.com/jp/xpg/pc-component-valor-air-jp-compact-mid-tower-chassis" target="_blank" rel="noopener"
 &gt;ADATA XPG VALOR AIR JP2 VALORAIR-WHJ2&lt;/a&gt;&lt;/td&gt;
 &lt;td&gt;7,480&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;OS&lt;/td&gt;
 &lt;td&gt;&lt;a class="link" href="https://www.microsoft.com/ja-jp/d/windows-11-home/dg7gmgf0krt0" target="_blank" rel="noopener"
 &gt;Windows 11 Home&lt;/a&gt;&lt;/td&gt;
 &lt;td&gt;17,980&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;合計&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;td&gt;212,680&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;BTOの方が安く済んだとか言っちゃいけない。&lt;br&gt;
これは趣味です。&lt;/p&gt;
&lt;p&gt;性能については後で記述するが、&lt;br&gt;
ホグワーツ・レガシーが解像度UWQHD(3440×1440)の75fpsでそこそこ快適に遊べている。&lt;/p&gt;
&lt;h2 id="自分の理解度"&gt;自分の理解度
&lt;/h2&gt;&lt;p&gt;組み始める前の自作PCに関する知識はこんな感じ(だった)。&lt;br&gt;
ガッチガチのPC初心者というわけではないと思う。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;各パーツの役割やソフトウェア周り(BIOS/UEFI, OS)はなんとなく理解している&lt;/li&gt;
&lt;li&gt;組み立ての手順はわかっていない&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;だいぶ昔にBTOを利用したことはあるけど、&lt;br&gt;
自力で組んだことはないしパーツの選び方とかもよくわかっていなかった。&lt;/p&gt;
&lt;h2 id="目的予算"&gt;目的/予算
&lt;/h2&gt;&lt;p&gt;自作経験者に「自作PC組みたいんだよね〜」と聞くと必ず返ってくるのが&lt;br&gt;
「目的と予算は？」だと思う。&lt;br&gt;
今回はこんな感じ。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;目的
&lt;ul&gt;
&lt;li&gt;家にMacしかないのでWindows機が欲しい
&lt;ul&gt;
&lt;li&gt;Windows on MacOSの構成はあまりやりたくなかった&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.hogwartslegacy.com/ja-jp" target="_blank" rel="noopener"
 &gt;ホグワーツ・レガシー&lt;/a&gt;をストレスなく遊びたい&lt;/li&gt;
&lt;li&gt;ついでに動画編集もできるとうれしい&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;予算
&lt;ul&gt;
&lt;li&gt;20万円前後&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;それっぽい理由を並べているが、&lt;br&gt;
実際のところは&lt;strong&gt;ただ単に自作という行為に憧れがあった&lt;/strong&gt;というのが大きい。&lt;/p&gt;
&lt;h2 id="構成"&gt;構成
&lt;/h2&gt;&lt;p&gt;組み終わった今振り返ると、&lt;br&gt;
自作の工程で一番大変で一番楽しいのがパーツ選びだったように思う。&lt;/p&gt;
&lt;p&gt;とりあえず初心者がいろいろ考えたところでろくな結果にはならないと思い、&lt;br&gt;
今回は金だけ持って脳死で&lt;a class="link" href="https://shop.tsukumo.co.jp/" target="_blank" rel="noopener"
 &gt;ツクモ&lt;/a&gt;に行ってきた。&lt;/p&gt;
&lt;p&gt;なのでほぼ店員さんの受け売りにはなってしまうが、&lt;br&gt;
パーツ選びのときに考えたことを将来の自分のために書いておく。&lt;br&gt;
(店員さん忙しそうなのにめちゃ優しかったです、ありがとうございました)&lt;/p&gt;
&lt;p&gt;※情報は購入時(2023年9~10月ごろ)のもの&lt;/p&gt;
&lt;h3 id="cpu"&gt;CPU
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://www.intel.co.jp/content/www/jp/ja/products/sku/230580/intel-core-i513500-processor-24m-cache-up-to-4-80-ghz/specifications.html" target="_blank" rel="noopener"
 &gt;Intel® Core™ i5-13500&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Intelにした理由&lt;/strong&gt;&lt;br&gt;
お店に行くまではAMD(Ryzen)の方がIntel(Core)よりお手頃価格だと思っていたのだが、&lt;br&gt;
実際には最新のRyzen7000シリーズだとメモリの規格がDDR5に縛られてしまい、&lt;br&gt;
マザーボードとメモリを合わせたトータルだと13世代Intel Coreシリーズの方が若干安くなる計算になった。&lt;/p&gt;
&lt;p&gt;13世代はDDR4,5両対応だし、将来DDR5で組みたいとなった時にも使えるはず。&lt;br&gt;
(その頃にはCPUも新しいのが欲しくなってそうだが&amp;hellip;)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;13世代Core i5にした理由&lt;/strong&gt;&lt;br&gt;
性能について強いこだわりはなく、&lt;br&gt;
13世代Coreシリーズであればi5で十分、&lt;br&gt;
i7との差額をグラボの費用にあてるべきと判断した。&lt;/p&gt;
&lt;p&gt;i7以上だと冷却も水冷/簡易水冷を検討しなきゃいけなくて値段が嵩張るというのもある。&lt;/p&gt;
&lt;p&gt;12世代にしてもっと安くできたかもしれないが、&lt;br&gt;
自分が購入した時期だと12世代の在庫(選択の幅)が少なかった。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;内蔵GPU有りにした理由&lt;/strong&gt;&lt;br&gt;
内蔵GPU非搭載のモデル(近いやつだとi5-13400F)と若干迷ったが、&lt;br&gt;
グラボがぶっ壊れたときのトラブルシュートを考えて内蔵GPU有りのモデルにした。&lt;br&gt;
あと内蔵GPUの有無でそこまで値段が変わらなかった。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;本当の理由&lt;/strong&gt;&lt;br&gt;
マザーボードとセット売りされてて安かった。&lt;/p&gt;
&lt;h3 id="マザーボード"&gt;マザーボード
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://www.asus.com/jp/motherboards-components/motherboards/tuf-gaming/tuf-gaming-b660-plus-wifi-d4/" target="_blank" rel="noopener"
 &gt;ASUS TUF GAMING B660-PLUS WIFI D4&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ATXにした理由&lt;/strong&gt;&lt;br&gt;
デカいと組みやすい。&lt;br&gt;
組み終わった後で考えてみると、確かにパーツ同士の干渉とかを気にせず組めた気がする。&lt;br&gt;
(Micro-ATXとかの規格で組んだことないから正確なところはわからんが&amp;hellip;)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;DDR4にした理由&lt;/strong&gt;&lt;br&gt;
CPU選びの際にも触れたが、安いから。&lt;br&gt;
自分が選んだタイミングではDDR5対応のマザーボードが軒並みお高めだった。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Wi-fiモデルにした理由&lt;/strong&gt;&lt;br&gt;
ルーターとの距離とかもそんなにないので有線LANで良いのだが、&lt;br&gt;
Bluetoothを楽に使いたかった。&lt;br&gt;
組んだ後もネットワークは有線、デバイスはBluetoothで繋いでいる。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;本当の理由&lt;/strong&gt;&lt;br&gt;
CPUとセット売りされてて安かった。&lt;br&gt;
あと元々は12世代Coreシリーズ向けのモデルだが、&lt;br&gt;
お店でBIOSアップデート済みだったので余計な作業が発生せず助かった。&lt;br&gt;
(13世代CPUとセット売りだから当然と言われたらそれはそう)&lt;/p&gt;
&lt;h3 id="グラフィックボード"&gt;グラフィックボード
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://jp.msi.com/Graphics-Card/GeForce-RTX-4070-VENTUS-2X-12G-OC" target="_blank" rel="noopener"
 &gt;MSI GeForce RTX™ 4070 VENTUS 2X 12G OC&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;NVIDIAにした理由&lt;/strong&gt;&lt;br&gt;
なんとなく馴染みのあるメーカーだから。&lt;br&gt;
AMD Radeonも一瞬考えたけど、&lt;br&gt;
そこまで安くなかったのとCPUがAMDじゃないので相性とかも別にいいかな&amp;hellip;となった。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;RTX 4070にした理由&lt;/strong&gt;&lt;br&gt;
最初はVRAMの容量重視で4060Ti(VRAM 16GB)を考えていたんだけど、&lt;br&gt;
自分が使うモニターのスペック(UWQHD/75Hz)だとVRAMよりもコア数の方がカギになるとのことでちょっとお金を積んで4070にした。&lt;/p&gt;
&lt;p&gt;あとは電力効率が良く冷却のことをそこまで考えなくて良さそうだったのもポイント。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;MSIにした理由&lt;/strong&gt;&lt;br&gt;
一番安かった。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;本当の理由&lt;/strong&gt;&lt;br&gt;
RTX 4080以上のハイエンドだと流石に予算的にキツかったし、&lt;br&gt;
万が一壊したときのことを想像したくもなかった。&lt;br&gt;
あとCPUのボトルネックガーとか言われると泣きそうだった。&lt;/p&gt;
&lt;h3 id="cpuクーラー"&gt;CPUクーラー
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://jp.deepcool.com/products/Cooling/cpuaircoolers/AK400-Performance-CPU-Cooler-1700-AM5/2021/15349.shtml" target="_blank" rel="noopener"
 &gt;DeepCool AK400 R-AK400-BKNNMN-G-1&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;空冷にした理由&lt;/strong&gt;&lt;br&gt;
水冷はメンテが面倒&amp;hellip;と思っていたらメンテが簡単な簡易水冷というのもあるらしい。&lt;br&gt;
が、簡易水冷も冷却水が補充できないとかで寿命があったり、&lt;br&gt;
価格もお高めということで初心者も安心な空冷に落ち着いた。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CPU付属のクーラーにしなかった理由&lt;/strong&gt;&lt;br&gt;
今回のCPUにはトップフロー型のファンが付属でついていたが、&lt;br&gt;
性能が低いとのことで諦めた。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;このモデルにした理由&lt;/strong&gt;&lt;br&gt;
光ってないから。&lt;br&gt;
虹色は個人的に好きじゃないのと、&lt;br&gt;
下手に光ってねこちゃんにいたずらされるのが怖かった。&lt;/p&gt;
&lt;p&gt;あと安かった。&lt;br&gt;
この価格帯の中では性能が良くてかなり人気らしい。&lt;/p&gt;
&lt;p&gt;組み立てのことを考えるとグリス塗布済みなので自分で塗る必要がなくてうれしい。&lt;br&gt;
取り付け方の動画が公式で提供されてたのも助かった。&lt;br&gt;
&lt;div class="video-wrapper"&gt;
 &lt;iframe loading="lazy" 
 src="https://www.youtube.com/embed/gH0VOdlOgMw" 
 allowfullscreen 
 title="YouTube Video"
 &gt;
 &lt;/iframe&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;h3 id="メモリ"&gt;メモリ
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://www.crucial.jp/memory/ddr4/ct2k32g4dfd832a" target="_blank" rel="noopener"
 &gt;Crucial 64GB Kit (2 x 32GB) DDR4-3200 UDIMM CT2K32G4DFD832A&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;DDR4にした理由&lt;/strong&gt;&lt;br&gt;
CPU選びの際にも触れたが、やっぱり安いから。&lt;br&gt;
64GBだと特にDDR5より安かった。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;64GBにした理由&lt;/strong&gt;&lt;br&gt;
&lt;del&gt;メモリサイズでマウントをとりたかったから&lt;/del&gt;&lt;br&gt;
趣味で長めの動画や4K動画を書き出すことがあるので、&lt;br&gt;
快適に作業できるようにしたかった。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;このモデルにした理由&lt;/strong&gt;&lt;br&gt;
DDR4, 64GBの中では一番コスパが良さそうだった。&lt;br&gt;
あと光ってないから(重要)&lt;/p&gt;
&lt;h3 id="ssd"&gt;SSD
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://www.westerndigital.com/ja-jp/products/internal-drives/wd-black-sn850x-nvme-ssd?sku=WDS100T2X0E" target="_blank" rel="noopener"
 &gt;Western Digital WD_BLACK SN850X NVMe™ SSD WDS100T2X0E&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1TBにした理由&lt;/strong&gt;&lt;br&gt;
2TBでも良いかと思ったんだけど、値段を考慮して1TBにした。&lt;br&gt;
もし足りなくなってもメモリよりは追加しやすいはずだし&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;このモデルにした理由&lt;/strong&gt;&lt;br&gt;
読み出し速度が爆速だから。&lt;br&gt;
ゲーム用途を考えると速ければ速いほどいいらしい。&lt;/p&gt;
&lt;p&gt;あと光ってないから。&lt;br&gt;
(最近はSSDも光るらしい。気を抜くとPCパーツはすぐ光る)&lt;/p&gt;
&lt;h3 id="電源"&gt;電源
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://www.kuroutoshikou.com/product/detail/krpw-ga750w-90-.html" target="_blank" rel="noopener"
 &gt;玄人志向 KRPW-GA750W/90+&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;750Wにした理由&lt;/strong&gt;&lt;br&gt;
グラボとCPUの消費電力(200W+65W)を考慮するとだいたい2&lt;del&gt;3倍の650&lt;/del&gt;750Wくらいが良いと考えていた。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;このモデルにした理由&lt;/strong&gt;&lt;br&gt;
入門用の価格帯で一番パフォーマンスが良いとされるものを選んだ。&lt;br&gt;
あとケーブルがプラグイン方式なのも組み立ての際に配線が楽だった。&lt;/p&gt;
&lt;h3 id="ケース"&gt;ケース
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://www.xpg.com/jp/xpg/pc-component-valor-air-jp-compact-mid-tower-chassis" target="_blank" rel="noopener"
 &gt;ADATA XPG VALOR AIR JP2 VALORAIR-WHJ2&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;選んだ理由&lt;/strong&gt;&lt;br&gt;
とにかく安かった。&lt;br&gt;
ケースファンが元々3(前面)+1(背面)台ついていて、&lt;br&gt;
かつファンコントロール機能があるものの中では一番安かった。&lt;/p&gt;
&lt;p&gt;とにかく見た目を地味にしたかったので本当は側面が透明でないものがよかったが、&lt;br&gt;
今そんなモデルはほとんどないらしく実際にお店にも在庫がなかった。&lt;/p&gt;
&lt;h2 id="組み立て"&gt;組み立て
&lt;/h2&gt;&lt;p&gt;ねこに手伝ってもらいながらなんとか組み立てられた。&lt;/p&gt;
&lt;div class="video-wrapper"&gt;
 &lt;iframe loading="lazy" 
 src="https://www.youtube.com/embed/HGwMsoA1POo" 
 allowfullscreen 
 title="YouTube Video"
 &gt;
 &lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;パーツの取り付けは割とカンタンだった。&lt;br&gt;
決められたソケットに端子をはめ込んでいくだけなのでプラモデル感覚でできた。&lt;/p&gt;
&lt;p&gt;動画には残せてないが一番手間取ったのが配線。&lt;br&gt;
電源ケーブルをマザーボードのどこに刺すかでめちゃくちゃ迷った。&lt;/p&gt;
&lt;p&gt;最初の電源投入時は絶対失敗するとか画面に何も映らないとか聞いてたのでめちゃめちゃビビってたが、&lt;br&gt;
今回は運良く一発で起動できたので嬉しかった。&lt;/p&gt;
&lt;p&gt;最終的にパーツの取り付けからOSインストールまでは合計で4,5時間くらいかかった。&lt;br&gt;
休日を消しとばすにはいい趣味になりそう。&lt;/p&gt;
&lt;h2 id="性能"&gt;性能
&lt;/h2&gt;&lt;p&gt;動くものが組めたので性能を見てみる。&lt;/p&gt;
&lt;h3 id="cinebench"&gt;CINEBENCH
&lt;/h3&gt;&lt;p&gt;自作PCを組んだらまずはベンチマークを回すものらしいので&lt;a class="link" href="https://www.maxon.net/ja/downloads/cinebench-2024-downloads" target="_blank" rel="noopener"
 &gt;CINEBENCH 2024&lt;/a&gt;を試してみた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="CINEBENCH 2024" class="gallery-image" data-flex-basis="362px" data-flex-grow="151" height="981" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-11-handmade-pc/cinebench2024.png" srcset="https://blog.uzimihsr.com/post/2023-11-11-handmade-pc/cinebench2024_hu_b98a9f551aa8beb4.png 800w, https://blog.uzimihsr.com/post/2023-11-11-handmade-pc/cinebench2024.png 1483w" width="1483"&gt;&lt;/p&gt;
&lt;p&gt;スコアはこんな感じ。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Type&lt;/th&gt;
 &lt;th&gt;Score(pts)&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;GPU&lt;/td&gt;
 &lt;td&gt;16598&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;CPU(Multi Core)&lt;/td&gt;
 &lt;td&gt;1051&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;CPU(Single Core)&lt;/td&gt;
 &lt;td&gt;98&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;正直スコアの見方がよくわかっていないが、&lt;br&gt;
概ね他サイト等で公表されている値より10%低い程度なのでまあこんなものか&amp;hellip;? 誤差&amp;hellip;? &lt;br&gt;
何かが足を引っ張ってるのかもだけど、冷却の度合いとか色々条件があるんだろうな〜。&lt;br&gt;
極端に低いわけじゃないので、初期不良とか取り付けミスの線はあまりなさそうでひとまず安心。&lt;/p&gt;
&lt;p&gt;以下、ベンチマークの参考にさせていただいたサイト&lt;br&gt;
&lt;a class="link" href="https://www.cgdirector.com/cinebench-2024-scores/" target="_blank" rel="noopener"
 &gt;https://www.cgdirector.com/cinebench-2024-scores/&lt;/a&gt;&lt;br&gt;
&lt;a class="link" href="https://pcrecommend.com/cpu/cinebench2024/" target="_blank" rel="noopener"
 &gt;https://pcrecommend.com/cpu/cinebench2024/&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="ホグワーツレガシー"&gt;ホグワーツ・レガシー
&lt;/h3&gt;&lt;p&gt;そして自作PCを組んだ大きな目的だった、ホグワーツ・レガシー起動中の状況はこんな感じ。&lt;br&gt;
&lt;a class="link" href="https://jp.msi.com/Landing/afterburner/graphics-cards" target="_blank" rel="noopener"
 &gt;MSI Afterburner&lt;/a&gt;で左上にCPU,GPUの状態を表示させている。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ホグワーツ楽しい" class="gallery-image" data-flex-basis="573px" data-flex-grow="238" height="1440" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-11-handmade-pc/hogwarts.png" srcset="https://blog.uzimihsr.com/post/2023-11-11-handmade-pc/hogwarts_hu_3c75b7b6675ae08.png 800w, https://blog.uzimihsr.com/post/2023-11-11-handmade-pc/hogwarts_hu_7aaa0e417849e247.png 1600w, https://blog.uzimihsr.com/post/2023-11-11-handmade-pc/hogwarts_hu_2d40089a3869f6ed.png 2400w, https://blog.uzimihsr.com/post/2023-11-11-handmade-pc/hogwarts.png 3440w" width="3440"&gt;&lt;/p&gt;
&lt;p&gt;ゲーム側の設定は画質が最高品質、&lt;br&gt;
フレームレートは75fps(ディスプレイのリフレッシュレートが75Hzのため)、&lt;br&gt;
レイトレーシングOFF、&lt;br&gt;
その他はたぶんいじってない。&lt;/p&gt;
&lt;p&gt;解像度はUWQHD(3440×1440)なんだけど綺麗に表示できていて、&lt;br&gt;
フレームレートも常時75fpsに張り付いている。&lt;/p&gt;
&lt;p&gt;レイトレーシングをONにするとたまに重く感じることもあるが、&lt;br&gt;
素人の自分には正直ON/OFFの違いがわからなかったのでOFFにして遊んでいる。&lt;br&gt;
(まだ光が反射するような場面で遊んでないからかも&amp;hellip;)&lt;/p&gt;
&lt;p&gt;あとはVRAMの使用量が10GBくらいほどあり、&lt;br&gt;
12GBのVRAMで一応耐えられているか&amp;hellip;?という感じ。&lt;br&gt;
CPU, GPUの使用率は落ち着いているので多分楽しく遊べているんじゃないかな&amp;hellip;?&lt;br&gt;
一応&lt;a class="link" href="https://www.hogwartslegacy.com/ja-jp/pc-specs" target="_blank" rel="noopener"
 &gt;推奨スペックのULTRA仕様&lt;/a&gt;くらいは満たせてそうだし&amp;hellip;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;新しい趣味が増えるのはたのしい。&lt;br&gt;
ほぼ初めての経験でちょっと不安だったが、意外と動くものが組めてよかった。&lt;br&gt;
相談に乗ってくれたおともだちのみんなとツクモの優しい店員さんに感謝でございます。🙏&lt;/p&gt;
&lt;p&gt;またお金と時間に余裕ができたら今度はRyzen+Radeonで小型のものも組んでみたい。&lt;br&gt;
パーツ選びで見るべきポイントとかもなんとなくわかったので、&lt;br&gt;
暇な時にふらっとPC専門店に行ってパーツを眺めるのも楽しそうだな〜。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="PCに乗るねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-11-handmade-pc/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2023-11-11-handmade-pc/sotochan_hu_7d3179358863674f.jpeg 800w, https://blog.uzimihsr.com/post/2023-11-11-handmade-pc/sotochan_hu_c1c65c238a1fb4d.jpeg 1600w, https://blog.uzimihsr.com/post/2023-11-11-handmade-pc/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>10月のそとちゃん(2023)</title><link>https://blog.uzimihsr.com/post/2023-11-05-sotochan/</link><pubDate>Sun, 05 Nov 2023 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2023-11-05-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan.jpeg" alt="Featured image of post 10月のそとちゃん(2023)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;h3 id="まるい"&gt;まるい
&lt;/h3&gt;&lt;p&gt;最近はそとちゃんがまるまっていることが多かった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="まるい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan01_hu_319e8539552df4a3.jpeg 800w, https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan01_hu_22e21f7c8346ec89.jpeg 1600w, https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;なんかおとなしいな〜と思ったらだいたいバリバリボウルで丸くなっている。&lt;br&gt;
(ひなたぼっことか遊んでるときはそとちゃんがちょこちょこ喋るので音でわかる)&lt;/p&gt;
&lt;p&gt;&lt;img alt="逆巻き" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan02_hu_54b9b933f410d38f.jpeg 800w, https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan02_hu_cd401e00245cd4d6.jpeg 1600w, https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;さほど暖かくないボウル(段ボール製)の上でまるまるのは何か意図があるのだろうか&amp;hellip;?&lt;/p&gt;
&lt;p&gt;&lt;img alt="毛布だってあるのに…" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan03_hu_29deece78430c4b0.jpeg 800w, https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan03_hu_e51125b4b0107c7d.jpeg 1600w, https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan03.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;「私はこんなに寒い思いをしています」&lt;br&gt;
とアピールしてはやくこたつを出させようとする作戦かもしれない。&lt;/p&gt;
&lt;p&gt;でもこたつ出すとそとちゃん本当に動かなくなっちゃうし&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="すねてる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan04_hu_c17d03c2c1cbc061.jpeg 800w, https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan04_hu_6f1ae08912ed6eaa.jpeg 1600w, https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="右目の調子"&gt;右目の調子
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2023-09-09-sotochan/#%E6%B6%99%E3%82%84%E3%81%91%E5%95%8F%E9%A1%8C" target="_blank" rel="noopener"
 &gt;8月くらいから怪しかった右目の目ヤニ&lt;/a&gt;だが、&lt;br&gt;
だんだんと良くなってきた感じがする。&lt;/p&gt;
&lt;p&gt;&lt;img alt="調子いい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan05_hu_685fbd276cfa769c.jpeg 800w, https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan05_hu_11d20163394662bc.jpeg 1600w, https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan05.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;もちろん完全に出なくなることはないんだけど、&lt;br&gt;
ひどい時に比べるとドロっとした目ヤニは少なくなった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="多い時でもこれくらい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan07_hu_b29023e778e86bb0.jpeg 800w, https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan07_hu_427c22d37cd3bba6.jpeg 1600w, https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan07.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;目ヤニが少なければウェットシートで簡単に拭き取れるのでこちらも助かるし、&lt;br&gt;
そとちゃんも嫌なお手入れが短く済んでうれしそう。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ごきげん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan06_hu_b781b77cc4acb587.jpeg 800w, https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan06_hu_848b59f3932bd1f4.jpeg 1600w, https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan06.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;いいね〜&lt;/p&gt;
&lt;p&gt;&lt;img alt="きれいに拭けてるとき" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan08_hu_9706864175a7be51.jpeg 800w, https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan08_hu_cd970c1ff5104953.jpeg 1600w, https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan08.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="よく遊ぶ"&gt;よく遊ぶ
&lt;/h3&gt;&lt;p&gt;元々よく遊ぶそとちゃん。&lt;/p&gt;
&lt;p&gt;薄明薄暮性だからか、&lt;br&gt;
特に朝と夕方は元気に走り回っている。&lt;/p&gt;
&lt;p&gt;&lt;img alt="残像" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan09.jpeg" srcset="https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan09_hu_7fcd904768a18bd5.jpeg 800w, https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan09_hu_2cc0d85e822ea57b.jpeg 1600w, https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan09.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;朝は7~8時ごろにエンジンがかかり出す。&lt;br&gt;
(もしかしたらもっと早く起きてるかも?その時間は俺が寝てるからわからない)&lt;/p&gt;
&lt;p&gt;&lt;img alt="朝練の様子" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan10.jpeg" srcset="https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan10_hu_bc68719907e223af.jpeg 800w, https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan10_hu_85ce204e1e0b86c8.jpeg 1600w, https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan10.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;遊ぶところを見ていてほしいのか、&lt;br&gt;
一人遊びできるおもちゃで遊ぶ前にも必ず俺に向かって鳴いてくる。&lt;/p&gt;
&lt;p&gt;かわいい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="袋" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan11.jpeg" srcset="https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan11_hu_cee4ddc3154291b4.jpeg 800w, https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan11_hu_da8377b90ef8f546.jpeg 1600w, https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan11.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;夕方も17~18時くらいになると急に爆鳴きして走り回る。&lt;/p&gt;
&lt;p&gt;朝に比べると、&lt;br&gt;
夕方は一緒に遊ぶ系のおもちゃ(猫じゃらしとかねずみのおもちゃ)を期待していることが多い。&lt;/p&gt;
&lt;p&gt;&lt;img alt="猫じゃらし" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1771" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan12.jpeg" srcset="https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan12_hu_809ae9cf5fc26191.jpeg 800w, https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan12_hu_151908e6b88b95f1.jpeg 1600w, https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan12.jpeg 2362w" width="2362"&gt;&lt;/p&gt;
&lt;p&gt;それ以外におもちゃに強いこだわりはなく、&lt;br&gt;
目の前にあるものでなんでも遊んでくれる。&lt;/p&gt;
&lt;p&gt;&lt;img alt="トンネルに頭だけ隠すのが好き" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan13.jpeg" srcset="https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan13_hu_4d31d8a738a733b9.jpeg 800w, https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan13_hu_e4851aeb837f3e0b.jpeg 1600w, https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan13.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;たくさん遊んでえらい！&lt;/p&gt;
&lt;p&gt;&lt;img alt="疲れ果てた" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan14.jpeg" srcset="https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan14_hu_5923ec0a714a2435.jpeg 800w, https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan14_hu_757a5bb4e4bb12f0.jpeg 1600w, https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan14.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="ハロウィン"&gt;ハロウィン
&lt;/h3&gt;&lt;p&gt;今年のハロウィンもそとちゃんに仮装してもらった。&lt;/p&gt;
&lt;div class="video-wrapper"&gt;
 &lt;iframe loading="lazy" 
 src="https://www.youtube.com/embed/dgT1acUlWJI" 
 allowfullscreen 
 title="YouTube Video"
 &gt;
 &lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;やっぱりマントは嫌がらずに着てくれてかわいい。&lt;/p&gt;
&lt;p&gt;次はクリスマスかな&amp;hellip;?&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;9月に救急にお世話になったのを忘れてしまうくらい、&lt;br&gt;
10月のそとちゃんは元気だった。&lt;/p&gt;
&lt;p&gt;今年は10月でもまだまだ暖かい日が続いていて、&lt;br&gt;
体温調節がぶっ壊れるかと心配したがねこは平気な様子。&lt;/p&gt;
&lt;p&gt;そとちゃんははやくこたつに入りたがっているようだが、&lt;br&gt;
当分の間は暖房なしでも暮らせちゃいそう&amp;hellip;&lt;br&gt;
果たして11月はこたつの出番があるのだろうか&amp;hellip;?&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="怖い顔で爪を研ぐねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1329" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan_hu_5cc2c325e6de2e42.jpeg 800w, https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan_hu_234771dbdfb54f96.jpeg 1600w, https://blog.uzimihsr.com/post/2023-11-05-sotochan/sotochan.jpeg 1772w" width="1772"&gt;&lt;/p&gt;</description></item><item><title>9月のそとちゃん(2023)</title><link>https://blog.uzimihsr.com/post/2023-10-13-sotochan/</link><pubDate>Fri, 13 Oct 2023 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2023-10-13-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan.jpeg" alt="Featured image of post 9月のそとちゃん(2023)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;h3 id="病院"&gt;病院
&lt;/h3&gt;&lt;p&gt;年1回のワクチン接種で病院へ。&lt;/p&gt;
&lt;p&gt;毎度のことながらキャリーには自分から飛び込んでいく。&lt;/p&gt;
&lt;p&gt;&lt;img alt="やる気" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan01_hu_86ddfb3c5ba17956.jpeg 800w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan01_hu_89146500c60b2c60.jpeg 1600w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan01_hu_7b08f0a2258db348.jpeg 2400w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan01.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;いくらやる気があっても車移動がやっぱり苦手で、&lt;br&gt;
道中はずっと鳴いていた。&lt;/p&gt;
&lt;p&gt;病院についたころにはお疲れの様子。&lt;/p&gt;
&lt;p&gt;&lt;img alt="酷い目に遭いましたという顔" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan02_hu_2d5680a6fd602bfd.jpeg 800w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan02_hu_84ade4135e3c98a2.jpeg 1600w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan02_hu_b72af8efa696a2a7.jpeg 2400w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan02.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;診察室に入ると最初はビビって出てこなかったが、&lt;br&gt;
キャリーから出したあとは落ち着いていた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="診察台の上" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan03_hu_33e709cd2ba7c32c.jpeg 800w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan03_hu_eba5572dae3db9ae.jpeg 1600w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan03_hu_6615fe6f57ba7102.jpeg 2400w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan03.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;体重は4.1kg、体温は37.5℃。&lt;br&gt;
触診と心音も問題なしだった。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2022-10-07-sotochan/" target="_blank" rel="noopener"
 &gt;前回&lt;/a&gt;と違って、&lt;br&gt;
おしりで体温を測るときにあまり暴れずえらかった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="耐える" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan04_hu_798d7e24694cd61d.jpeg 800w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan04_hu_f7be8c5f031d28.jpeg 1600w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan04_hu_f128516e9b144f8b.jpeg 2400w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan04.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;先生が薬を取りに行っている間にまた探検。&lt;/p&gt;
&lt;p&gt;&lt;img alt="床の匂いをたどる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan05_hu_a64b7068c1bb1af8.jpeg 800w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan05_hu_e4579460ac7f67b9.jpeg 1600w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan05_hu_685394ac0062e1f3.jpeg 2400w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan05.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="ここが気になる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan06_hu_dfd569080047589f.jpeg 800w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan06_hu_e4d7a33f5ec669a2.jpeg 1600w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan06_hu_7572518d38b9c71b.jpeg 2400w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan06.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;元々注射は得意なので、ワクチンは暴れずにあっさり接種完了。&lt;br&gt;
たくさん探検して落ち着けたのも良かったかもしれない。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Vaccinated" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan07_hu_145a9d3cb4cd57ff.jpeg 800w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan07_hu_aca7a23c84590c1.jpeg 1600w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan07_hu_ea38dbcd1281d4e9.jpeg 2400w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan07.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;帰りの車内でもわんわん鳴いて、&lt;br&gt;
家に着いたらすぐお昼寝。&lt;/p&gt;
&lt;p&gt;&lt;img alt="つかれた" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan08_hu_ac2da4e44a2238e4.jpeg 800w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan08_hu_fa28ce9eeac2b10.jpeg 1600w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan08_hu_80dc515073be6124.jpeg 2400w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan08.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;おつかれさまでした。&lt;/p&gt;
&lt;h3 id="ソファ"&gt;ソファ
&lt;/h3&gt;&lt;p&gt;そとちゃんはソファの主である。&lt;/p&gt;
&lt;p&gt;そもそも家の主がそとちゃんだろうと言われればそれはそう&amp;hellip;&lt;br&gt;
なんだけど、最近は特にお気に入り。&lt;/p&gt;
&lt;p&gt;&lt;img alt="かわいいねぇ…" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan09.jpeg" srcset="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan09_hu_bbd9b8a42c6c386b.jpeg 800w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan09_hu_11acba32ae18fe3.jpeg 1600w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan09_hu_4cd065f48ca56991.jpeg 2400w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan09.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;爪とぎ防止のためにかけてた布を6月くらいから違うものに変えたのだが、&lt;br&gt;
その触感が気に入ったっぽい？&lt;/p&gt;
&lt;p&gt;気がつけばだいたいソファに座っている。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ここはねこのものです" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan10.jpeg" srcset="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan10_hu_6f20995332c9d126.jpeg 800w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan10_hu_87dffd8d5ce30537.jpeg 1600w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan10_hu_9b6a1088a60567eb.jpeg 2400w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan10.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;主なので当然なのだがそとちゃんはソファの真ん中に座る🤔&lt;/p&gt;
&lt;p&gt;元々2人がけの小さめソファなので、&lt;br&gt;
そとちゃんが真ん中に居ると人間が座る余地はない。&lt;/p&gt;
&lt;p&gt;&lt;img alt="贅沢な使い方" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan11.jpeg" srcset="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan11_hu_88fa002e4afb1e0f.jpeg 800w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan11_hu_f78f732807ef0e49.jpeg 1600w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan11_hu_d143dcc8115637ae.jpeg 2400w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan11.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;俺が床に直座りしてても譲る気はないらしい😭&lt;/p&gt;
&lt;p&gt;&lt;img alt="あげませんよの左手" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan13.jpeg" srcset="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan13_hu_20387dfd6b4ac478.jpeg 800w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan13_hu_1f6642ce6db9bd97.jpeg 1600w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan13_hu_11293d230c6e7c2f.jpeg 2400w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan13.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;気にいってくれたなら何よりです&amp;hellip;&lt;/p&gt;
&lt;h3 id="病院その2"&gt;病院その2
&lt;/h3&gt;&lt;p&gt;月末のある日のこと。&lt;/p&gt;
&lt;p&gt;晩ごはんを食べた後いつものようにそとちゃんをお腹の上に載せてまったりしていたら、&lt;br&gt;
体勢を変えようとしたそとちゃんがバランスを崩してベッドに落ちてしまった。&lt;/p&gt;
&lt;p&gt;嫌な予感がした。&lt;br&gt;
いつもならベッドに落ちそうになると爪を立ててふんばる(痛い)はず。&lt;/p&gt;
&lt;p&gt;抱っこしてみるといつもより力が抜けていてぐったりしていて、&lt;br&gt;
やっぱり様子がおかしい。&lt;/p&gt;
&lt;p&gt;意識ははっきりしていて呼びかけにも応えるんだけど、&lt;br&gt;
普段より元気が無くて一度座るとそのまま全然動かない。&lt;/p&gt;
&lt;p&gt;&lt;img alt="動かない" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="720" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan15.jpg" srcset="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan15_hu_fdb02f4aabe8a7e1.jpg 800w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan15.jpg 1280w" width="1280"&gt;&lt;/p&gt;
&lt;p&gt;試しに歩行を促しても数歩歩いたところですぐ座り込んでしまう。&lt;/p&gt;
&lt;p&gt;骨折や脱臼を疑い手足をさすってみても痛がるような反応はなかった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="大好きなねずみのおもちゃを出しても目で追うだけ" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="720" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan16.jpg" srcset="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan16_hu_ffdddade36e8e1a3.jpg 800w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan16.jpg 1280w" width="1280"&gt;&lt;/p&gt;
&lt;p&gt;これはまずいと思い、深夜だったが病院に電話。&lt;br&gt;
幸いすぐに診てくれるとのことだったので車で病院へ。&lt;/p&gt;
&lt;p&gt;車中ではいつも以上にそとちゃんが大騒ぎ。&lt;br&gt;
キャリーの中で爆鳴きしたかと思ったらすぐに吐いてしまった。&lt;/p&gt;
&lt;p&gt;病院に到着してすぐに診察。&lt;br&gt;
(事前に受け入れの準備をしてもらえていて非常にありがたかった)&lt;/p&gt;
&lt;p&gt;車中ではよく確認できなかったが嘔吐物は茶色で、&lt;br&gt;
晩ごはんの猫缶を吐いたような感じだった。&lt;/p&gt;
&lt;p&gt;診察でまず聞かれたのは誤飲の可能性。&lt;br&gt;
&lt;a class="link" href="https://uzimihsr.github.io/post/2020-08-13-sotochan/" target="_blank" rel="noopener"
 &gt;過去に一度やらかしている&lt;/a&gt;がそれ以降一度も変なものを飲みこんだことはなく、&lt;br&gt;
紐状や口に入るサイズのおもちゃの管理は気をつけていたはず。&lt;br&gt;
直近でおもちゃが消えたこともなかったのでこれはなさそう。&lt;/p&gt;
&lt;p&gt;先生によると呼吸が荒く、&lt;br&gt;
肺の音に乱れがあるので急いでレントゲンとエコーを撮ることになった。&lt;/p&gt;
&lt;p&gt;待合室で検査を待つこと30分。&lt;br&gt;
先生に「状態が良くないかもしれない」と言われたのを頭の中で繰り返してしまい、&lt;br&gt;
正気ではいられなかった。&lt;/p&gt;
&lt;p&gt;&amp;hellip;診察の結果。&lt;br&gt;
エコーやレントゲンの結果はとても綺麗で、
内臓や骨に大きな問題はなかった。&lt;/p&gt;
&lt;p&gt;強いて言えば血中酸素濃度が少し低く、胃と膵臓に若干炎症があるかも？というくらいだが、&lt;br&gt;
急性膵炎の場合はもっと高頻度で嘔吐するので違うだろうという診断。&lt;br&gt;
可能性を考えられるのは急性胃腸炎だが、&lt;br&gt;
1度吐いた後すっかり元気なので、&lt;strong&gt;なんとなくただ気持ち悪かっただけかもしれない&lt;/strong&gt;とのこと😭&lt;br&gt;
(呼吸や肺の音が荒かったのは吐いた直後だったからっぽい)&lt;/p&gt;
&lt;p&gt;精密検査は不要になったが、&lt;br&gt;
念のため急性胃腸炎の対症療法を行うことに。&lt;br&gt;
吐き気止めと消化器促進のお薬として&lt;a class="link" href="https://www.vm.nval.go.jp/public/detail/12529" target="_blank" rel="noopener"
 &gt;セレニア&lt;/a&gt;と&lt;a class="link" href="https://www.vm.nval.go.jp/public/detail/1501" target="_blank" rel="noopener"
 &gt;プリンペラン&lt;/a&gt;の注射、&lt;br&gt;
それと嘔吐で失った水分を補う皮下注射(点滴のようなもの)を打ってもらった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="処置後のそとちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan17.jpeg" srcset="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan17_hu_f56618abf8c99740.jpeg 800w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan17_hu_aab125827d34efc1.jpeg 1600w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan17_hu_8495155ad905ea32.jpeg 2400w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan17.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;処置後も元気にしていたので入院せずそのまま帰宅。&lt;br&gt;
注射をしたのでご飯を無理に食べさせる必要はないが(食べられるなら食べてもOK)、&lt;br&gt;
再度吐いたり呼吸が荒くなったらまた連れてくるようにとのことだった。&lt;/p&gt;
&lt;p&gt;帰宅後はそれまでが嘘だったかのように元気に部屋の中をうろうろ。&lt;/p&gt;
&lt;p&gt;なんとなくごはんを欲しがる素ぶりをしていたので試しにちゅーるをちらつかせたらあっさり食いつき、&lt;br&gt;
ものすごいスピードで完食。&lt;/p&gt;
&lt;p&gt;&lt;img alt="超元気" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan18.jpeg" srcset="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan18_hu_8edc01ee403dcbd4.jpeg 800w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan18_hu_5ba0b2733c031ebd.jpeg 1600w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan18_hu_77ed7c8aa9046f49.jpeg 2400w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan18.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;その後はいつも通り元気に夜鳴き&amp;amp;運動会をしてから就寝。&lt;/p&gt;
&lt;p&gt;翌朝も何事もなかったかのように寝ていた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="人の心配など知らないねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan19.jpeg" srcset="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan19_hu_748e262f6ce81444.jpeg 800w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan19_hu_9605ff84e33c241f.jpeg 1600w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan19_hu_b9eb664b5f261b5d.jpeg 2400w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan19.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;それ以降も吐いたり様子がおかしくなることはなく、&lt;br&gt;
いつもの元気に叫んで走り回るそとちゃんになった。&lt;br&gt;
よかった&amp;hellip;&lt;/p&gt;
&lt;p&gt;(お財布には大ダメージ💸)&lt;/p&gt;
&lt;p&gt;&lt;img alt="動物と暮らすということは大変です" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan20.jpeg" srcset="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan20_hu_8fb05d60ba2e0fa8.jpeg 800w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan20_hu_315e2f26852e05a9.jpeg 1600w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan20_hu_d5a5a77c025db764.jpeg 2400w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan20.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;9月は2回も病院に行くことになってしまい、&lt;br&gt;
しもべとしては大変だったが本人(ねこ)は至って元気だった。&lt;/p&gt;
&lt;p&gt;夜間救急にお世話になった件ではお金は飛んだが、&lt;br&gt;
様子が怪しいと思った時にすぐに行ける病院があることと、&lt;br&gt;
深夜でも躊躇なく病院に行く判断ができたのは良かったと思う。&lt;br&gt;
お金は飛んだが(重要)。&lt;/p&gt;
&lt;p&gt;ここからだんだん寒くなってくるはずだが、&lt;br&gt;
病院にかかることがないくらい元気に過ごしてもらいたい。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="ゲーミングPCの完成を祝うねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan_hu_5321d353e6d224a2.jpeg 800w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan_hu_791d6379e26ed46c.jpeg 1600w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan_hu_4b5606fe3a4da421.jpeg 2400w, https://blog.uzimihsr.com/post/2023-10-13-sotochan/sotochan.jpeg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>8月のそとちゃん(2023)</title><link>https://blog.uzimihsr.com/post/2023-09-09-sotochan/</link><pubDate>Sat, 09 Sep 2023 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2023-09-09-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan.jpeg" alt="Featured image of post 8月のそとちゃん(2023)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;h3 id="ハンモック"&gt;ハンモック
&lt;/h3&gt;&lt;p&gt;窓に取り付けてあるねこ用ハンモック。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ねこ専用" class="gallery-image" data-flex-basis="350px" data-flex-grow="145" height="1360" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan01_hu_ed44a2751e9358f4.jpeg 800w, https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan01_hu_96b5933c996418eb.jpeg 1600w, https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;8月はここがお気に入りだった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ねてる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan02_hu_746f64d4ae4f4709.jpeg 800w, https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan02_hu_f3c145249fa11a8a.jpeg 1600w, https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;毎朝必ずここにいて、どうやら夜もハンモックで寝ている様子。&lt;/p&gt;
&lt;p&gt;&lt;img alt="毎朝眼にする光景" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan03_hu_2e592e43cd0ef9d9.jpeg 800w, https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan03_hu_2f52f334e1ac133b.jpeg 1600w, https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan03.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;寝てない時は外で飛んでる鳥を観察したり、&lt;br&gt;
ベランダの洗濯物を監視してくれている。&lt;br&gt;
たすかる(?)&lt;/p&gt;
&lt;p&gt;(ちなみにクラッキングはしない。シャーと同様にやり方がわかってなさそう😹)&lt;/p&gt;
&lt;p&gt;&lt;img alt="超真剣" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan06_hu_350750f428a73e6d.jpeg 800w, https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan06_hu_bb909fe361345976.jpeg 1600w, https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan06.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="飽きた" class="gallery-image" data-flex-basis="327px" data-flex-grow="136" height="1454" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan05_hu_4dd9761b86c5280c.jpeg 800w, https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan05_hu_f64198289ea6d3fd.jpeg 1600w, https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan05.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;窓のカーテンが閉まっているとそとちゃん1人ではハンモックに登れないので、&lt;br&gt;
開けろ開けろとわんわん鳴いたりする。&lt;/p&gt;
&lt;p&gt;&lt;img alt="開けてもらえなかったときは仕方なくしろたんに乗る" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan07_hu_a2c1a15ea6693c13.jpeg 800w, https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan07_hu_84dc201d23e91a35.jpeg 1600w, https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan07.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;かわいいね〜&lt;/p&gt;
&lt;p&gt;&lt;img alt="よくねてる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan04_hu_a0245fa66badc61b.jpeg 800w, https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan04_hu_6d0a5c97ff786742.jpeg 1600w, https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="電動ねこじゃらし"&gt;電動ねこじゃらし
&lt;/h3&gt;&lt;p&gt;だいぶ前に買った電動ねこじゃらし。&lt;br&gt;
すぐ電池が切れちゃうのであんまり使っていなかった。&lt;/p&gt;
&lt;div class="video-wrapper"&gt;
 &lt;iframe loading="lazy" 
 src="https://www.youtube.com/embed/D5xUNnj5KDU" 
 allowfullscreen 
 title="YouTube Video"
 &gt;
 &lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;最近充電式電池を買ったので、&lt;br&gt;
久しぶりに出してみたらねこ大喜び。&lt;/p&gt;
&lt;p&gt;&lt;img alt="大興奮" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan08_hu_f3ff6ec0b596e41c.jpeg 800w, https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan08_hu_230649a5cb4cdab5.jpeg 1600w, https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan08.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;飽きずによく遊んでいる。&lt;/p&gt;
&lt;p&gt;たまに興奮しすぎて(ねこが)どっかに飛んでいくのが意味わかんなくておもしろい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="狩" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan09.jpeg" srcset="https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan09_hu_e7c79d84f4934b3b.jpeg 800w, https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan09_hu_f9185c9072d49945.jpeg 1600w, https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan09.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;安全のために何分か経ったら勝手に止まるようになってるんだけど、&lt;br&gt;
ねこは遊び足りなくてプレッシャーをかけてくる。&lt;/p&gt;
&lt;p&gt;&lt;img alt="早く動かしての顔" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan10.jpeg" srcset="https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan10_hu_7346926c38e974f9.jpeg 800w, https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan10_hu_385f510b98934b6b.jpeg 1600w, https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan10.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;たのしそうだし運動不足も解消できていいね〜&lt;/p&gt;
&lt;p&gt;&lt;img alt="しっぽびんびんでかわいい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan11.jpeg" srcset="https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan11_hu_1ebc8f94310ebfe3.jpeg 800w, https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan11_hu_6d305fe7ac103bb8.jpeg 1600w, https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan11.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="涙やけ問題"&gt;涙やけ問題
&lt;/h3&gt;&lt;p&gt;8月の後半あたりから右目の目ヤニというか涙やけがひどくなってきた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="かわいそう" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan12.jpeg" srcset="https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan12_hu_7ebf065f1deb27ac.jpeg 800w, https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan12_hu_31a0ea759856f105.jpeg 1600w, https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan12.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;毎年梅雨の時期にこの症状が出ていて、&lt;br&gt;
今年は珍しく落ち着いていると思ったが結局ちょっと遅れて来てしまった。😿&lt;/p&gt;
&lt;p&gt;&lt;img alt="ご飯食べるときが特にひどい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan13.jpeg" srcset="https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan13_hu_69cd8b11159cccac.jpeg 800w, https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan13_hu_af4eba1f4b95eae0.jpeg 1600w, https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan13.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;これ(猫風邪の後遺症)は保護されたときからのことで、&lt;br&gt;
病院でも治すのは難しいと言われているが&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="目ヤニを拭いた直後はこんな感じ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan15.jpeg" srcset="https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan15_hu_90bd32499155d1fb.jpeg 800w, https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan15_hu_c96780115c12ddd6.jpeg 1600w, https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan15.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;やっぱりみてるとこっちがつらくなってくる。&lt;/p&gt;
&lt;p&gt;例年涼しくなると症状がマシになるので、&lt;br&gt;
早くおさまってほしい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="目ヤニ拭かれるの得意じゃない" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan14.jpeg" srcset="https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan14_hu_dd119b5c310db9be.jpeg 800w, https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan14_hu_63dbfcc0d0072f2f.jpeg 1600w, https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan14.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;8月も元気だったそとちゃん。&lt;/p&gt;
&lt;p&gt;右目はかわいそうだけど、&lt;br&gt;
本人(ねこ)はあんまり気にしてないし毎日元気に食べて遊んで寝ている。&lt;/p&gt;
&lt;p&gt;今年の夏は暑すぎてあまりできていなかったが、&lt;br&gt;
またキャリーおさんぽにも行きたいので(というかねこが行きたがってそう)早く涼しくなってほしい。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="ハンモックでスヤスヤなねこ" class="gallery-image" data-flex-basis="362px" data-flex-grow="151" height="1312" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan_hu_ab62414090eb1a53.jpeg 800w, https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan_hu_40d5a378ed9cbeb9.jpeg 1600w, https://blog.uzimihsr.com/post/2023-09-09-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>7月のそとちゃん(2023)</title><link>https://blog.uzimihsr.com/post/2023-08-17-sotochan/</link><pubDate>Thu, 17 Aug 2023 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2023-08-17-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan.jpeg" alt="Featured image of post 7月のそとちゃん(2023)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;h3 id="ひなたぼっこ"&gt;ひなたぼっこ
&lt;/h3&gt;&lt;p&gt;夏。&lt;/p&gt;
&lt;p&gt;あつすぎる。&lt;/p&gt;
&lt;p&gt;なのにねこは毎日窓際でひなたぼっこ。&lt;/p&gt;
&lt;p&gt;暑くないのだろうか。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ご満悦" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan01_hu_a836f43e51e56557.jpeg 800w, https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan01_hu_ecf7ba59c63116bd.jpeg 1600w, https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan01_hu_2a520077a0616b3e.jpeg 2400w, https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan01.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;最近は日の出も早いので、&lt;br&gt;
欠かさず朝からスタンバイ。&lt;/p&gt;
&lt;p&gt;&lt;img alt="窓際でお日様待ち" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan02_hu_52fd8b72f8a8514e.jpeg 800w, https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan02_hu_bfee126a0aabb0ad.jpeg 1600w, https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan02_hu_250a9be02cedfc0d.jpeg 2400w, https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan02.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;天気が悪いと不機嫌になるくらいにはお日様が好き。&lt;/p&gt;
&lt;p&gt;&lt;img alt="くもりだった" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan03_hu_ef051d685d124871.jpeg 800w, https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan03_hu_1f288b5f83a3c94c.jpeg 1600w, https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan03_hu_8f9ab9c5921a8dd3.jpeg 2400w, https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan03.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;日に当たりすぎるのも良くないと思い時々抱っこして移動させるが、&lt;br&gt;
目を離すと勝手に窓際に戻ってしまう。&lt;/p&gt;
&lt;p&gt;&lt;img alt="熱中症なるよ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan04_hu_e4d6a1a84580c975.jpeg 800w, https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan04_hu_cd212801ebfc6323.jpeg 1600w, https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan04_hu_2fc40f52be13cd15.jpeg 2400w, https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan04.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;ねこは常に自分の気持ちよさ優先で、&lt;br&gt;
たとえ暑いと感じていても日差しが気持ちいいとやめられないとかなんとか。&lt;/p&gt;
&lt;p&gt;ちょっとアホなのがかわいい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="西日を浴びている" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan05_hu_8ac056cd535c0837.jpeg 800w, https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan05_hu_e2a84d62d8196083.jpeg 1600w, https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan05_hu_1d58d5c00cee44f.jpeg 2400w, https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan05.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;常にエアコンガンガンで部屋はそこまで暑くないし、&lt;br&gt;
そとちゃんが楽しいならいいか&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="本当に暑くないの？" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan06_hu_f358085ec7567f1b.jpeg 800w, https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan06_hu_ee0a84c07f61b0e4.jpeg 1600w, https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan06_hu_814786ac0719863c.jpeg 2400w, https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan06.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;h3 id="袋"&gt;袋
&lt;/h3&gt;&lt;p&gt;何十回目かの袋ブーム到来。&lt;/p&gt;
&lt;p&gt;&lt;img alt="いいね" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan07_hu_9da6a0740485e76b.jpeg 800w, https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan07_hu_f89de6458a5f6c4f.jpeg 1600w, https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan07_hu_5ed20303c89bf20c.jpeg 2400w, https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan07.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;ニトリさんのでかいレジ袋にクタクタになった紙袋を入れただけのいつものやつ。&lt;/p&gt;
&lt;p&gt;いつか捨てようとおもって放置していたらまた気に入られてしまった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="かくれてる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan08_hu_be45b6f7bfeb70a6.jpeg 800w, https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan08_hu_1c56b5c266a5614c.jpeg 1600w, https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan08_hu_780de75a585ede5f.jpeg 2400w, https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan08.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;最近はこの袋がもうビリビリに破けていて、&lt;br&gt;
ただ上から乗るだけの寝床になっている。&lt;/p&gt;
&lt;p&gt;&lt;img alt="もう袋としての機能はない" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan09.jpeg" srcset="https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan09_hu_93175bd1cdb78458.jpeg 800w, https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan09_hu_aec5ebd6b45ba2f6.jpeg 1600w, https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan09_hu_351cd3053e6e226.jpeg 2400w, https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan09.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;いい加減新しい袋に替えたいけど、&lt;br&gt;
捨てたら怒りそうだな&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="猫用ベッドより袋がいい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan10.jpeg" srcset="https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan10_hu_fc698426166a23bf.jpeg 800w, https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan10_hu_db1d03e98e50f830.jpeg 1600w, https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan10_hu_a224785fb2fbafc.jpeg 2400w, https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan10.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;ただただ書くのが遅い。&lt;/p&gt;
&lt;p&gt;そとちゃんは相変わらず元気。&lt;br&gt;
むしろ俺の方が暑さにやられてしまっているかもしれない。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="ソファのど真ん中に座るねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan_hu_780f9d9caf5baa8a.jpeg 800w, https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan_hu_cfada4ce47b149b4.jpeg 1600w, https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan_hu_edbd7f688dd2e690.jpeg 2400w, https://blog.uzimihsr.com/post/2023-08-17-sotochan/sotochan.jpeg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>6月のそとちゃん(2023)</title><link>https://blog.uzimihsr.com/post/2023-07-17-sotochan/</link><pubDate>Mon, 17 Jul 2023 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2023-07-17-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan.jpeg" alt="Featured image of post 6月のそとちゃん(2023)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;h3 id="草"&gt;草
&lt;/h3&gt;&lt;p&gt;一瞬の気の迷いでうっかり猫草を買ってしまった。&lt;br&gt;
(&lt;a class="link" href="https://uzimihsr.github.io/post/2021-09-30-sotochan/#%E8%8D%89" target="_blank" rel="noopener"
 &gt;前科&lt;/a&gt;があるのに&amp;hellip;)&lt;/p&gt;
&lt;p&gt;やっぱりそとちゃんは草が大好き🌱&lt;/p&gt;
&lt;p&gt;というか草ジャンキー。😵‍💫&lt;/p&gt;
&lt;p&gt;&lt;img alt="テイスティング" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan01_hu_61d6ae4cb0553df.jpeg 800w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan01_hu_9aa90a6f5580f3cf.jpeg 1600w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;大喜びでカッ喰らう。&lt;/p&gt;
&lt;p&gt;&lt;img alt="フードファイター" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan02_hu_bc671be55e3b67eb.jpeg 800w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan02_hu_72538f83dcf6ba16.jpeg 1600w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;そして吐く🤮&lt;br&gt;
(汚いので写真なし)&lt;/p&gt;
&lt;p&gt;あまりにも勢いよく食べては吐くのを繰り返してしまうので、&lt;br&gt;
ごほうびとしてたまにお風呂場であげることにした。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ライブ感" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan03_hu_791ee61f69cc9470.jpeg 800w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan03_hu_8df0de3fb27a94c2.jpeg 1600w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan03.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;右の奥歯を抜いてしまったので、&lt;br&gt;
うまく噛みきれずどうしても顔が左に傾いちゃうのがかわいそうだけどちょっとかわいい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="頭突っ込んで食べる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan04_hu_fd8d66381da558dd.jpeg 800w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan04_hu_ecccaf35a967dafb.jpeg 1600w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;草が室内にあるとそとちゃんが食べすぎてしまうので基本はベランダに置いていたが、&lt;br&gt;
そとちゃんはあまりにも草が好きすぎて窓に張り付く始末。&lt;/p&gt;
&lt;p&gt;日中はずーっと草を眺め続ける生活になってしまった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="本当にずっとみてる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan05_hu_450577ca90da7a06.jpeg 800w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan05_hu_ba9e2382af80d49c.jpeg 1600w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan05.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;また、お風呂場で草をあげるのが習慣化していたので&lt;br&gt;
「お風呂場に行く→草が出てくる」と覚えてしまった様子。&lt;/p&gt;
&lt;p&gt;&lt;img alt="草ちょーだいのポーズ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan06_hu_d60ff5e8729af625.jpeg 800w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan06_hu_d0957819333353cc.jpeg 1600w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan06.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;脱衣所のドアを閉めて入れないようにすると今度はその下から無理やり手を突っ込んできた。&lt;/p&gt;
&lt;p&gt;草への執着心がもはや中毒者のそれである。&lt;/p&gt;
&lt;p&gt;&lt;img alt="こわい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan07_hu_8aee5687d118293c.jpeg 800w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan07_hu_287fb9395c4f6ad5.jpeg 1600w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan07.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="キメかたが豪快" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan08_hu_70b4cf7db9287b05.jpeg 800w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan08_hu_2ba606c5ac0fc0a9.jpeg 1600w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan08.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;そんな草ライフを送っていたそとちゃんに悲劇。&lt;/p&gt;
&lt;p&gt;連日の猛暑に耐えきれず、&lt;br&gt;
草が日焼けして枯れてしまった😢&lt;/p&gt;
&lt;p&gt;&lt;img alt="かなしいね" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan09.jpeg" srcset="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan09_hu_4dc32e97dc96222.jpeg 800w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan09_hu_737f6034cde5f758.jpeg 1600w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan09.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;吐きすぎるとそとちゃんの健康にもよくないので、&lt;br&gt;
そのまま処分して代わりの草も買わないことにした。&lt;/p&gt;
&lt;p&gt;また俺の気が狂った時に買おう&amp;hellip;&lt;/p&gt;
&lt;h3 id="カーテン"&gt;カーテン
&lt;/h3&gt;&lt;p&gt;草を見張る目的で窓際にいることが多かったそとちゃんがカーテン遊びにハマってしまった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="大興奮" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan10.jpeg" srcset="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan10_hu_cd56bb700b9ca891.jpeg 800w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan10_hu_4ebd40108624fd2c.jpeg 1600w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan10.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;元々カーテンの生地が好きみたいでよく上に乗っていたのだが、&lt;br&gt;
最近は薄い布がひらひらするのが面白いようでよく遊んでいる。&lt;/p&gt;
&lt;p&gt;&lt;img alt="レース素材が好き？" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan11.jpeg" srcset="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan11_hu_8e7e1a58a5c644af.jpeg 800w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan11_hu_bb87144b0156d21a.jpeg 1600w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan11.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;もぐったりしばいたり(?)、遊び方は多彩。&lt;/p&gt;
&lt;p&gt;&lt;img alt="テントみたいだね" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan12.jpeg" srcset="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan12_hu_332466ded0b3d209.jpeg 800w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan12_hu_694c6fee05cfcaf8.jpeg 1600w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan12.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="草への思いをぶつけているのかもしれない" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan13.jpeg" srcset="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan13_hu_c786aa6233d6faaf.jpeg 800w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan13_hu_c2c1354c9629d0b7.jpeg 1600w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan13.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;カーテンが丈夫な素材でそとちゃんの爪では破けないのが幸い。&lt;/p&gt;
&lt;p&gt;思う存分遊んでストレス解消してくれればそれでいいです。&lt;/p&gt;
&lt;h3 id="ソファ"&gt;ソファ
&lt;/h3&gt;&lt;p&gt;そとちゃんのストレス解消法は他にもある。&lt;/p&gt;
&lt;p&gt;それはソファでの爪研ぎ😭&lt;/p&gt;
&lt;p&gt;&lt;img alt="一仕事終えた職人の顔" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan16.jpeg" srcset="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan16_hu_ac7072be13c6e9ee.jpeg 800w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan16_hu_d400816241e3253.jpeg 1600w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan16.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;以前から肘掛けのところをよく破壊していたのだが、&lt;br&gt;
流石にやりすぎて手応えがなくなったのか最近は座るところの側面がターゲットになっている。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ソファバリバリ職人による丁寧なバリバリ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan14.jpeg" srcset="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan14_hu_374cb92540df8e7.jpeg 800w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan14_hu_60993dd7c98c03b2.jpeg 1600w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan14.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;ひっくり返って仰向けになり、&lt;br&gt;
バリバリしながら移動していく。&lt;br&gt;
まるで天井に張り付いたクモのような洗練された動き🕷️ &lt;br&gt;
(動画を撮れなかったのが残念)&lt;/p&gt;
&lt;p&gt;&lt;img alt="この顔である" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan15.jpeg" srcset="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan15_hu_ce1113822d9aba32.jpeg 800w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan15_hu_19a63d6e7c98e72b.jpeg 1600w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan15.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;うちはのびのび教育がモットーなので&lt;br&gt;
そとちゃんに危険がない限りは何やっても怒らないんだけど、&lt;br&gt;
それでも糸くずが出たりクッションの中身が出るのが怖いので対策することにした。&lt;/p&gt;
&lt;p&gt;破壊された部分に雑に当て布をして補強🪡&lt;br&gt;
さらに座面に毛布をかけてバリバリしづらくした。&lt;/p&gt;
&lt;p&gt;&lt;img alt="裁縫上手" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan18.jpeg" srcset="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan18_hu_cd261d733f1c7d1.jpeg 800w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan18_hu_4050aff4ff0311b4.jpeg 1600w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan18.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;当て布にちょっと硬めの素材を選んだので、&lt;br&gt;
そとちゃんがバリバリしてもなかなか破けない👍&lt;/p&gt;
&lt;p&gt;&lt;img alt="不満げ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan17.jpeg" srcset="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan17_hu_33f4d4e82d4fc64c.jpeg 800w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan17_hu_cec74795bfff1fd9.jpeg 1600w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan17.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;なお、背もたれ側&amp;hellip;😭&lt;/p&gt;
&lt;p&gt;&lt;img alt="to be continued…" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan19.jpeg" srcset="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan19_hu_32302ec8125bce20.jpeg 800w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan19_hu_c8b6f89860912117.jpeg 1600w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan19.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;自分が最近妙に忙しく、&lt;br&gt;
書くのがめっちゃ遅くなってしまった。&lt;/p&gt;
&lt;p&gt;最近は猛暑日が続くけどそとちゃんは元気(エアコンガンガンだし)。&lt;br&gt;
毎日叫んで走り回っている。&lt;br&gt;
このまま夏バテ知らずで乗り切りたい。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="暴れつかれたねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan_hu_fece329553984ce2.jpeg 800w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan_hu_5544ed7ba03d20a4.jpeg 1600w, https://blog.uzimihsr.com/post/2023-07-17-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>5月のそとちゃん(2023)</title><link>https://blog.uzimihsr.com/post/2023-06-06-sotochan/</link><pubDate>Tue, 06 Jun 2023 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2023-06-06-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan.jpg" alt="Featured image of post 5月のそとちゃん(2023)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;h3 id="誕生日"&gt;誕生日
&lt;/h3&gt;&lt;p&gt;元野良なので誕生日がわからないそとちゃん。&lt;br&gt;
一応5月生まれということにしていて、今年で&lt;strong&gt;たぶん7さい&lt;/strong&gt;になった。&lt;/p&gt;
&lt;p&gt;今年の誕生日プレゼントはでかいキャットタワー。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;(たぶん)誕生日プレゼント &lt;a href="https://t.co/gYZXuybmcA"&gt;pic.twitter.com/gYZXuybmcA&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1652995423467114496?ref_src=twsrc%5Etfw"&gt;May 1, 2023&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;組み立て中から興味津々。&lt;/p&gt;
&lt;p&gt;&lt;img alt="現場監督" class="gallery-image" data-flex-basis="308px" data-flex-grow="128" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan01_hu_c4841241b192cc2a.jpeg 800w, https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan01_hu_59958692c5bdb0fd.jpeg 1600w, https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan01.jpeg 1914w" width="1914"&gt;&lt;/p&gt;
&lt;p&gt;今回買ったやつは天井と床に突っ張るタイプで、&lt;br&gt;
本当に天井ギリギリくらいまでの高さがある。&lt;/p&gt;
&lt;p&gt;&lt;img alt="最高峰" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan02_hu_b7cc81f4a089a908.jpeg 800w, https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan02_hu_f68d55f7e7358ad1.jpeg 1600w, https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;最大の特徴はこの透明なボウル。&lt;/p&gt;
&lt;p&gt;ここに入ってるところを下からみたらめっちゃかわいいんだろうな&amp;hellip;と思って買ったが、&lt;br&gt;
そとちゃんは透明な部分が穴に見えたみたいでなかなか入ってくれない。&lt;/p&gt;
&lt;p&gt;&lt;img alt="まだ信用できない" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan03_hu_1fbef4986a4d66e9.jpeg 800w, https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan03_hu_b3571e04876ad5dd.jpeg 1600w, https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan03.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;慣れてもらうためにお気に入りのおもちゃをボウルに入れてみた。&lt;/p&gt;
&lt;p&gt;浮いてるように見えるのが不思議みたいで興味を持ちはじめるそとちゃん。&lt;/p&gt;
&lt;p&gt;&lt;img alt="気になる" class="gallery-image" data-flex-basis="317px" data-flex-grow="132" height="1400" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan04_hu_9b1da8104132e9a2.jpeg 800w, https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan04_hu_9be4f783144950eb.jpeg 1600w, https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan04.jpeg 1851w" width="1851"&gt;&lt;/p&gt;
&lt;p&gt;そこからは割とあっさりで、&lt;br&gt;
おもちゃでちょこちょこ遊んでるな〜と思ってたら数分後にはすっぽり入っていた。&lt;/p&gt;
&lt;p&gt;たすかる〜〜😊&lt;/p&gt;
&lt;p&gt;&lt;img alt="もう慣れた" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan05_hu_eece2db269cff4e5.jpeg 800w, https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan05_hu_1ccc2da9df589d78.jpeg 1600w, https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan05.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;おまちかねのローアングルはこんな感じ。&lt;/p&gt;
&lt;p&gt;ご自慢のピンク肉球がぺったりついてて超かわいい&amp;hellip;🥰&lt;/p&gt;
&lt;p&gt;&lt;img alt="LOVE…" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan06_hu_b76c4d9a6c2407b9.jpeg 800w, https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan06_hu_e92a32563ce3866d.jpeg 1600w, https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan06.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;誕生日ごはんは例年ケーキを買ってアホみたいに残されるので、&lt;br&gt;
今年はシンプルにいつものおやつとちゅーるだけでお祝いした。&lt;/p&gt;
&lt;p&gt;今年も余裕の完食。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ごちそう &lt;a href="https://t.co/NjpaUe1vd8"&gt;pic.twitter.com/NjpaUe1vd8&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1653027020820066305?ref_src=twsrc%5Etfw"&gt;May 1, 2023&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;今年も無事に誕生日が迎えられてよかった。&lt;/p&gt;
&lt;p&gt;ちなみに今まで使ってたキャットタワーもいまだに現役。&lt;/p&gt;
&lt;p&gt;というか、1週くらいしたら結局元のタワーに登る方が多くなってしまって、&lt;br&gt;
新しいやつでは全然遊ばなくなってしまった&amp;hellip;&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;しっぽです &lt;a href="https://t.co/zdi0FkQ7AY"&gt;pic.twitter.com/zdi0FkQ7AY&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1663027599902412800?ref_src=twsrc%5Etfw"&gt;May 29, 2023&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;一瞬でも楽しんでくれたならOKです。&lt;/p&gt;
&lt;h3 id="記念写真"&gt;記念写真
&lt;/h3&gt;&lt;p&gt;ここ数年は毎年写真屋さんで誕生日の記念写真を撮ってもらっている。&lt;/p&gt;
&lt;p&gt;今年も同じところで撮ってもらった。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;被写体 &lt;a href="https://t.co/6q4AFayOG7"&gt;pic.twitter.com/6q4AFayOG7&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1660106336158498817?ref_src=twsrc%5Etfw"&gt;May 21, 2023&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;そとちゃんはやっぱりスタジオで大興奮。&lt;/p&gt;
&lt;p&gt;&lt;img alt="テンションMAX" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan07_hu_a98b05f10262887b.jpeg 800w, https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan07_hu_899df8f4365eac88.jpeg 1600w, https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan07.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;隅から隅まで探検する。&lt;/p&gt;
&lt;p&gt;&lt;img alt="調べまくり" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan08_hu_8acaea62e82e2268.jpeg 800w, https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan08_hu_30a7e06d040995e4.jpeg 1600w, https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan08.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;気が済むまでうろうろしてからいざ撮影。&lt;/p&gt;
&lt;p&gt;今年はそとちゃんが協力的だったのかカメラマンさんが上手なのか、&lt;br&gt;
結構スムーズに撮ることができた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="椅子でじっと待てるのえらすぎ" class="gallery-image" data-flex-basis="160px" data-flex-grow="66" height="2646" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan09.jpg" srcset="https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan09_hu_60d185c88ba5084e.jpg 800w, https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan09_hu_7eb0a36b71b3b28b.jpg 1600w, https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan09.jpg 1764w" width="1764"&gt;&lt;/p&gt;
&lt;p&gt;あとはおもちゃを大量に持参してカメラマンさんの後ろで振りまくったのがよかったのかもしれない。😂&lt;/p&gt;
&lt;p&gt;&lt;img alt="カメラ目線" class="gallery-image" data-flex-basis="160px" data-flex-grow="66" height="2646" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan10.jpg" srcset="https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan10_hu_f702d8c9fbc57c44.jpg 800w, https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan10_hu_91afd3b3cb6b74d8.jpg 1600w, https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan10.jpg 1764w" width="1764"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="お気に入りのねずみと一緒" class="gallery-image" data-flex-basis="160px" data-flex-grow="66" height="2646" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan11.jpg" srcset="https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan11_hu_bbdb22473ddf25fb.jpg 800w, https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan11_hu_762f5e5848ee84d3.jpg 1600w, https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan11.jpg 1764w" width="1764"&gt;&lt;/p&gt;
&lt;p&gt;今年は集中力が切れることもなく、
そとちゃん単体でもたっぷり撮ってもらうことができた。&lt;br&gt;
(去年は落ち着きがなさすぎて俺が無理やり抱っこして撮ったものが多かった)&lt;/p&gt;
&lt;p&gt;&lt;img alt="顔が良い" class="gallery-image" data-flex-basis="360px" data-flex-grow="150" height="1764" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan13.jpg" srcset="https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan13_hu_2d0d745cbdfedf77.jpg 800w, https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan13_hu_f6b40dfba1712e24.jpg 1600w, https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan13_hu_f48a5d19fcfddf7e.jpg 2400w, https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan13.jpg 2646w" width="2646"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="七五三的な…" class="gallery-image" data-flex-basis="360px" data-flex-grow="150" height="1764" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan12.jpg" srcset="https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan12_hu_c78188818b7dd355.jpg 800w, https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan12_hu_c0fe9bf0fd8b55d0.jpg 1600w, https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan12_hu_6ae72a5564a12a34.jpg 2400w, https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan12.jpg 2646w" width="2646"&gt;&lt;/p&gt;
&lt;p&gt;今年もかわいい写真をたくさん撮ってもらえてよかった。&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;そとちゃんが無事に7さいを迎えられた。&lt;br&gt;
推定3さいのころにお迎えしたので、もう丸4年一緒に暮らしていることになる。&lt;/p&gt;
&lt;p&gt;そとちゃんが保護されるまでよりも俺と暮らしている時間の方が長くなった(推定)というのはなんかうれしい。&lt;/p&gt;
&lt;p&gt;8さいも健康に迎えられるように頑張ろう&amp;hellip;&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="今年のベストショット" class="gallery-image" data-flex-basis="360px" data-flex-grow="150" height="1764" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan_hu_e757496bf0382ff5.jpg 800w, https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan_hu_8628a8b559bd918b.jpg 1600w, https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan_hu_ea7f68b0509c3b74.jpg 2400w, https://blog.uzimihsr.com/post/2023-06-06-sotochan/sotochan.jpg 2646w" width="2646"&gt;&lt;/p&gt;</description></item><item><title>4月のそとちゃん(2023)</title><link>https://blog.uzimihsr.com/post/2023-05-05-sotochan/</link><pubDate>Fri, 05 May 2023 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2023-05-05-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan.jpg" alt="Featured image of post 4月のそとちゃん(2023)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;h3 id="手術"&gt;手術
&lt;/h3&gt;&lt;p&gt;ついに&lt;a class="link" href="https://uzimihsr.github.io/post/2023-04-06-sotochan/#%E7%97%85%E9%99%A2" target="_blank" rel="noopener"
 &gt;スケーリング手術&lt;/a&gt;を行うことになったそとちゃん。&lt;/p&gt;
&lt;p&gt;全身麻酔の手術は2回目なので、そとちゃんも俺も慣れたもの。&lt;br&gt;
当日の体調もよく、キャリーにも自分から入り意気揚々と病院へ。&lt;/p&gt;
&lt;p&gt;&lt;img alt="やるき満々" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan01_hu_606d8531b201c11b.jpeg 800w, https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan01_hu_ecba39e8ce1f421d.jpeg 1600w, https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;それでも診察室に入ると急にぐずりだす。&lt;br&gt;
&lt;a class="link" href="https://uzimihsr.github.io/post/2021-09-30-sotochan/#%E7%97%85%E9%99%A2" target="_blank" rel="noopener"
 &gt;昔&lt;/a&gt;はあんなにはしゃいでたのに&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="なんか嫌 出たくない" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan02_hu_3740a0fea42cdefb.jpeg 800w, https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan02_hu_6622d5419fcd1670.jpeg 1600w, https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;なんとか(無理やり)引っ張り出し、&lt;br&gt;
当日の検査も体重4.1kg, 体温37.8℃でほぼ問題なし。&lt;/p&gt;
&lt;p&gt;全身麻酔と手術内容についての説明をしっかり受け、&lt;br&gt;
そとちゃんを預けた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="恒例のチョー怖い説明" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan11.jpeg" srcset="https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan11_hu_5fb7e0de7695bbc4.jpeg 800w, https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan11_hu_c82dba48c0352d03.jpeg 1600w, https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan11.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;俺はそのまま前回同様近所の神社で神頼み。&lt;/p&gt;
&lt;p&gt;術前術後の電話をもらい(手術自体はかなり早く終わった)、&lt;br&gt;
麻酔が切れたあとの経過観察が終わってから夕方にお迎え。&lt;/p&gt;
&lt;p&gt;ここで悲しいお知らせ。&lt;/p&gt;
&lt;p&gt;一番症状がひどかった右上の奥歯だが、&lt;br&gt;
ぐらつきがひどかったため抜歯になってしまった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="抜かれてしまった" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan03_hu_6c705f79c1c39540.jpeg 800w, https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan03_hu_862351627de1615c.jpeg 1600w, https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan03.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;これが術前の状態。&lt;br&gt;
奥歯が黒くなっているのと、他の歯も根本が若干黄色くなっている。&lt;/p&gt;
&lt;p&gt;&lt;img alt="赤丸で囲んだ部分が黒くなっている" class="gallery-image" data-flex-basis="384px" data-flex-grow="160" height="913" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan04.jpg" srcset="https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan04_hu_842687f57e9e77b1.jpg 800w, https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan04.jpg 1464w" width="1464"&gt;&lt;/p&gt;
&lt;p&gt;術後がこんな感じ。&lt;br&gt;
抜歯したほか、黄色く歯石がついていた部分を綺麗にしてもらった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="奥歯 なくなった" class="gallery-image" data-flex-basis="375px" data-flex-grow="156" height="981" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan05.jpg" srcset="https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan05_hu_578af839feff3dcf.jpg 800w, https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan05.jpg 1536w" width="1536"&gt;&lt;/p&gt;
&lt;p&gt;術後の説明も上記画像などを混ぜながら丁寧にしてもらった。&lt;br&gt;
口腔内にウイルス性の症状は見受けられなかった(単純に歯石がついていただけ)とのことで、&lt;br&gt;
追加の通院などは不要になった。&lt;/p&gt;
&lt;p&gt;術後のそとちゃんはこの表情。&lt;br&gt;
超しょんぼりしている。&lt;/p&gt;
&lt;p&gt;&lt;img alt="大変な思いをした" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan06_hu_7bc9d6addf76156e.jpeg 800w, https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan06_hu_c42bfa5747bdca5d.jpeg 1600w, https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan06.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;前回の手術のときもそうだったけど、&lt;br&gt;
麻酔で寝てる間におしっこがちょっと漏れておしりが汚れるのがめちゃめちゃ嫌みたい。&lt;br&gt;
かわいそう&amp;hellip;&lt;/p&gt;
&lt;p&gt;帰宅後は疲労困憊かと思いきやごはんをよこせと大騒ぎ。&lt;/p&gt;
&lt;p&gt;先生から「術後は痛みもあるしお水だけで大丈夫ですよ&amp;hellip;」と言われていたが、&lt;br&gt;
この日のそとちゃんは麻酔に備えて前日の夜10時から何も食べておらず腹ペコなのだった。&lt;/p&gt;
&lt;p&gt;すこしだけおやつを出したらすぐ完食。&lt;/p&gt;
&lt;p&gt;&lt;img alt="食欲モリモリ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan08_hu_e25d59fa753d3c52.jpeg 800w, https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan08_hu_6993641ec2039757.jpeg 1600w, https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan08.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;そんな感じで大変な一日が終了。&lt;/p&gt;
&lt;p&gt;翌日は心配なので丸一日付きっきりで様子を見ていたが、&lt;br&gt;
初めこそちょっとだるそうにしていたもののお昼頃にはいつも通り遊んで食べて寝ての生活に戻った。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ちょっと元気出てきた &lt;a href="https://t.co/oQPbuuYKAO"&gt;pic.twitter.com/oQPbuuYKAO&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1642753264642056193?ref_src=twsrc%5Etfw"&gt;April 3, 2023&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;一応処方してもらった痛み止めの薬もちゃんと飲んだ。&lt;br&gt;
えらい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="痛み止め" class="gallery-image" data-flex-basis="328px" data-flex-grow="136" height="1450" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan07_hu_837898eb8e780f68.jpeg 800w, https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan07_hu_fe41b2186e3a7f92.jpeg 1600w, https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan07.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;抜歯跡は出血もなく、綺麗に塞がった。&lt;br&gt;
1本だけ抜いたので噛み合わせが悪くなるのでは？と心配だったが、&lt;br&gt;
よくわかんないけどねこはそういうのあまり気にしない生き物らしい。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;くわ〜っ &lt;a href="https://t.co/mGdzi8pNCw"&gt;pic.twitter.com/mGdzi8pNCw&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1651193120137314307?ref_src=twsrc%5Etfw"&gt;April 26, 2023&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;とりあえずお口まわりの問題が無事に終わって良かった。&lt;/p&gt;
&lt;p&gt;ちなみに今回かかった費用はこんな感じ。&lt;br&gt;
お財布に大ダメージ&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="痛い出費" class="gallery-image" data-flex-basis="179px" data-flex-grow="74" height="1890" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan12.jpeg" srcset="https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan12_hu_b77c18bf379635a5.jpeg 800w, https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan12.jpeg 1417w" width="1417"&gt;&lt;/p&gt;
&lt;h3 id="こたつとさようなら"&gt;こたつとさようなら
&lt;/h3&gt;&lt;p&gt;そとちゃんにとって悲しい出来事がもう一つ。&lt;/p&gt;
&lt;p&gt;ついにこたつを撤去した。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;こたつ なくなった &lt;a href="https://t.co/Bo4fdRMWY6"&gt;pic.twitter.com/Bo4fdRMWY6&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1651842144699830274?ref_src=twsrc%5Etfw"&gt;April 28, 2023&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;片付ける片付けると言い続けてもう4月。&lt;br&gt;
4月も中旬からかなり暖かくなってきたのでいよいよ片付けることにした。&lt;/p&gt;
&lt;p&gt;まずはこたつがなくても部屋が暖かいことを理解してもらうため、&lt;br&gt;
こっそり電源を落とすところから&amp;hellip;&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;こたつの電源を落とすところから始めていく &lt;a href="https://t.co/v1huvgXKV7"&gt;pic.twitter.com/v1huvgXKV7&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1646334650258976768?ref_src=twsrc%5Etfw"&gt;April 13, 2023&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;が、ダメ。&lt;br&gt;
毎日こたつでゴロゴロしているそとちゃんにはすぐバレてしまった。&lt;/p&gt;
&lt;div class="video-wrapper"&gt;
 &lt;iframe loading="lazy" 
 src="https://www.youtube.com/embed/DKLskmQ6YRk" 
 allowfullscreen 
 title="YouTube Video"
 &gt;
 &lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;そとちゃんは意志が強いので、&lt;br&gt;
電源が入るまでこたつの周りをうろうろにゃんにゃんする。&lt;/p&gt;
&lt;p&gt;&lt;img alt="敢えてスイッチの前で待つ気合の入りよう" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan09.jpeg" srcset="https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan09_hu_d9726b7a94498123.jpeg 800w, https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan09_hu_43f93b2a959bbcd4.jpeg 1600w, https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan09.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;こうなるとそとちゃんと俺で根比べになるのだが、&lt;br&gt;
集中力が続かない俺と違ってそとちゃんはおもちゃやおやつにも釣られず命懸けで抗議を続ける。&lt;br&gt;
そんなそとちゃんに勝てるはずもなく、&lt;br&gt;
このときは片付けを断念。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;懸命の抗議活動で暖かいこたつを取り戻したねこ &lt;a href="https://t.co/REhyHn031i"&gt;pic.twitter.com/REhyHn031i&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1648567847159992320?ref_src=twsrc%5Etfw"&gt;April 19, 2023&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;しかしこの1週間後、転機が訪れる。&lt;br&gt;
たまたまタイミング良く(?)、そとちゃんがこたつ布団の上にGEROを吐いてしまったのだ。&lt;/p&gt;
&lt;p&gt;これでは仕方ないので速攻で布団を外して洗濯に。&lt;/p&gt;
&lt;p&gt;&lt;img alt="突然の撤去に驚き抗議の声も出ない" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan10.jpeg" srcset="https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan10_hu_797a5481d9825db1.jpeg 800w, https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan10_hu_4c43f7344d456b3.jpeg 1600w, https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan10.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;そんなわけで長く続いたそとちゃんのこたつ生活は割とあっけなく終了したのだった。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;かなしそう &lt;a href="https://t.co/ONevBHblnK"&gt;pic.twitter.com/ONevBHblnK&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1651888763675742209?ref_src=twsrc%5Etfw"&gt;April 28, 2023&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;今回の冬もたくさんお世話になったこたつ。&lt;br&gt;
また半年後くらいに会いましょう&amp;hellip;&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;こたつがなくても太陽がある &lt;a href="https://t.co/G9S7Zu8kKU"&gt;pic.twitter.com/G9S7Zu8kKU&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1646401869781274625?ref_src=twsrc%5Etfw"&gt;April 13, 2023&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;春は別れの季節なので(?)、4月はそとちゃんにとって悲しいイベントが多かった。&lt;br&gt;
かわいそう。&lt;/p&gt;
&lt;p&gt;歯の件は心配だったけど本人(ねこ)はあんまり気にしてない様子。&lt;br&gt;
せっかく綺麗にしてもらったのでこれを継続できるように歯みがきをがんばりたいところ。&lt;/p&gt;
&lt;p&gt;こたつは結構むりやり撤去してしまったが、&lt;br&gt;
2日も経たないうちに他の場所でごろごろするようになったのでこれもそんなに気にしてないと思いたい。&lt;br&gt;
というか4月下旬は流石にもう暑かったし&amp;hellip;&lt;/p&gt;
&lt;p&gt;5月でそとちゃんは(たぶん)7さいになる。&lt;br&gt;
一緒に暮らし始めてからもう4年になることにただただ驚き。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="今はもうごきげんなねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan_hu_a2deec1e25aee66.jpg 800w, https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan_hu_659fc65b3c381737.jpg 1600w, https://blog.uzimihsr.com/post/2023-05-05-sotochan/sotochan.jpg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>3月のそとちゃん(2023)</title><link>https://blog.uzimihsr.com/post/2023-04-06-sotochan/</link><pubDate>Thu, 06 Apr 2023 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2023-04-06-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan.jpeg" alt="Featured image of post 3月のそとちゃん(2023)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;h3 id="表情"&gt;表情
&lt;/h3&gt;&lt;p&gt;そとちゃんの表情はよくわからない。&lt;/p&gt;
&lt;p&gt;イカ耳になってるときのねこって不機嫌なはずなんだけど、&lt;br&gt;
そとちゃんはこんな感じで思いっきり耳を絞ってても喉をゴロゴロ鳴らしていたりする。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;この顔で超ごきげんなのよくわからない &lt;a href="https://t.co/HVxjfpJN9k"&gt;pic.twitter.com/HVxjfpJN9k&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1639193703070969856?ref_src=twsrc%5Etfw"&gt;March 24, 2023&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;この状態のときはなかなかひざから降りないので本当に機嫌がいいはず。&lt;/p&gt;
&lt;p&gt;逆に仰向けになってリラックスしてるようにみえるときでもめちゃめちゃ機嫌が悪いことがある。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;激おこねこちゃん &lt;a href="https://t.co/63boxsg8AP"&gt;pic.twitter.com/63boxsg8AP&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1636730000908128256?ref_src=twsrc%5Etfw"&gt;March 17, 2023&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;このときは頭をなでようとしただけでも攻撃してくる。&lt;br&gt;
どうして&amp;hellip;&lt;/p&gt;
&lt;p&gt;こんな感じでそとちゃんのご機嫌は表情からではよくわからない。&lt;br&gt;
結局のところ喉を鳴らしているかどうかで判断している。&lt;/p&gt;
&lt;p&gt;&amp;hellip;ちなみに喉を鳴らしながら何故か攻撃してくることもあるので本当のところはなにもわかっていない。&lt;/p&gt;
&lt;h3 id="テレビっ子"&gt;テレビっ子
&lt;/h3&gt;&lt;p&gt;去年の年末くらいに我が家にでかいテレビを導入した。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="qme" dir="ltr"&gt;&lt;a href="https://twitter.com/hashtag/WorldBaseballClassic?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#WorldBaseballClassic&lt;/a&gt; &lt;a href="https://t.co/XtlfABJaZE"&gt;pic.twitter.com/XtlfABJaZE&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1638316288941633536?ref_src=twsrc%5Etfw"&gt;March 21, 2023&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;それまで使っていた小さいテレビにはあまり興味がなさそうだったそとちゃんだが、&lt;br&gt;
さすがにこの大きさと明るさ(あと画質がチョーきれい)だと気になる様子。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://www.nhk.jp/p/nekoaruki/ts/6VPMR3P1WX/" target="_blank" rel="noopener"
 &gt;世界ネコ歩き&lt;/a&gt;を流しっぱなしにしてると結構集中して見ている。&lt;br&gt;
(前のテレビで流しても全然見なかった)&lt;/p&gt;
&lt;p&gt;ちなみにテレビに向かって話しかけたり画面にちょっかい出したりはしないので、&lt;br&gt;
映っているねこが本物じゃないというか本当はそこにいないことは理解してるっぽい。&lt;br&gt;
かしこい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ガン見" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan08_hu_292978cbaeafdbab.jpeg 800w, https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan08_hu_57094e057cdff401.jpeg 1600w, https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan08.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;最近のテレビはYouTubeも見られるということで、&lt;br&gt;
試しにこんな感じの鳥やら小動物がぴょこぴょこ映る猫用動画を流したら大ハマり。&lt;/p&gt;
&lt;div class="video-wrapper"&gt;
 &lt;iframe loading="lazy" 
 src="https://www.youtube.com/embed/dIq7E-l1b5k" 
 allowfullscreen 
 title="YouTube Video"
 &gt;
 &lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;こたつの上にどかっと座ってずーっと見ている。&lt;br&gt;
カウチポテト？&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;YouTubeを観る現代っ子 &lt;a href="https://t.co/h5MNczcJJZ"&gt;pic.twitter.com/h5MNczcJJZ&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1639863393703313410?ref_src=twsrc%5Etfw"&gt;March 26, 2023&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;仕事中にそとちゃんがめちゃ暴れてるときとかに流すと一瞬で大人しくなるので助かる。&lt;/p&gt;
&lt;p&gt;子供にYouTubeを観せて大人しくさせる親の気持ちがちょっとわかった気がする&amp;hellip;&lt;/p&gt;
&lt;h3 id="病院"&gt;病院
&lt;/h3&gt;&lt;p&gt;だいぶ前から&lt;a class="link" href="https://uzimihsr.github.io/post/2022-10-07-sotochan/" target="_blank" rel="noopener"
 &gt;歯石が気になっていた&lt;/a&gt;そとちゃんだったが、&lt;br&gt;
3月の中旬から毎日の歯磨きを本当に痛がるようになってしまったため病院へ行った。&lt;/p&gt;
&lt;p&gt;&lt;img alt="相変わらずキャリーバッグには意気揚々と入る" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan01_hu_4b5fd35793e585f6.jpeg 800w, https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan01_hu_e7262d7b69e11e9f.jpeg 1600w, https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;体重は4.08kgでいい感じ、&lt;br&gt;
体温は37.6度でちょっと低めだった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="病院に着いたら全然出てこない" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan02_hu_a114877da28133e7.jpeg 800w, https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan02_hu_28ea99389aab4cb5.jpeg 1600w, https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;診察してもらったところやはり歯肉炎が酷くなっていて、&lt;br&gt;
スケーリング(歯石除去)をすることになった。&lt;/p&gt;
&lt;p&gt;この日は施術を行わず、&lt;br&gt;
全身麻酔の準備として血液検査だけやってもらった。&lt;/p&gt;
&lt;p&gt;結果は&lt;a class="link" href="https://uzimihsr.github.io/post/2021-12-31-sotochan/" target="_blank" rel="noopener"
 &gt;毛包嚢胞の手術&lt;/a&gt;のときと同様にグロブリン(免疫機能を示すやつ)が高めで、&lt;br&gt;
やはり猫風邪の後遺症があるのだろうという話。&lt;br&gt;
それ以外の数値は問題なく健康だった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="だいたい問題なし" class="gallery-image" data-flex-basis="180px" data-flex-grow="75" height="4032" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan06_hu_149e8bdd8b3c04b4.jpeg 800w, https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan06_hu_34059989b323c930.jpeg 1600w, https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan06_hu_dd922e2ef110db44.jpeg 2400w, https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan06.jpeg 3024w" width="3024"&gt;
&lt;img alt="グロブリンだけ高め" class="gallery-image" data-flex-basis="180px" data-flex-grow="75" height="4032" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan07_hu_6b9d71b52641006a.jpeg 800w, https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan07_hu_40619cea4b543676.jpeg 1600w, https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan07_hu_cb651fbdd42cf61a.jpeg 2400w, https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan07.jpeg 3024w" width="3024"&gt;&lt;/p&gt;
&lt;p&gt;この日は天気が良かったので、&lt;br&gt;
診察後は久しぶりのお散歩がてら歩いて家まで帰った。&lt;/p&gt;
&lt;p&gt;病院から家の途中にはいい感じの池がある公園があって、&lt;br&gt;
そとちゃんは結構満喫していた様子。&lt;/p&gt;
&lt;p&gt;&lt;img alt="池の魚に夢中" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan03_hu_2e683eacecf5a32b.jpeg 800w, https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan03_hu_81037390f2e9195d.jpeg 1600w, https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan03.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;10分くらいずーっと見ていた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="桜も咲いてた(ピンボケしてるけど…)" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan04_hu_69688c8ed50923d7.jpeg 800w, https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan04_hu_fe11687ab66a68bd.jpeg 1600w, https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;結局1時間くらいお散歩して、家についたらごほうびタイム。&lt;br&gt;
ものすごい勢いでちゅーるを貪る。&lt;/p&gt;
&lt;p&gt;&lt;img alt="食いつきがすごい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan05_hu_419f304e797b11e2.jpeg 800w, https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan05_hu_8e2cf9c4726eb6ca.jpeg 1600w, https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan05_hu_4984c9e4275db152.jpeg 2400w, https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan05.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;全身麻酔の手術は不安だけど、&lt;br&gt;
とりあえずそとちゃんは元気だった。&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;かなりあったかくなってきて、そとちゃんは毎日いい感じ。&lt;br&gt;
よく遊んで食べて寝て元気に過ごしている。&lt;br&gt;
テレビばかりだと退屈しそうなのでそろそろお散歩を再開してもよさそう。&lt;/p&gt;
&lt;p&gt;ちなみにこたつはまだ片付けられていない。&lt;br&gt;
4月こそは強い意志を持って片付けたい。&lt;/p&gt;
&lt;p&gt;(ネタバレ?になるけどこの日記を書いている時点でスケーリングの手術は成功しているが、いろいろあったので来月ちゃんと書く)&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="大あくびするねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan_hu_1ef1dbb4aab7d838.jpeg 800w, https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan_hu_5b3b94a1790ca5fc.jpeg 1600w, https://blog.uzimihsr.com/post/2023-04-06-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>2月のそとちゃん(2023)</title><link>https://blog.uzimihsr.com/post/2023-03-14-sotochan/</link><pubDate>Tue, 14 Mar 2023 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2023-03-14-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2023-03-14-sotochan/sotochan.jpeg" alt="Featured image of post 2月のそとちゃん(2023)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;h3 id="お留守番"&gt;お留守番
&lt;/h3&gt;&lt;p&gt;大変申し訳ないのだが2月はそとちゃんにお留守番してもらう機会がちょっと多かった。&lt;/p&gt;
&lt;p&gt;そとちゃんは自立した大人の女性(推定6歳)だし、そんなのは余裕&amp;hellip;&lt;/p&gt;
&lt;p&gt;ではない。&lt;/p&gt;
&lt;p&gt;&lt;img alt="明らかに機嫌がよくない" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-03-14-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2023-03-14-sotochan/sotochan01_hu_62874953a84915ef.jpeg 800w, https://blog.uzimihsr.com/post/2023-03-14-sotochan/sotochan01_hu_4ccd19d8a3a20132.jpeg 1600w, https://blog.uzimihsr.com/post/2023-03-14-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;お留守番のときはこんな感じでめちゃめちゃ機嫌が悪くなる。&lt;/p&gt;
&lt;p&gt;普段俺が家にいてもごはんのときと遊ぶとき以外ほとんど寝てるのに、&lt;br&gt;
外出から戻ったタイミングでは高確率で起きて文句を言いにくる。&lt;/p&gt;
&lt;p&gt;ごはんは自動給餌器で出している(しかもこの場合はちゃんと完食する)ので、&lt;br&gt;
空腹ではなくお留守番させられたことに腹を立てているのは確か。&lt;/p&gt;
&lt;p&gt;ちなみにこのとき顔は怒っていて耳もイカ耳になるのだが、&lt;br&gt;
しっぽはピンと立って震えているので&lt;br&gt;
お留守番させられた怒りとしもべ(俺)が帰ってきた喜びが混ざり合った変な感情になっている。&lt;br&gt;
ような気がする。&lt;/p&gt;
&lt;p&gt;&lt;img alt="怒りながら喜んでるかもしれない" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-03-14-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2023-03-14-sotochan/sotochan02_hu_af6f1276d534d0a8.jpeg 800w, https://blog.uzimihsr.com/post/2023-03-14-sotochan/sotochan02_hu_5a6d1f2893d3c5cb.jpeg 1600w, https://blog.uzimihsr.com/post/2023-03-14-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;とてもかわいい。&lt;/p&gt;
&lt;p&gt;また、お留守番中はずっと寝ているわけではなく、&lt;br&gt;
結構元気に走り回っていることもある。&lt;/p&gt;
&lt;p&gt;たまに外出先からペットカメラで見ているので何をしてるかはだいたい筒抜けなのだが、&lt;br&gt;
そうとは知らないそとちゃんはこのとき結構悪さをする。&lt;/p&gt;
&lt;p&gt;普段登ると怒られる台所に乗ったり、ソファを破壊したりと割とやりたい放題。&lt;/p&gt;
&lt;p&gt;&lt;img alt="これはカバンを漁っているタイミングで俺が帰宅したときのやつ" class="gallery-image" data-flex-basis="246px" data-flex-grow="102" height="2944" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-03-14-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2023-03-14-sotochan/sotochan03_hu_d3240a97723e56a3.jpeg 800w, https://blog.uzimihsr.com/post/2023-03-14-sotochan/sotochan03_hu_8114fe318c59443b.jpeg 1600w, https://blog.uzimihsr.com/post/2023-03-14-sotochan/sotochan03_hu_8e36eaf8c65d6627.jpeg 2400w, https://blog.uzimihsr.com/post/2023-03-14-sotochan/sotochan03.jpeg 3024w" width="3024"&gt;&lt;/p&gt;
&lt;p&gt;最初お迎えした頃(まだ毎日出社していた時期)はお留守番余裕ねこちゃんだったので、&lt;br&gt;
この数年の在宅勤務で俺が常に家に居る状況に慣れてしまったのかもしれない。&lt;br&gt;
(お留守番中に吐いたりトイレの失敗はないのでひどい分離不安とかではないと思いたいが&amp;hellip;)&lt;/p&gt;
&lt;h3 id="こたつのプロ"&gt;こたつのプロ
&lt;/h3&gt;&lt;p&gt;こたつの上に乗る楽しみを見つけたそとちゃんだったが、&lt;br&gt;
2月はどちらかというとこたつの中で過ごすことが多かったように思った。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;こたつ &lt;a href="https://t.co/e4N7cZFaWu"&gt;pic.twitter.com/e4N7cZFaWu&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1621103691196682240?ref_src=twsrc%5Etfw"&gt;February 2, 2023&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;2月は部屋の乾燥が気になってエアコンを止めることが多かったりしたのでそのせいかもしれない。&lt;/p&gt;
&lt;p&gt;特に寒い日の朝なんかは気づいたらこたつの中にいた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="暖をとっていた" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-03-14-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2023-03-14-sotochan/sotochan04_hu_bd04ddc3d8e1d564.jpeg 800w, https://blog.uzimihsr.com/post/2023-03-14-sotochan/sotochan04_hu_b34bf456044be515.jpeg 1600w, https://blog.uzimihsr.com/post/2023-03-14-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;こたつの中で寝るときにはこだわりがあって、&lt;br&gt;
入るときに頭で布団を押して内側に折り込んでその上に寝っ転がるのがけっこう好き。&lt;/p&gt;
&lt;p&gt;&lt;img alt="こだわりのねかた" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-03-14-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2023-03-14-sotochan/sotochan05_hu_b2d765510a8d3ac6.jpeg 800w, https://blog.uzimihsr.com/post/2023-03-14-sotochan/sotochan05_hu_6ffb41139ac37e39.jpeg 1600w, https://blog.uzimihsr.com/post/2023-03-14-sotochan/sotochan05.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;こたつ &lt;a href="https://t.co/YQ0umUlguz"&gt;pic.twitter.com/YQ0umUlguz&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1623198090529472512?ref_src=twsrc%5Etfw"&gt;February 8, 2023&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;もちろんそうじゃないときもある。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ねてる &lt;a href="https://t.co/oESUDYjISD"&gt;pic.twitter.com/oESUDYjISD&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1622839165401575425?ref_src=twsrc%5Etfw"&gt;February 7, 2023&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;&lt;img alt="完全に気分" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-03-14-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2023-03-14-sotochan/sotochan06_hu_353ab46949b7435.jpeg 800w, https://blog.uzimihsr.com/post/2023-03-14-sotochan/sotochan06_hu_c6660203931be0d0.jpeg 1600w, https://blog.uzimihsr.com/post/2023-03-14-sotochan/sotochan06.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;こたつの中で溶けてるときのそとちゃんがかわいくて、&lt;br&gt;
ついつい写真を撮ってしまう。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;こたつ &lt;a href="https://t.co/MuhlU0mWTI"&gt;pic.twitter.com/MuhlU0mWTI&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1626105679055564804?ref_src=twsrc%5Etfw"&gt;February 16, 2023&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;が、やりすぎると普通に嫌そうにする。&lt;br&gt;
むずかしい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="はよ閉めろやという顔" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-03-14-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2023-03-14-sotochan/sotochan07_hu_da51361f1bc7ec0e.jpeg 800w, https://blog.uzimihsr.com/post/2023-03-14-sotochan/sotochan07_hu_c73423866c7b3578.jpeg 1600w, https://blog.uzimihsr.com/post/2023-03-14-sotochan/sotochan07.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;そとちゃんは2月もごろごろして元気だった。&lt;/p&gt;
&lt;p&gt;これを書いている時点(3月中旬)でだいぶ暖かくなっているのでこたつはそろそろ片付けたいが、&lt;br&gt;
果たして無事にいくだろうか&amp;hellip;&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="カーテンで遊ぶねこ" class="gallery-image" data-flex-basis="323px" data-flex-grow="134" height="1219" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-03-14-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2023-03-14-sotochan/sotochan_hu_c3a1d016aed42721.jpeg 800w, https://blog.uzimihsr.com/post/2023-03-14-sotochan/sotochan_hu_b9f64eb45162560a.jpeg 1600w, https://blog.uzimihsr.com/post/2023-03-14-sotochan/sotochan.jpeg 1641w" width="1641"&gt;&lt;/p&gt;</description></item><item><title>jq/yqでオブジェクトのキーを正規表現でフィルタする</title><link>https://blog.uzimihsr.com/post/2023-02-13-jq-yq-regex-for-keys/</link><pubDate>Mon, 13 Feb 2023 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2023-02-13-jq-yq-regex-for-keys/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2023-02-13-jq-yq-regex-for-keys/sotochan.jpeg" alt="Featured image of post jq/yqでオブジェクトのキーを正規表現でフィルタする" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;jq(yq)の&lt;code&gt;with_entries&lt;/code&gt;, &lt;code&gt;select&lt;/code&gt;, &lt;code&gt;test&lt;/code&gt;を組み合わせるとオブジェクトのキー名の正規表現でフィルタをかけることができる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# regexには正規表現のパターンを記述する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;jq &lt;span class="s2"&gt;&amp;#34;with_entries(select(.key|test(\&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;regex&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\&amp;#34;)))&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;yq &lt;span class="s2"&gt;&amp;#34;with_entries(select(.key|test(\&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;regex&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\&amp;#34;)))&amp;#34;&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/stedolan/jq" target="_blank" rel="noopener"
 &gt;jq&lt;/a&gt; 1.6&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mikefarah/yq" target="_blank" rel="noopener"
 &gt;yq&lt;/a&gt; v4.30.8&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="キーに正規表現を当てる"&gt;キーに正規表現を当てる
&lt;/h2&gt;&lt;p&gt;こんな感じのJSONまたはYAMLについて、&lt;code&gt;.config&lt;/code&gt;配下の&lt;code&gt;spec111&lt;/code&gt;と&lt;code&gt;spec222&lt;/code&gt;の要素だけを正規表現で抜きたいとする。&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/a916f9d41169cde13055499a9263d4ed.js"&gt;&lt;/script&gt;
&lt;script src="https://gist.github.com/uzimihsr/35633cc8896b739d5dfd251db0d38412.js"&gt;&lt;/script&gt;
&lt;p&gt;こんなときは&lt;code&gt;with_entries&lt;/code&gt;と&lt;code&gt;select&lt;/code&gt;, &lt;code&gt;test&lt;/code&gt;を使うと良い感じにできる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 先頭がspecで始まり数字で終わるパターン&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nv"&gt;regex&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;^spec[0-9]+$&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat example.json &lt;span class="p"&gt;|&lt;/span&gt; jq &lt;span class="s2"&gt;&amp;#34;.config | with_entries(select(.key|test(\&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;regex&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\&amp;#34;)))&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;spec111&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;aaa&amp;#34;&lt;/span&gt;: 123,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;bbb&amp;#34;&lt;/span&gt;: &lt;span class="m"&gt;456&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;spec222&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;aaa&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;abc&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;bbb&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;def&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat example.yaml &lt;span class="p"&gt;|&lt;/span&gt; yq &lt;span class="s2"&gt;&amp;#34;.config | with_entries(select(.key|test(\&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;regex&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\&amp;#34;)))&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;spec111:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; aaa: &lt;span class="m"&gt;123&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; bbb: &lt;span class="m"&gt;456&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;spec222:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; aaa: abc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; bbb: def&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="なにが起こっているのか"&gt;なにが起こっているのか
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://stedolan.github.io/jq/manual/#to_entries,from_entries,with_entries" target="_blank" rel="noopener"
 &gt;jq Manual&lt;/a&gt;によると&lt;code&gt;with_entries(foo)&lt;/code&gt;は&lt;br&gt;
&lt;code&gt;to_entries | map(foo) | from_entries&lt;/code&gt;と同じ意味なので、&lt;br&gt;
先ほどのコマンドを下記のように分解して何が起こっているのか詳細を追っていく。&lt;br&gt;
(yqについてもjqとほぼ同じはず)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 下記2行は同じ操作&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;jq &lt;span class="s2"&gt;&amp;#34;.config | with_entries(select(.key|test(\&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;regex&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\&amp;#34;)))&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;jq &lt;span class="s2"&gt;&amp;#34;.config | to_entries | map(select(.key|test(\&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;regex&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\&amp;#34;))) | from_entries&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# yqについても同じ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;yq &lt;span class="s2"&gt;&amp;#34;.config | with_entries(select(.key|test(\&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;regex&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\&amp;#34;)))&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;yq &lt;span class="s2"&gt;&amp;#34;.config | to_entries | map(select(.key|test(\&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;regex&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\&amp;#34;))) | from_entries&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;まずは&lt;code&gt;to_entries&lt;/code&gt;から。&lt;/p&gt;
&lt;p&gt;これを噛ませるとキーの文字列に&lt;code&gt;.key&lt;/code&gt;としてアクセスできるようになる。&lt;br&gt;
&lt;a class="link" href="https://stedolan.github.io/jq/manual/#to_entries,from_entries,with_entries" target="_blank" rel="noopener"
 &gt;https://stedolan.github.io/jq/manual/#to_entries,from_entries,with_entries&lt;/a&gt;&lt;br&gt;
&lt;a class="link" href="https://mikefarah.gitbook.io/yq/operators/entries" target="_blank" rel="noopener"
 &gt;https://mikefarah.gitbook.io/yq/operators/entries&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat example.json &lt;span class="p"&gt;|&lt;/span&gt; jq &lt;span class="s2"&gt;&amp;#34;.config | to_entries&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;spec111&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;aaa&amp;#34;&lt;/span&gt;: 123,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;bbb&amp;#34;&lt;/span&gt;: &lt;span class="m"&gt;456&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;spec222&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;aaa&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;abc&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;bbb&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;def&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;metadata&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;hoge&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;fuga&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat example.yaml &lt;span class="p"&gt;|&lt;/span&gt; yq &lt;span class="s2"&gt;&amp;#34;.config | to_entries&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- key: spec111
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; value:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; aaa: &lt;span class="m"&gt;123&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; bbb: &lt;span class="m"&gt;456&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- key: spec222
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; value:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; aaa: abc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; bbb: def
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- key: metadata
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; value:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; hoge: fuga&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;to_entries&lt;/code&gt;を噛ませた結果は配列として出力されるので、&lt;br&gt;
この配列の要素を正規表現でフィルタするために&lt;code&gt;map&lt;/code&gt;, &lt;code&gt;select&lt;/code&gt;, &lt;code&gt;test&lt;/code&gt;を噛ませてやる。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://stedolan.github.io/jq/manual/#map%28x%29,map_values%28x%29" target="_blank" rel="noopener"
 &gt;https://stedolan.github.io/jq/manual/#map(x),map_values(x)&lt;/a&gt;&lt;br&gt;
&lt;a class="link" href="https://stedolan.github.io/jq/manual/#select%28boolean_expression%29" target="_blank" rel="noopener"
 &gt;https://stedolan.github.io/jq/manual/#select(boolean_expression)&lt;/a&gt;&lt;br&gt;
&lt;a class="link" href="https://stedolan.github.io/jq/manual/#test%28val%29,test%28regex;flags%29" target="_blank" rel="noopener"
 &gt;https://stedolan.github.io/jq/manual/#test(val),test(regex;flags)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://mikefarah.gitbook.io/yq/operators/map" target="_blank" rel="noopener"
 &gt;https://mikefarah.gitbook.io/yq/operators/map&lt;/a&gt;&lt;br&gt;
&lt;a class="link" href="https://mikefarah.gitbook.io/yq/operators/select" target="_blank" rel="noopener"
 &gt;https://mikefarah.gitbook.io/yq/operators/select&lt;/a&gt;&lt;br&gt;
&lt;a class="link" href="https://mikefarah.gitbook.io/yq/operators/string-operators#test-using-regex" target="_blank" rel="noopener"
 &gt;https://mikefarah.gitbook.io/yq/operators/string-operators#test-using-regex&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;select&lt;/code&gt;, &lt;code&gt;test&lt;/code&gt;の条件に&lt;code&gt;to_entries&lt;/code&gt;で追加された&lt;code&gt;.key&lt;/code&gt;を指定することでキー名で正規表現をかけることができる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nv"&gt;regex&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;^spec[0-9]+$&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat example.json &lt;span class="p"&gt;|&lt;/span&gt; jq &lt;span class="s2"&gt;&amp;#34;.config | to_entries | map(select(.key|test(\&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;regex&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\&amp;#34;)))&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;spec111&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;aaa&amp;#34;&lt;/span&gt;: 123,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;bbb&amp;#34;&lt;/span&gt;: &lt;span class="m"&gt;456&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;spec222&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;aaa&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;abc&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;bbb&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;def&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat example.yaml &lt;span class="p"&gt;|&lt;/span&gt; yq &lt;span class="s2"&gt;&amp;#34;.config | to_entries | map(select(.key|test(\&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;regex&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\&amp;#34;)))&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- key: spec111
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; value:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; aaa: &lt;span class="m"&gt;123&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; bbb: &lt;span class="m"&gt;456&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- key: spec222
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; value:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; aaa: abc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; bbb: def&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;あとは&lt;code&gt;to_entries&lt;/code&gt;のフォーマットの配列を&lt;code&gt;from_entries&lt;/code&gt;で元のキーと値の形式に戻してやる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nv"&gt;regex&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;^spec[0-9]+$&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat example.json &lt;span class="p"&gt;|&lt;/span&gt; jq &lt;span class="s2"&gt;&amp;#34;.config | to_entries | map(select(.key|test(\&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;regex&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\&amp;#34;))) | from_entries&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;spec111&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;aaa&amp;#34;&lt;/span&gt;: 123,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;bbb&amp;#34;&lt;/span&gt;: &lt;span class="m"&gt;456&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;spec222&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;aaa&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;abc&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;bbb&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;def&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat example.yaml &lt;span class="p"&gt;|&lt;/span&gt; yq &lt;span class="s2"&gt;&amp;#34;.config | to_entries | map(select(.key|test(\&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;regex&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\&amp;#34;))) | from_entries&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;spec111:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; aaa: &lt;span class="m"&gt;123&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; bbb: &lt;span class="m"&gt;456&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;spec222:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; aaa: abc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; bbb: def&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;最初のコマンドと同じ結果が得られた。&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;jq(yq)でオブジェクトのキーに対して正規表現でフィルタをかけることができた。&lt;br&gt;
マジで便利。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="こたつで溶けるねこ" class="gallery-image" data-flex-basis="405px" data-flex-grow="169" height="1173" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-02-13-jq-yq-regex-for-keys/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2023-02-13-jq-yq-regex-for-keys/sotochan_hu_86a0b2515ea4438d.jpeg 800w, https://blog.uzimihsr.com/post/2023-02-13-jq-yq-regex-for-keys/sotochan_hu_d6fca87963a866e3.jpeg 1600w, https://blog.uzimihsr.com/post/2023-02-13-jq-yq-regex-for-keys/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>1月のそとちゃん(2023)</title><link>https://blog.uzimihsr.com/post/2023-02-10-sotochan/</link><pubDate>Fri, 10 Feb 2023 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2023-02-10-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2023-02-10-sotochan/sotochan.jpeg" alt="Featured image of post 1月のそとちゃん(2023)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;h3 id="こたつの上"&gt;こたつの上
&lt;/h3&gt;&lt;p&gt;前からちょいちょいこたつの上でごろごろしていたそとちゃん。&lt;/p&gt;
&lt;p&gt;たまたまそこにタオルを放置していたら、いつのまにかそとちゃんのものになってしまった。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;タオルすき &lt;a href="https://t.co/KDL1YSQVtb"&gt;pic.twitter.com/KDL1YSQVtb&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1613731302188122112?ref_src=twsrc%5Etfw"&gt;January 13, 2023&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;あったかくて肌触りがやわらかいのが気に入った？&lt;/p&gt;
&lt;p&gt;せまいのにはみ出さないように乗っかっててかわいい。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;おまんじゅう &lt;a href="https://t.co/IltrJi9gfu"&gt;pic.twitter.com/IltrJi9gfu&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1616261388510580737?ref_src=twsrc%5Etfw"&gt;January 20, 2023&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;訂正。&lt;br&gt;
はみ出てるときもある。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;とけた &lt;a href="https://t.co/8e16Anh8DC"&gt;pic.twitter.com/8e16Anh8DC&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1615190417376706560?ref_src=twsrc%5Etfw"&gt;January 17, 2023&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;この後一回タオルにうっかり吐いてしまい洗うことになったが、&lt;br&gt;
その間すげー悲しそうだったのでよっぽど気に入ったんだと思う。&lt;br&gt;
(なかったらなかったでこたつの上には乗る)&lt;/p&gt;
&lt;p&gt;&lt;img alt="かなしそう" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-02-10-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2023-02-10-sotochan/sotochan04_hu_faa0e32fc046959f.jpeg 800w, https://blog.uzimihsr.com/post/2023-02-10-sotochan/sotochan04_hu_131c9c76d530ad7.jpeg 1600w, https://blog.uzimihsr.com/post/2023-02-10-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="ドア"&gt;ドア
&lt;/h3&gt;&lt;p&gt;あったかい時期は部屋のドアを開けっぱなしにしていたのだが、&lt;br&gt;
最近は廊下の冷気がキツいので頻繁に閉めている。&lt;/p&gt;
&lt;p&gt;そしてそとちゃんは自力でドアが開けられない。&lt;br&gt;
(世の中には器用にドアノブを回しちゃうねこもいるみたいだけど&amp;hellip;)&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ドアを開けてほしいねこ &lt;a href="https://t.co/Fdq16nBJGC"&gt;pic.twitter.com/Fdq16nBJGC&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1620228692910956544?ref_src=twsrc%5Etfw"&gt;January 31, 2023&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;廊下を走り回るのが好きなそとちゃんはこれが不満で、&lt;br&gt;
昼夜問わずドアの前でわんわん鳴いている。&lt;/p&gt;
&lt;p&gt;&lt;img alt="コロの近くで転がるの危ないからやめてほしい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-02-10-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2023-02-10-sotochan/sotochan02_hu_5ee09189ddc558e8.jpeg 800w, https://blog.uzimihsr.com/post/2023-02-10-sotochan/sotochan02_hu_1eb4b864541eda5e.jpeg 1600w, https://blog.uzimihsr.com/post/2023-02-10-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;仕方がないので開けてあげるとそとちゃんが廊下に飛び出す。&lt;br&gt;
うっかり締め出してしまわないように、戻ってくるのを待ってからドアを閉める。&lt;br&gt;
またそとちゃんが走りたくなって鳴く。&lt;/p&gt;
&lt;p&gt;&lt;img alt="GO" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-02-10-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2023-02-10-sotochan/sotochan03_hu_2536cf6d6c5d6b26.jpeg 800w, https://blog.uzimihsr.com/post/2023-02-10-sotochan/sotochan03_hu_18ad252228a3437a.jpeg 1600w, https://blog.uzimihsr.com/post/2023-02-10-sotochan/sotochan03.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;日中はこれがずっと続いている。&lt;br&gt;
猫は寒い所が苦手とはなんだったのか。&lt;br&gt;
なぜ廊下より広くて暖かい部屋で遊ばないのか。&lt;br&gt;
謎である。&lt;/p&gt;
&lt;p&gt;&lt;img alt="開けないと怒られる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-02-10-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2023-02-10-sotochan/sotochan01_hu_602884f2f7e7a96.jpeg 800w, https://blog.uzimihsr.com/post/2023-02-10-sotochan/sotochan01_hu_8b80a333045efb33.jpeg 1600w, https://blog.uzimihsr.com/post/2023-02-10-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;でも開けてあげたときのそとちゃんがめちゃごきげんでかわいいのでOKです。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ドア開けてもらって機嫌良い &lt;a href="https://t.co/GlBBhdU60b"&gt;pic.twitter.com/GlBBhdU60b&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1617761500848074754?ref_src=twsrc%5Etfw"&gt;January 24, 2023&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;年があけてさらに寒くなってきたけど、そとちゃんは元気に寒い廊下を走り回っている。&lt;/p&gt;
&lt;p&gt;ごはんもよく食べるし(カリカリも食べる)、うんちももりもり出して健康でなにより。&lt;/p&gt;
&lt;p&gt;そとちゃんが今年も健康を維持できるように頑張りたい。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="俺のひざにあごを乗せるそとちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2023-02-10-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2023-02-10-sotochan/sotochan_hu_9038bd575d9e8396.jpeg 800w, https://blog.uzimihsr.com/post/2023-02-10-sotochan/sotochan_hu_296d64ef20f7360a.jpeg 1600w, https://blog.uzimihsr.com/post/2023-02-10-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>12月のそとちゃん(2022)</title><link>https://blog.uzimihsr.com/post/2022-12-31-sotochan/</link><pubDate>Sat, 31 Dec 2022 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2022-12-31-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan.jpeg" alt="Featured image of post 12月のそとちゃん(2022)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%93%e3%81%9f%e3%81%a4" &gt;こたつ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e5%af%9d%e8%90%bd%e3%81%a1" &gt;寝落ち&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%af%e3%83%aa%e3%82%b9%e3%83%9e%e3%82%b9" &gt;クリスマス&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="こたつ"&gt;こたつ
&lt;/h3&gt;&lt;p&gt;めちゃんこ寒くなってきたのでついにこたつを出した。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;こたつ &lt;a href="https://t.co/deHYXBAjS3"&gt;pic.twitter.com/deHYXBAjS3&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1604040919321153536?ref_src=twsrc%5Etfw"&gt;December 17, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;そとちゃんはこたつが大好き。&lt;/p&gt;
&lt;p&gt;ほぼ毎日中で寝ている。&lt;/p&gt;
&lt;p&gt;&lt;img alt="溶けてる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan01_hu_70be0b9692f4ca59.jpeg 800w, https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan01_hu_549606e89c815008.jpeg 1600w, https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;普段布団なんか絶対入らないのに(被せると逃げる)、こたつには自分から器用に潜っていく。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ぬるり &lt;a href="https://t.co/9IGxBZdyfG"&gt;pic.twitter.com/9IGxBZdyfG&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1604271935084298241?ref_src=twsrc%5Etfw"&gt;December 18, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;ちなみにそとちゃんがこたつにいるときに俺が後から入ると高確率で出ていってしまう。&lt;/p&gt;
&lt;p&gt;冷たいつま先が触れるのがどうしても嫌みたい。&lt;br&gt;
&lt;del&gt;(ただ単に俺の足が臭い説もある)&lt;/del&gt;&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;俺がこたつ入ったのが気に入らない様子 &lt;a href="https://t.co/GEPcdQk9L0"&gt;pic.twitter.com/GEPcdQk9L0&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1608321450058055680?ref_src=twsrc%5Etfw"&gt;December 29, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;それでもそとちゃんが後からくるときはこたつの上に乗ってくれるようになって、&lt;br&gt;
うまいこと共存できている。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;こたつの上もあったかいことに気づいた &lt;a href="https://t.co/1DjQsydKbE"&gt;pic.twitter.com/1DjQsydKbE&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1608060111075041280?ref_src=twsrc%5Etfw"&gt;December 28, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;が、欲を言えばやっぱり一緒に入りたい。&lt;br&gt;
かなしい&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="上でも溶ける" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan02_hu_166c52692da85d2b.jpeg 800w, https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan02_hu_6ec46e3dc038622a.jpeg 1600w, https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="寝落ち"&gt;寝落ち
&lt;/h3&gt;&lt;p&gt;前述のとおりそとちゃんはほぼ毎日こたつの中で溶けているのだが、&lt;br&gt;
日が差す時間になるとちゃんと窓際でひなたぼっこする。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;超ごきげん &lt;a href="https://t.co/vHZiSXGNh8"&gt;pic.twitter.com/vHZiSXGNh8&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1602170587757293568?ref_src=twsrc%5Etfw"&gt;December 12, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;問題はその後で、
なぜかそとちゃんはこたつに戻れずカーテンの裾で寝落ちしてしまう。&lt;/p&gt;
&lt;p&gt;光が多く入るように毎日カーテンの裾を上げているのだが、&lt;br&gt;
ある日裾を縛るのがめんどくさくてベッドの上にそのまま放置したら気に入られてしまった。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;こたつにいないと思ったら変なとこで寝てた &lt;a href="https://t.co/jQ5G1tGK1z"&gt;pic.twitter.com/jQ5G1tGK1z&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1605815019547283456?ref_src=twsrc%5Etfw"&gt;December 22, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;理由はよくわかんない。謎。&lt;/p&gt;
&lt;p&gt;生地の肌触りが好きなのか&amp;hellip;？&lt;/p&gt;
&lt;p&gt;裾を縛ってるときはすぐこたつに戻るので、場所というよりはカーテンがよっぽど気に入った様子。&lt;/p&gt;
&lt;p&gt;珍しいときにはまだひなたぼっこできる時間でもここで寝てることがある。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;またカーテン踏んづけて寝てる &lt;a href="https://t.co/lJDLNRui70"&gt;pic.twitter.com/lJDLNRui70&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1606157392307159044?ref_src=twsrc%5Etfw"&gt;December 23, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;よくわからない。&lt;/p&gt;
&lt;h3 id="クリスマス"&gt;クリスマス
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2021-12-31-sotochan/" target="_blank" rel="noopener"
 &gt;去年&lt;/a&gt;は手術後でクリスマスっぽいことがあまりできなかったが、&lt;br&gt;
今年はそとちゃんに変身してもらった。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;クリスマスねこちゃん &lt;a href="https://t.co/bPFOwb97e1"&gt;pic.twitter.com/bPFOwb97e1&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1606499418966233088?ref_src=twsrc%5Etfw"&gt;December 24, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;今回は赤いマント。&lt;br&gt;
あんまり重くないし、動きも制限されないので結構気に入ったみたい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="自力で脱げるように緩めにつけても全然脱がなかった" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan03_hu_c5ca45c5e7f0a688.jpeg 800w, https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan03_hu_4e63ac217ec4daa1.jpeg 1600w, https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan03.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="やる気" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan04_hu_39d860e2efb4f715.jpeg 800w, https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan04_hu_1c52690d1d949a53.jpeg 1600w, https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="かわいいね" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan05_hu_c28005ba91626ebc.jpeg 800w, https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan05_hu_e9c1183fb63abdec.jpeg 1600w, https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan05.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;人間のわがままに付き合ってもらったので、報酬としてごちそうを献上。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ごちそう &lt;a href="https://t.co/FjoYqyJ9Il"&gt;pic.twitter.com/FjoYqyJ9Il&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1606591673810948098?ref_src=twsrc%5Etfw"&gt;December 24, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;翌朝はプレゼントを開封。&lt;br&gt;
去年あんまりお祝いできなかったので、今年のクリスマスプレゼントは気持ち多めになった。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="qme" dir="ltr"&gt;🎅🎁 &lt;a href="https://t.co/I4PuPQqSSf"&gt;pic.twitter.com/I4PuPQqSSf&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1606804777861808129?ref_src=twsrc%5Etfw"&gt;December 25, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;今まで持ってなかった光を追いかける系のおもちゃを手に入れたのだが、&lt;br&gt;
そとちゃんはかしこい(?)ので、ライトで照らされる場所でなくライトの発光部分を直接追いかけてしまう。&lt;/p&gt;
&lt;p&gt;ちなみにこのおもちゃの光はレーザーではない(LED)のでそれらに比べれば安全という話だが、&lt;br&gt;
実際のところどうなんだろう&amp;hellip;?&lt;/p&gt;
&lt;p&gt;直視して良いものでは無い気がしたので、結局このおもちゃはほぼお蔵入りとなってしまった。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;遊び方が違う &lt;a href="https://t.co/1vQiSt2qhc"&gt;pic.twitter.com/1vQiSt2qhc&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1606999704101081089?ref_src=twsrc%5Etfw"&gt;December 25, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;&lt;img alt="あとつめとぎベッドのサイズまちがえた" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan08_hu_6999f5adb1688090.jpeg 800w, https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan08_hu_c0aea6c65ef46600.jpeg 1600w, https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan08.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;こんなこともあろうかと(?)&lt;br&gt;
クリスマスに関係なく 100 均で適当に買ってきたおもちゃを出したらこちらにめちゃめちゃ食いついた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="食いついた" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan06_hu_bc240d3c88150be1.jpeg 800w, https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan06_hu_8bdec5f0929b218e.jpeg 1600w, https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan06.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="うおお" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan07_hu_11ede01cf2b62c7c.jpeg 800w, https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan07_hu_e9e3eea0cb440f45.jpeg 1600w, https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan07.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;楽しく過ごせてよかった。&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;今年のそとちゃんは大きな病気や怪我もなく健康で何よりだった。&lt;/p&gt;
&lt;p&gt;そとちゃん的に良い 1 年だったかはよくわからないが、
俺的にはまあまあだったと思う。&lt;/p&gt;
&lt;p&gt;大きなイベントとして引越しがあったけどすぐに慣れてくれたし、&lt;br&gt;
引越しの目的でもあったひなたぼっこをたくさんしてくれたので嬉しかった。&lt;/p&gt;
&lt;p&gt;そとちゃんは来年いよいよシニアねこ(たぶん 7 歳)になる。&lt;br&gt;
まだまだうるさいくらいに元気いっぱいだけど、これからも元気に過ごせるように気をつけたい。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="こたつの中で撮ったら渋めの俳優みたいになったそとちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan_hu_6722d45d57ef5b7a.jpeg 800w, https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan_hu_4fff938b2a655a44.jpeg 1600w, https://blog.uzimihsr.com/post/2022-12-31-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>11月のそとちゃん(2022)</title><link>https://blog.uzimihsr.com/post/2022-12-07-sotochan/</link><pubDate>Wed, 07 Dec 2022 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2022-12-07-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2022-12-07-sotochan/sotochan.jpeg" alt="Featured image of post 11月のそとちゃん(2022)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e6%97%a5%e8%aa%b2" &gt;日課&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e6%96%b0%e3%83%99%e3%83%83%e3%83%89" &gt;新ベッド&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%88%e3%82%89%e3%81%84" &gt;えらい&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="日課"&gt;日課
&lt;/h3&gt;&lt;p&gt;そとちゃんは11月もひなたぼっこを毎日がんばっていた。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;くわ〜っ &lt;a href="https://t.co/aobiS002r9"&gt;pic.twitter.com/aobiS002r9&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1589490799200595969?ref_src=twsrc%5Etfw"&gt;November 7, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;日が入ってくる時間帯になると窓際で待機。&lt;/p&gt;
&lt;p&gt;鳥が来ないか少しだけ見張って(最近あんまりこない)、&lt;br&gt;
あとは横になって満足するまでしっかり日を浴びる。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;いそがしい &lt;a href="https://t.co/oeN8RYWEKu"&gt;pic.twitter.com/oeN8RYWEKu&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1592728714588336128?ref_src=twsrc%5Etfw"&gt;November 16, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;(だいたい寝落ちする)&lt;/p&gt;
&lt;div class="video-wrapper"&gt;
 &lt;iframe loading="lazy" 
 src="https://www.youtube.com/embed/Gl0YSfCxZYk" 
 allowfullscreen 
 title="YouTube Video"
 &gt;
 &lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;あんまり元気じゃない日もひなたぼっこは欠かさない。&lt;br&gt;
まるで仕事のよう。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;機嫌悪い &lt;a href="https://t.co/e9NowqEQ0t"&gt;pic.twitter.com/e9NowqEQ0t&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1595991912531783680?ref_src=twsrc%5Etfw"&gt;November 25, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;天気が悪い日も一応窓際に出勤する。&lt;/p&gt;
&lt;p&gt;ハンモックの上で日が出るのをずっと待っていて、&lt;br&gt;
そのまま晴れなかったら文句を言いながら降りてくる。&lt;/p&gt;
&lt;p&gt;&lt;img alt="真面目" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-12-07-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2022-12-07-sotochan/sotochan01_hu_583a85a8bfda2f3.jpeg 800w, https://blog.uzimihsr.com/post/2022-12-07-sotochan/sotochan01_hu_bc5bf6a243536ff2.jpeg 1600w, https://blog.uzimihsr.com/post/2022-12-07-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&amp;hellip;毎日と言ったがあれは嘘だった。&lt;br&gt;
早朝の運動で疲れすぎて夕方まで寝てる日もある。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;今日はひなたぼっこサボって寝てた &lt;a href="https://t.co/dvWQD36L6H"&gt;pic.twitter.com/dvWQD36L6H&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1588473721312149504?ref_src=twsrc%5Etfw"&gt;November 4, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;自分のペースでがんばってほしい(?)。&lt;/p&gt;
&lt;h3 id="新ベッド"&gt;新ベッド
&lt;/h3&gt;&lt;p&gt;10月後半あたりからそうなんだけどお気に入りの場所がまた増えた。&lt;/p&gt;
&lt;p&gt;今までもあったバリバリボウルにブランケットかけただけのベッドがいい感じ。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ベッド?" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-12-07-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2022-12-07-sotochan/sotochan02_hu_953c11627297cf20.jpeg 800w, https://blog.uzimihsr.com/post/2022-12-07-sotochan/sotochan02_hu_d667758d1ebb3b11.jpeg 1600w, https://blog.uzimihsr.com/post/2022-12-07-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;テーブルの下に置いたらやたらと乗る。&lt;br&gt;
こたつ出せアピール？&lt;/p&gt;
&lt;p&gt;&lt;img alt="いい感じ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-12-07-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2022-12-07-sotochan/sotochan03_hu_2c03a1969251b1a7.jpeg 800w, https://blog.uzimihsr.com/post/2022-12-07-sotochan/sotochan03_hu_c5c42a9e8f57e307.jpeg 1600w, https://blog.uzimihsr.com/post/2022-12-07-sotochan/sotochan03.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;ひなたぼっこしてないときはだいたいここだし、&lt;br&gt;
最近は寝る時も本棚の上よりこっちにいることが多い。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ごろごろ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-12-07-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2022-12-07-sotochan/sotochan04_hu_37ee0e5f7d2c02a0.jpeg 800w, https://blog.uzimihsr.com/post/2022-12-07-sotochan/sotochan04_hu_7b120887a02d4ad6.jpeg 1600w, https://blog.uzimihsr.com/post/2022-12-07-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;よくわかんないけど気に入ってくれてよかった。&lt;/p&gt;
&lt;h3 id="えらい"&gt;えらい
&lt;/h3&gt;&lt;p&gt;朝昼のカリカリ完食率が上がってきた。&lt;/p&gt;
&lt;p&gt;理由は謎だけど&lt;a class="link" href="https://uzimihsr.github.io/post/2022-11-09-sotochan/#%E3%83%88%E3%83%83%E3%83%94%E3%83%B3%E3%82%B0" target="_blank" rel="noopener"
 &gt;トッピング付与率&lt;/a&gt;の仕組みに気づいたか、部屋が乾燥してきてカリカリの風味が良くなった？&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;うまいうまい &lt;a href="https://t.co/dwdzWzXDwR"&gt;pic.twitter.com/dwdzWzXDwR&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1591406350076383234?ref_src=twsrc%5Etfw"&gt;November 12, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;おかげでちゅーるごはんの機会も増えていい感じ。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;マシマシ &lt;a href="https://t.co/CbD7S9AT00"&gt;pic.twitter.com/CbD7S9AT00&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1592491355892494337?ref_src=twsrc%5Etfw"&gt;November 15, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;でも毎日カリカリ完食って感じではなくて、&lt;br&gt;
たまに食べ忘れてノートッピングになることもある。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;プレーン猫缶 &lt;a href="https://t.co/xy1FYeo6m3"&gt;pic.twitter.com/xy1FYeo6m3&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1592101694808395776?ref_src=twsrc%5Etfw"&gt;November 14, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;ちなみにそとちゃんはかしこいので絶対に美味しいところから食べる。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;絶対トッピングから食べる &lt;a href="https://t.co/5LXKYrZESC"&gt;pic.twitter.com/5LXKYrZESC&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1597521389741051904?ref_src=twsrc%5Etfw"&gt;November 29, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;カリカリを一口も食べずに残したりしてた夏頃に比べると格段に良くなった。&lt;br&gt;
えらい！&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;だんだん寒くなってきたが11月もそとちゃんはよく寝てよく食べて元気だった。&lt;/p&gt;
&lt;p&gt;新居の断熱性能がそこそこいい感じで11月まではエアコンだけで寒さをしのいだが、&lt;br&gt;
ここからもっと寒くなるはずなのでこたつの出番は近いかもしれない。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="ベッドの上で寝ながら遊ぶ横着者ねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-12-07-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2022-12-07-sotochan/sotochan_hu_c1a42047267c275c.jpeg 800w, https://blog.uzimihsr.com/post/2022-12-07-sotochan/sotochan_hu_7091cafaa104861a.jpeg 1600w, https://blog.uzimihsr.com/post/2022-12-07-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>Install kube-state-metrics, cAdvisor and Prometheus on a Kubernetes cluster</title><link>https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor/</link><pubDate>Mon, 28 Nov 2022 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor/sotochan.jpeg" alt="Featured image of post Install kube-state-metrics, cAdvisor and Prometheus on a Kubernetes cluster" /&gt;&lt;h2 id="summary"&gt;Summary
&lt;/h2&gt;&lt;p&gt;This is a working log of the installation of kube-state-metrics, cAdvisor, and Prometheus on a Kubernetes cluster.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create a single-node Kubernetes cluster with kind&lt;/li&gt;
&lt;li&gt;Install kube-state-metrics as a Deployment&lt;/li&gt;
&lt;li&gt;Install cAdvisor as a DaemonSet&lt;/li&gt;
&lt;li&gt;Install Prometheus as a Deployment and configure it to scrape these metrics&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="architecture diagram" class="gallery-image" data-flex-basis="445px" data-flex-grow="185" height="421" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor/component.drawio.png" width="781"&gt;&lt;/p&gt;
&lt;h2 id="prerequisites"&gt;Prerequisites
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kind.sigs.k8s.io/" target="_blank" rel="noopener"
 &gt;kind&lt;/a&gt; v0.17.0 go1.19.2 darwin/arm64&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://kubernetes.io/" target="_blank" rel="noopener"
 &gt;kubernetes&lt;/a&gt; v1.25.3&lt;/li&gt;
&lt;li&gt;kubectl v1.25.0&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://prometheus.io/" target="_blank" rel="noopener"
 &gt;prometheus&lt;/a&gt; version 2.40.3&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/kubernetes/kube-state-metrics" target="_blank" rel="noopener"
 &gt;kube-state-metrics&lt;/a&gt; v2.7.0&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/google/cadvisor" target="_blank" rel="noopener"
 &gt;cAdvisor&lt;/a&gt; v0.45.0&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="logs"&gt;Logs
&lt;/h2&gt;&lt;h3 id="create-a-kubernetes-cluster"&gt;Create a Kubernetes cluster
&lt;/h3&gt;&lt;p&gt;Let&amp;rsquo;s go with kind.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kind create cluster
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Creating cluster &lt;span class="s2"&gt;&amp;#34;kind&amp;#34;&lt;/span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✓ Ensuring node image &lt;span class="o"&gt;(&lt;/span&gt;kindest/node:v1.25.3&lt;span class="o"&gt;)&lt;/span&gt; 🖼
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✓ Preparing nodes 📦
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✓ Writing configuration 📜
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✓ Starting control-plane 🕹️
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✓ Installing CNI 🔌
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✓ Installing StorageClass 💾
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Set kubectl context to &lt;span class="s2"&gt;&amp;#34;kind-kind&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;You can now use your cluster with:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl cluster-info --context kind-kind
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Have a question, bug, or feature request? Let us know! https://kind.sigs.k8s.io/#community 🙂&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="install-kube-state-metrics"&gt;Install kube-state-metrics
&lt;/h3&gt;&lt;p&gt;kube-state-metrics generates the metrics of Kubernetes objects such as Nodes, Services and Pods.&lt;/p&gt;
&lt;p&gt;You can install it using the &lt;a class="link" href="https://github.com/kubernetes/kube-state-metrics/tree/0cbabf95239b33e8a469630e63c668b8e9786ad3/examples/standard" target="_blank" rel="noopener"
 &gt;sample manifests&lt;/a&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/kube-state-metrics/master/examples/standard/service-account.yaml &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubectl apply -f https://raw.githubusercontent.com/kubernetes/kube-state-metrics/master/examples/standard/cluster-role.yaml &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubectl apply -f https://raw.githubusercontent.com/kubernetes/kube-state-metrics/master/examples/standard/cluster-role-binding.yaml &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubectl apply -f https://raw.githubusercontent.com/kubernetes/kube-state-metrics/master/examples/standard/deployment.yaml &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubectl apply -f https://raw.githubusercontent.com/kubernetes/kube-state-metrics/master/examples/standard/service.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;serviceaccount/kube-state-metrics created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;clusterrole.rbac.authorization.k8s.io/kube-state-metrics created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;clusterrolebinding.rbac.authorization.k8s.io/kube-state-metrics created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps/kube-state-metrics created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/kube-state-metrics created&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In this case, kube-state-metrics is run as a Deployment.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s port-forward to this Service and check the metrics.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n kube-system get deploy,service -l app.kubernetes.io/name&lt;span class="o"&gt;=&lt;/span&gt;kube-state-metrics
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY UP-TO-DATE AVAILABLE AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps/kube-state-metrics 1/1 &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 115s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/kube-state-metrics ClusterIP None &amp;lt;none&amp;gt; 8080/TCP,8081/TCP 115s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n kube-system port-forward service/kube-state-metrics 8080:8080 8081:8081
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Forwarding from 127.0.0.1:8080 -&amp;gt; &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Forwarding from &lt;span class="o"&gt;[&lt;/span&gt;::1&lt;span class="o"&gt;]&lt;/span&gt;:8080 -&amp;gt; &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Forwarding from 127.0.0.1:8081 -&amp;gt; &lt;span class="m"&gt;8081&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Forwarding from &lt;span class="o"&gt;[&lt;/span&gt;::1&lt;span class="o"&gt;]&lt;/span&gt;:8081 -&amp;gt; &lt;span class="m"&gt;8081&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# from different terminal&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl localhost:8080/metrics
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# HELP kube_configmap_labels [STABLE] Kubernetes labels converted to Prometheus labels.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# TYPE kube_configmap_labels gauge&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube_configmap_labels&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;local-path-storage&amp;#34;&lt;/span&gt;,configmap&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;local-path-config&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube_configmap_labels&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;default&amp;#34;&lt;/span&gt;,configmap&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;kube-root-ca.crt&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Good. It works fine.&lt;/p&gt;
&lt;p&gt;The &lt;a class="link" href="https://github.com/kubernetes/kube-state-metrics/tree/master/docs" target="_blank" rel="noopener"
 &gt;docs&lt;/a&gt; has more information about the metrics.&lt;/p&gt;
&lt;p&gt;kube-state-metrics can also be accessed via a browser.&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="http://localhost:8080/" target="_blank" rel="noopener"
 &gt;http://localhost:8080/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="/metrics is the link to the Kubernetes metrics page and /healthz is the health check endpoint" class="gallery-image" data-flex-basis="619px" data-flex-grow="258" height="487" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor/sc01-kube-state-metrics-ui.png" srcset="https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor/sc01-kube-state-metrics-ui_hu_a8f70400275e100c.png 800w, https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor/sc01-kube-state-metrics-ui.png 1257w" width="1257"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="http://localhost:8081/" target="_blank" rel="noopener"
 &gt;http://localhost:8081/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="this /metrics is the link to the metrics of the kube-state-metrics process" class="gallery-image" data-flex-basis="619px" data-flex-grow="258" height="487" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor/sc02-kube-state-metrics-ui.png" srcset="https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor/sc02-kube-state-metrics-ui_hu_f7c026885602b1af.png 800w, https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor/sc02-kube-state-metrics-ui.png 1257w" width="1257"&gt;&lt;/p&gt;
&lt;h3 id="install-cadvisor"&gt;Install cAdvisor
&lt;/h3&gt;&lt;p&gt;cAdvisor exports the container metrics such as CPU usage, Memory usage, etc.&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/google/cadvisor/tree/master/deploy/kubernetes" target="_blank" rel="noopener"
 &gt;Kustomized manifests&lt;/a&gt; are available. Yes!&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -k https://github.com/google/cadvisor//deploy/kubernetes/base
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;namespace/cadvisor created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;serviceaccount/cadvisor created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;daemonset.apps/cadvisor created&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;cAdvisor runs as a DaemonSet and collects container information from each Node.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n cadvisor get daemonset -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;cadvisor
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cadvisor &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &amp;lt;none&amp;gt; 6m54s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nv"&gt;pod&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;kubectl -n cadvisor get pod -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;cadvisor -o &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;{.items[0].metadata.name}&amp;#34;&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n cadvisor port-forward pod/&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;pod&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; 8080:8080
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Forwarding from 127.0.0.1:8080 -&amp;gt; &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Forwarding from &lt;span class="o"&gt;[&lt;/span&gt;::1&lt;span class="o"&gt;]&lt;/span&gt;:8080 -&amp;gt; &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# from different terminal&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl localhost:8080/metrics
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# HELP cadvisor_version_info A metric with a constant &amp;#39;1&amp;#39; value labeled by kernel version, OS version, docker version, cadvisor version &amp;amp; cadvisor revision.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# TYPE cadvisor_version_info gauge&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cadvisor_version_info&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;cadvisorRevision&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;86b11c65&amp;#34;&lt;/span&gt;,cadvisorVersion&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;v0.45.0&amp;#34;&lt;/span&gt;,dockerVersion&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,kernelVersion&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;5.10.124-linuxkit&amp;#34;&lt;/span&gt;,osVersion&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Alpine Linux v3.16&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# HELP container_blkio_device_usage_total Blkio Device bytes usage&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# TYPE container_blkio_device_usage_total counter&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;container_blkio_device_usage_total&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;container_label_app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,container_label_app_kubernetes_io_component&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,container_label_app_kubernetes_io_name&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,container_label_app_kubernetes_io_version&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,container_label_component&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,container_label_controller_revision_hash&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,container_label_description&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,container_label_io_cri_containerd_kind&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,container_label_io_kubernetes_container_name&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,container_label_io_kubernetes_pod_name&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,container_label_io_kubernetes_pod_namespace&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,container_label_io_kubernetes_pod_uid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,container_label_k8s_app&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,container_label_maintainers&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,container_label_name&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,container_label_pod_template_generation&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,container_label_pod_template_hash&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,container_label_tier&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,device&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/dev/vda&amp;#34;&lt;/span&gt;,id&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/&amp;#34;&lt;/span&gt;,image&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,major&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;254&amp;#34;&lt;/span&gt;,minor&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;0&amp;#34;&lt;/span&gt;,name&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,operation&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Read&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;1669642901054&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Metrics with names like &lt;code&gt;container_**&lt;/code&gt; are container metrics.&lt;/p&gt;
&lt;p&gt;Of course, cAdvisor can also be accessed via a browser.&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="http://localhost:8080/" target="_blank" rel="noopener"
 &gt;http://localhost:8080/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="graphical pages" class="gallery-image" data-flex-basis="374px" data-flex-grow="155" height="811" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor/sc03-cadvisor-ui.png" srcset="https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor/sc03-cadvisor-ui_hu_8e11760766aba361.png 800w, https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor/sc03-cadvisor-ui.png 1265w" width="1265"&gt;&lt;/p&gt;
&lt;h3 id="install-prometheus"&gt;Install Prometheus
&lt;/h3&gt;&lt;p&gt;Next, install Prometheus to scrape these metrics.&lt;/p&gt;
&lt;p&gt;Here is an example manifest that installs Prometheus as a Deployment.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/a09c3dd0bc680144d6110ff3bd5c98c8.js"&gt;&lt;/script&gt;
&lt;p&gt;Apply it.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create namespace prometheus
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;namespace/prometheus created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n prometheus apply -f deployment.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps/prometheus created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n prometheus expose deployment prometheus --port&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;9090&lt;/span&gt; --target-port&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;9090&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/prometheus exposed&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Make sure it is working properly.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n prometheus port-forward service/prometheus 9090:9090
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Forwarding from 127.0.0.1:9090 -&amp;gt; &lt;span class="m"&gt;9090&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Forwarding from &lt;span class="o"&gt;[&lt;/span&gt;::1&lt;span class="o"&gt;]&lt;/span&gt;:9090 -&amp;gt; &lt;span class="m"&gt;9090&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a class="link" href="http://localhost:9090/" target="_blank" rel="noopener"
 &gt;http://localhost:9090/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Prometheus" class="gallery-image" data-flex-basis="374px" data-flex-grow="155" height="811" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor/sc04-prometheus-ui.png" srcset="https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor/sc04-prometheus-ui_hu_53350ffa4126489e.png 800w, https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor/sc04-prometheus-ui.png 1265w" width="1265"&gt;&lt;/p&gt;
&lt;p&gt;Good.&lt;/p&gt;
&lt;h3 id="configure-prometheus-for-service-discovery-kubernetes_sd_config"&gt;Configure Prometheus for service discovery (kubernetes_sd_config)
&lt;/h3&gt;&lt;p&gt;Finally, configure Prometheus to scrape metrics in the cluster.&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config" target="_blank" rel="noopener"
 &gt;kubernetes_sd_config&lt;/a&gt; is the key.&lt;/p&gt;
&lt;p&gt;Follow the &lt;a class="link" href="https://github.com/prometheus/prometheus/blob/main/documentation/examples/prometheus-kubernetes.yml" target="_blank" rel="noopener"
 &gt;example&lt;/a&gt; and create &lt;code&gt;prometheus.yml&lt;/code&gt;.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/04f5f04f8f0c9f202e80335eadb7cc42.js"&gt;&lt;/script&gt;
&lt;p&gt;In this case, Prometheus scrapes only Services of kube-state-metrics and Pods of cAdvisor.&lt;br&gt;
(Without this config, kube-state-metrics is scraped by both &amp;ldquo;role: service&amp;rdquo; job and &amp;ldquo;role: pod&amp;rdquo; job, then the metrics are duplicated.)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n cadvisor get pods --show-labels
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE LABELS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cadvisor-fngj6 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 23h &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;cadvisor,controller-revision-hash&lt;span class="o"&gt;=&lt;/span&gt;df8bf66b4,name&lt;span class="o"&gt;=&lt;/span&gt;cadvisor,pod-template-generation&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n kube-system get service kube-state-metrics --show-labels
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE LABELS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube-state-metrics ClusterIP None &amp;lt;none&amp;gt; 8080/TCP,8081/TCP 24h app.kubernetes.io/component&lt;span class="o"&gt;=&lt;/span&gt;exporter,app.kubernetes.io/name&lt;span class="o"&gt;=&lt;/span&gt;kube-state-metrics,app.kubernetes.io/version&lt;span class="o"&gt;=&lt;/span&gt;2.7.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f configmap.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;configmap/prometheus-config created&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Update the Deployment to load the config.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/49300e02d52eb981869e65b1b76d209c.js"&gt;&lt;/script&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f deployment.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps/prometheus configured&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Open &lt;code&gt;Status&lt;/code&gt;-&amp;gt;&lt;code&gt;Service Discovery&lt;/code&gt; to check operation.&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="http://localhost:9090/service-discovery" target="_blank" rel="noopener"
 &gt;http://localhost:9090/service-discovery&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Failed" class="gallery-image" data-flex-basis="374px" data-flex-grow="155" height="811" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor/sc05-service-discovery-fail.png" srcset="https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor/sc05-service-discovery-fail_hu_9fed600bd58abadd.png 800w, https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor/sc05-service-discovery-fail.png 1265w" width="1265"&gt;&lt;/p&gt;
&lt;p&gt;Oops! Service discovery has failed.&lt;/p&gt;
&lt;p&gt;Check the Pod log&amp;hellip;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nv"&gt;pod&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;kubectl -n prometheus get pods -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;prometheus -o &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;{.items[0].metadata.name}&amp;#34;&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n prometheus logs &lt;span class="nv"&gt;$pod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;ts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2022-11-28T14:26:56.150Z &lt;span class="nv"&gt;caller&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes.go:326 &lt;span class="nv"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;info &lt;span class="nv"&gt;component&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;discovery manager scrape&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;discovery&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes &lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Using pod service account via in-cluster config&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;ts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2022-11-28T14:26:56.150Z &lt;span class="nv"&gt;caller&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;main.go:1234 &lt;span class="nv"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;info &lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Completed loading of configuration file&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/config/prometheus.yml &lt;span class="nv"&gt;totalDuration&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2.798834ms &lt;span class="nv"&gt;db_storage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.208µs &lt;span class="nv"&gt;remote_storage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.417µs &lt;span class="nv"&gt;web_handler&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;375ns &lt;span class="nv"&gt;query_engine&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.042µs &lt;span class="nv"&gt;scrape&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;250.917µs &lt;span class="nv"&gt;scrape_sd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2.159042ms &lt;span class="nv"&gt;notify&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.083µs &lt;span class="nv"&gt;notify_sd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5.709µs &lt;span class="nv"&gt;rules&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.584µs &lt;span class="nv"&gt;tracing&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;12.958µs
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;ts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2022-11-28T14:26:56.150Z &lt;span class="nv"&gt;caller&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;main.go:978 &lt;span class="nv"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;info &lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Server is ready to receive web requests.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;ts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2022-11-28T14:26:56.150Z &lt;span class="nv"&gt;caller&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;manager.go:944 &lt;span class="nv"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;info &lt;span class="nv"&gt;component&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;rule manager&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Starting rule manager...&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;ts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2022-11-28T14:26:56.156Z &lt;span class="nv"&gt;caller&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;klog.go:108 &lt;span class="nv"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;warn &lt;span class="nv"&gt;component&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;k8s_client_runtime &lt;span class="nv"&gt;func&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Warningf &lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;pkg/mod/k8s.io/client-go@v0.25.3/tools/cache/reflector.go:169: failed to list *v1.Service: services is forbidden: User \&amp;#34;system:serviceaccount:prometheus:default\&amp;#34; cannot list resource \&amp;#34;services\&amp;#34; in API group \&amp;#34;\&amp;#34; at the cluster scope&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;ts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2022-11-28T14:26:56.156Z &lt;span class="nv"&gt;caller&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;klog.go:108 &lt;span class="nv"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;warn &lt;span class="nv"&gt;component&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;k8s_client_runtime &lt;span class="nv"&gt;func&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Warningf &lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;pkg/mod/k8s.io/client-go@v0.25.3/tools/cache/reflector.go:169: failed to list *v1.Pod: pods is forbidden: User \&amp;#34;system:serviceaccount:prometheus:default\&amp;#34; cannot list resource \&amp;#34;pods\&amp;#34; in API group \&amp;#34;\&amp;#34; at the cluster scope&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;ts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2022-11-28T14:26:56.156Z &lt;span class="nv"&gt;caller&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;klog.go:116 &lt;span class="nv"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;error &lt;span class="nv"&gt;component&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;k8s_client_runtime &lt;span class="nv"&gt;func&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ErrorDepth &lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;pkg/mod/k8s.io/client-go@v0.25.3/tools/cache/reflector.go:169: Failed to watch *v1.Service: failed to list *v1.Service: services is forbidden: User \&amp;#34;system:serviceaccount:prometheus:default\&amp;#34; cannot list resource \&amp;#34;services\&amp;#34; in API group \&amp;#34;\&amp;#34; at the cluster scope&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;ts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2022-11-28T14:26:56.156Z &lt;span class="nv"&gt;caller&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;klog.go:108 &lt;span class="nv"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;warn &lt;span class="nv"&gt;component&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;k8s_client_runtime &lt;span class="nv"&gt;func&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Warningf &lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;pkg/mod/k8s.io/client-go@v0.25.3/tools/cache/reflector.go:169: failed to list *v1.Endpoints: endpoints is forbidden: User \&amp;#34;system:serviceaccount:prometheus:default\&amp;#34; cannot list resource \&amp;#34;endpoints\&amp;#34; in API group \&amp;#34;\&amp;#34; at the cluster scope&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;ts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2022-11-28T14:26:56.156Z &lt;span class="nv"&gt;caller&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;klog.go:116 &lt;span class="nv"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;error &lt;span class="nv"&gt;component&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;k8s_client_runtime &lt;span class="nv"&gt;func&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ErrorDepth &lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;pkg/mod/k8s.io/client-go@v0.25.3/tools/cache/reflector.go:169: Failed to watch *v1.Endpoints: failed to list *v1.Endpoints: endpoints is forbidden: User \&amp;#34;system:serviceaccount:prometheus:default\&amp;#34; cannot list resource \&amp;#34;endpoints\&amp;#34; in API group \&amp;#34;\&amp;#34; at the cluster scope&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;According to the log, Prometheus is failing to get information of Pods, Services and Endpoints because the default ServiceAccount is not authorized.&lt;/p&gt;
&lt;p&gt;Then create ServiceAccount, ClusterRole and ClusterRoleBinding to gave permission.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n prometheus create serviceaccount prometheus
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;serviceaccount/prometheus created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create clusterrole prometheus --verb&lt;span class="o"&gt;=&lt;/span&gt;get,list,watch --resource&lt;span class="o"&gt;=&lt;/span&gt;pods,services,endpoints
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;clusterrole.rbac.authorization.k8s.io/prometheus created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create clusterrolebinding prometheus --clusterrole&lt;span class="o"&gt;=&lt;/span&gt;prometheus --serviceaccount&lt;span class="o"&gt;=&lt;/span&gt;prometheus:prometheus
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;clusterrolebinding.rbac.authorization.k8s.io/prometheus created&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Update the Deployment again.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/f4d81f8f3b5bcb4b83e5dc759251242f.js"&gt;&lt;/script&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f deployment.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps/prometheus configured&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This time it succeeded. Wow!&lt;/p&gt;
&lt;p&gt;&lt;img alt="Succeeded" class="gallery-image" data-flex-basis="458px" data-flex-grow="191" height="662" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor/sc06-service-discovery-success.png" srcset="https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor/sc06-service-discovery-success_hu_17d78e907eb74ff3.png 800w, https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor/sc06-service-discovery-success.png 1265w" width="1265"&gt;&lt;/p&gt;
&lt;p&gt;The metrics are correctly scraped.&lt;/p&gt;
&lt;p&gt;&lt;img alt="kube_pod_info(kube-state-metrics) and container_memory_usage_bytes(cAdvisor)" class="gallery-image" data-flex-basis="318px" data-flex-grow="132" height="954" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor/sc07-prometheus-metrics.png" srcset="https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor/sc07-prometheus-metrics_hu_58e6c0c1003747e9.png 800w, https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor/sc07-prometheus-metrics.png 1265w" width="1265"&gt;&lt;/p&gt;
&lt;p&gt;That is all.&lt;/p&gt;</description></item><item><title>Kubernetesクラスタにkube-state-metricsとcAdvisorをぶちこんでPrometheusで監視する</title><link>https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor-ja/</link><pubDate>Mon, 28 Nov 2022 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor-ja/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor-ja/sotochan.jpeg" alt="Featured image of post Kubernetesクラスタにkube-state-metricsとcAdvisorをぶちこんでPrometheusで監視する" /&gt;&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;p&gt;自分は普段すでに監視用アドオンが入った状態のマネージドKubernetesクラスタを使うのが当たり前になっている。&lt;br&gt;
それがどんなにありがたいことか分かってない気がしたのと、&lt;br&gt;
単純にそれらの構成がどうなっているのか興味があったので実際に手を動かして設定してみた。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;お試し用にkindでKubernetesクラスタ作成&lt;/li&gt;
&lt;li&gt;kube-state-metrics(Deployment)でKubernetesメトリクスを収集&lt;/li&gt;
&lt;li&gt;cAdvisor(DaemonSet)でコンテナメトリクスを収集&lt;/li&gt;
&lt;li&gt;Prometheus(Deployment)にService Discovery設定をして上記2種のメトリクスをモニタリング&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="構成" class="gallery-image" data-flex-basis="445px" data-flex-grow="185" height="421" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor-ja/component.drawio.png" width="781"&gt;&lt;/p&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kind.sigs.k8s.io/" target="_blank" rel="noopener"
 &gt;kind&lt;/a&gt; v0.17.0 go1.19.2 darwin/arm64&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://kubernetes.io/" target="_blank" rel="noopener"
 &gt;kubernetes&lt;/a&gt; v1.25.3&lt;/li&gt;
&lt;li&gt;kubectl v1.25.0&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://prometheus.io/" target="_blank" rel="noopener"
 &gt;prometheus&lt;/a&gt; version 2.40.3&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/kubernetes/kube-state-metrics" target="_blank" rel="noopener"
 &gt;kube-state-metrics&lt;/a&gt; v2.7.0&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/google/cadvisor" target="_blank" rel="noopener"
 &gt;cAdvisor&lt;/a&gt; v0.45.0&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;h3 id="kubernetesクラスタの作成"&gt;Kubernetesクラスタの作成
&lt;/h3&gt;&lt;p&gt;今回は特に構成にこだわりもないので適当にkindでシングルノードのKubernetesクラスタをつくる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kind create cluster
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Creating cluster &lt;span class="s2"&gt;&amp;#34;kind&amp;#34;&lt;/span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✓ Ensuring node image &lt;span class="o"&gt;(&lt;/span&gt;kindest/node:v1.25.3&lt;span class="o"&gt;)&lt;/span&gt; 🖼
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✓ Preparing nodes 📦
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✓ Writing configuration 📜
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✓ Starting control-plane 🕹️
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✓ Installing CNI 🔌
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✓ Installing StorageClass 💾
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Set kubectl context to &lt;span class="s2"&gt;&amp;#34;kind-kind&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;You can now use your cluster with:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl cluster-info --context kind-kind
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Have a question, bug, or feature request? Let us know! https://kind.sigs.k8s.io/#community 🙂&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="kube-state-metricsのインストール"&gt;kube-state-metricsのインストール
&lt;/h3&gt;&lt;p&gt;Kubernetesリソース(Podとか)のメトリクスといったらkube-state-metricsって感じなのでまずはこいつを入れていく。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/kubernetes/kube-state-metrics/tree/0cbabf95239b33e8a469630e63c668b8e9786ad3/examples/standard" target="_blank" rel="noopener"
 &gt;サンプルマニフェスト&lt;/a&gt;が公開されているのでそれを使ってみる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/kube-state-metrics/master/examples/standard/service-account.yaml &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubectl apply -f https://raw.githubusercontent.com/kubernetes/kube-state-metrics/master/examples/standard/cluster-role.yaml &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubectl apply -f https://raw.githubusercontent.com/kubernetes/kube-state-metrics/master/examples/standard/cluster-role-binding.yaml &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubectl apply -f https://raw.githubusercontent.com/kubernetes/kube-state-metrics/master/examples/standard/deployment.yaml &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubectl apply -f https://raw.githubusercontent.com/kubernetes/kube-state-metrics/master/examples/standard/service.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;serviceaccount/kube-state-metrics created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;clusterrole.rbac.authorization.k8s.io/kube-state-metrics created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;clusterrolebinding.rbac.authorization.k8s.io/kube-state-metrics created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps/kube-state-metrics created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/kube-state-metrics created&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;この手順でマニフェストをapplyするとkube-state-metricsがDeploymentとして動作する。&lt;br&gt;
Serviceも一緒に作られているのでport-forwardしてメトリクスを見てみる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n kube-system get deploy,service -l app.kubernetes.io/name&lt;span class="o"&gt;=&lt;/span&gt;kube-state-metrics
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY UP-TO-DATE AVAILABLE AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps/kube-state-metrics 1/1 &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 115s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/kube-state-metrics ClusterIP None &amp;lt;none&amp;gt; 8080/TCP,8081/TCP 115s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n kube-system port-forward service/kube-state-metrics 8080:8080 8081:8081
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Forwarding from 127.0.0.1:8080 -&amp;gt; &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Forwarding from &lt;span class="o"&gt;[&lt;/span&gt;::1&lt;span class="o"&gt;]&lt;/span&gt;:8080 -&amp;gt; &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Forwarding from 127.0.0.1:8081 -&amp;gt; &lt;span class="m"&gt;8081&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Forwarding from &lt;span class="o"&gt;[&lt;/span&gt;::1&lt;span class="o"&gt;]&lt;/span&gt;:8081 -&amp;gt; &lt;span class="m"&gt;8081&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# from different terminal&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl localhost:8080/metrics
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# HELP kube_configmap_labels [STABLE] Kubernetes labels converted to Prometheus labels.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# TYPE kube_configmap_labels gauge&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube_configmap_labels&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;local-path-storage&amp;#34;&lt;/span&gt;,configmap&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;local-path-config&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube_configmap_labels&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;default&amp;#34;&lt;/span&gt;,configmap&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;kube-root-ca.crt&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;こんな感じでkube-state-metricsはKubernetes APIをポーリングして得られたPodのステータスとかの情報をメトリクス化している。らしい。&lt;/p&gt;
&lt;p&gt;ちなみにメトリクスの詳細な説明は&lt;a class="link" href="https://github.com/kubernetes/kube-state-metrics/tree/master/docs" target="_blank" rel="noopener"
 &gt;docs&lt;/a&gt;で公開されている。&lt;/p&gt;
&lt;p&gt;実はUIも用意されているが、今回の目的ではないので割愛。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="http://localhost:8080/" target="_blank" rel="noopener"
 &gt;http://localhost:8080/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="/metricsはメトリクスを表示する /healthzはヘルスチェック用" class="gallery-image" data-flex-basis="619px" data-flex-grow="258" height="487" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor-ja/sc01-kube-state-metrics-ui.png" srcset="https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor-ja/sc01-kube-state-metrics-ui_hu_a8f70400275e100c.png 800w, https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor-ja/sc01-kube-state-metrics-ui.png 1257w" width="1257"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="http://localhost:8081/" target="_blank" rel="noopener"
 &gt;http://localhost:8081/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="こちらの/metricsはkube-state-metrics自体のメトリクス(Go関連とか)を表示する" class="gallery-image" data-flex-basis="619px" data-flex-grow="258" height="487" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor-ja/sc02-kube-state-metrics-ui.png" srcset="https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor-ja/sc02-kube-state-metrics-ui_hu_f7c026885602b1af.png 800w, https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor-ja/sc02-kube-state-metrics-ui.png 1257w" width="1257"&gt;&lt;/p&gt;
&lt;h3 id="cadvisorのインストール"&gt;cAdvisorのインストール
&lt;/h3&gt;&lt;p&gt;cAdvisorもコンテナ単位のメトリクスが見られて便利なのでこれも入れていく。&lt;/p&gt;
&lt;p&gt;こちらは&lt;a class="link" href="https://github.com/google/cadvisor/tree/master/deploy/kubernetes" target="_blank" rel="noopener"
 &gt;サンプルマニフェスト&lt;/a&gt;がkustomize化されているのでさらに簡単に入れられる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -k https://github.com/google/cadvisor//deploy/kubernetes/base
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;namespace/cadvisor created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;serviceaccount/cadvisor created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;daemonset.apps/cadvisor created&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;cAdvisorは各Node上のコンテナ情報を取得するためDaemonSetとして動作している。&lt;br&gt;
(昔はkubeletに勝手に入ってた気がするが、最近はDaemonSetで動かすのが普通っぽい?)&lt;/p&gt;
&lt;p&gt;kube-state-metricsと同様にport-forwardしてメトリクスを確認する。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n cadvisor get daemonset -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;cadvisor
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cadvisor &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &amp;lt;none&amp;gt; 6m54s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nv"&gt;pod&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;kubectl -n cadvisor get pod -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;cadvisor -o &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;{.items[0].metadata.name}&amp;#34;&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n cadvisor port-forward pod/&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;pod&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; 8080:8080
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Forwarding from 127.0.0.1:8080 -&amp;gt; &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Forwarding from &lt;span class="o"&gt;[&lt;/span&gt;::1&lt;span class="o"&gt;]&lt;/span&gt;:8080 -&amp;gt; &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# from different terminal&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl localhost:8080/metrics
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# HELP cadvisor_version_info A metric with a constant &amp;#39;1&amp;#39; value labeled by kernel version, OS version, docker version, cadvisor version &amp;amp; cadvisor revision.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# TYPE cadvisor_version_info gauge&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cadvisor_version_info&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;cadvisorRevision&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;86b11c65&amp;#34;&lt;/span&gt;,cadvisorVersion&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;v0.45.0&amp;#34;&lt;/span&gt;,dockerVersion&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,kernelVersion&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;5.10.124-linuxkit&amp;#34;&lt;/span&gt;,osVersion&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Alpine Linux v3.16&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# HELP container_blkio_device_usage_total Blkio Device bytes usage&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# TYPE container_blkio_device_usage_total counter&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;container_blkio_device_usage_total&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;container_label_app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,container_label_app_kubernetes_io_component&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,container_label_app_kubernetes_io_name&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,container_label_app_kubernetes_io_version&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,container_label_component&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,container_label_controller_revision_hash&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,container_label_description&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,container_label_io_cri_containerd_kind&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,container_label_io_kubernetes_container_name&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,container_label_io_kubernetes_pod_name&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,container_label_io_kubernetes_pod_namespace&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,container_label_io_kubernetes_pod_uid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,container_label_k8s_app&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,container_label_maintainers&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,container_label_name&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,container_label_pod_template_generation&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,container_label_pod_template_hash&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,container_label_tier&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,device&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/dev/vda&amp;#34;&lt;/span&gt;,id&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/&amp;#34;&lt;/span&gt;,image&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,major&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;254&amp;#34;&lt;/span&gt;,minor&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;0&amp;#34;&lt;/span&gt;,name&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,operation&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Read&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;1669642901054&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;container_**&lt;/code&gt;みたいな名前のメトリクスがとれていることがわかる。&lt;/p&gt;
&lt;p&gt;こちらも実はUIが用意されているが割愛。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="http://localhost:8080/" target="_blank" rel="noopener"
 &gt;http://localhost:8080/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="ふくろうかわいい" class="gallery-image" data-flex-basis="374px" data-flex-grow="155" height="811" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor-ja/sc03-cadvisor-ui.png" srcset="https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor-ja/sc03-cadvisor-ui_hu_8e11760766aba361.png 800w, https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor-ja/sc03-cadvisor-ui.png 1265w" width="1265"&gt;&lt;/p&gt;
&lt;h3 id="prometheusのインストール"&gt;Prometheusのインストール
&lt;/h3&gt;&lt;p&gt;Kubernetesリソースとコンテナのメトリクスが用意できたので、&lt;br&gt;
次にこれをモニタリングするPrometheusを用意する。&lt;/p&gt;
&lt;p&gt;ちょっと探したけどPrometheusについては公式っぽいKubernetesマニフェスト例が見つからなかったので自分でちょろっと書いて立ててみる。&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/a09c3dd0bc680144d6110ff3bd5c98c8.js"&gt;&lt;/script&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create namespace prometheus
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;namespace/prometheus created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n prometheus apply -f deployment.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps/prometheus created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n prometheus expose deployment prometheus --port&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;9090&lt;/span&gt; --target-port&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;9090&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/prometheus exposed&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;今回は特にメトリクスを永続化したいわけではなかったのでPrometheusをDeploymentとして立てた。&lt;br&gt;
(メトリクスを永続化したいときはStatefulSetで立てたり、クラスタ外にFederateしたりいろいろやり方はあるとおもう)&lt;/p&gt;
&lt;p&gt;これも同様にport-forwardしてUIを開いて動作確認する。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n prometheus port-forward service/prometheus 9090:9090
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Forwarding from 127.0.0.1:9090 -&amp;gt; &lt;span class="m"&gt;9090&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Forwarding from &lt;span class="o"&gt;[&lt;/span&gt;::1&lt;span class="o"&gt;]&lt;/span&gt;:9090 -&amp;gt; &lt;span class="m"&gt;9090&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a class="link" href="http://localhost:9090/" target="_blank" rel="noopener"
 &gt;http://localhost:9090/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="いつもの" class="gallery-image" data-flex-basis="374px" data-flex-grow="155" height="811" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor-ja/sc04-prometheus-ui.png" srcset="https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor-ja/sc04-prometheus-ui_hu_53350ffa4126489e.png 800w, https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor-ja/sc04-prometheus-ui.png 1265w" width="1265"&gt;&lt;/p&gt;
&lt;p&gt;いい感じ。&lt;/p&gt;
&lt;h3 id="prometheusの監視設定kubernetes_sd_config"&gt;Prometheusの監視設定(kubernetes_sd_config)
&lt;/h3&gt;&lt;p&gt;最後にこのPrometheusでkube-state-metricsとcAdvisorのメトリクスが取れるように設定していく。&lt;/p&gt;
&lt;p&gt;Kubernetesクラスタ内のメトリクスをPrometheusで監視する場合&lt;a class="link" href="https://prometheus.io/docs/prometheus/latest/configuration/configuration/#static_config" target="_blank" rel="noopener"
 &gt;static_config&lt;/a&gt;にいちいちServiceやPodのIPを羅列していては日が暮れてしまうし、&lt;br&gt;
それらが変化してしまったときに動的に追従させるのが大変というかたぶん無理。&lt;/p&gt;
&lt;p&gt;このため通常は&lt;a class="link" href="https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config" target="_blank" rel="noopener"
 &gt;kubernetes_sd_config&lt;/a&gt;を使ってクラスタ内のServiceやPodの宛先をPrometheusが勝手に探すようにする(Service Discovery)。&lt;/p&gt;
&lt;p&gt;これについては&lt;a class="link" href="https://github.com/prometheus/prometheus/blob/main/documentation/examples/prometheus-kubernetes.yml" target="_blank" rel="noopener"
 &gt;公式の例&lt;/a&gt;があるのでこちらを参考にさせてもらう。&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/04f5f04f8f0c9f202e80335eadb7cc42.js"&gt;&lt;/script&gt;
&lt;p&gt;今回はrelabel_configsの設定でモニタリングの対象をkube-state-metricsのServiceとcAdvisorのDaemonSet(Pod)に絞っている。&lt;br&gt;
(&lt;code&gt;role: pod&lt;/code&gt;のsd設定を入れると全Podのメトリクスが対象となり&lt;code&gt;role: service&lt;/code&gt;のsd設定で対象となっているメトリクスと重複するため)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n cadvisor get pods --show-labels
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE LABELS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cadvisor-fngj6 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 23h &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;cadvisor,controller-revision-hash&lt;span class="o"&gt;=&lt;/span&gt;df8bf66b4,name&lt;span class="o"&gt;=&lt;/span&gt;cadvisor,pod-template-generation&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n kube-system get service kube-state-metrics --show-labels
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE LABELS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube-state-metrics ClusterIP None &amp;lt;none&amp;gt; 8080/TCP,8081/TCP 24h app.kubernetes.io/component&lt;span class="o"&gt;=&lt;/span&gt;exporter,app.kubernetes.io/name&lt;span class="o"&gt;=&lt;/span&gt;kube-state-metrics,app.kubernetes.io/version&lt;span class="o"&gt;=&lt;/span&gt;2.7.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f configmap.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;configmap/prometheus-config created&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;ついでにこのConfigMapを読み込むようにDeploymentの設定も修正する。&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/49300e02d52eb981869e65b1b76d209c.js"&gt;&lt;/script&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f deployment.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps/prometheus configured&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;この状態でPrometheusのService Discoveryの状態を確認する。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="http://localhost:9090/service-discovery" target="_blank" rel="noopener"
 &gt;http://localhost:9090/service-discovery&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="とれてない" class="gallery-image" data-flex-basis="374px" data-flex-grow="155" height="811" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor-ja/sc05-service-discovery-fail.png" srcset="https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor-ja/sc05-service-discovery-fail_hu_9fed600bd58abadd.png 800w, https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor-ja/sc05-service-discovery-fail.png 1265w" width="1265"&gt;&lt;/p&gt;
&lt;p&gt;&amp;hellip;あれ？&lt;br&gt;
なんかできてなさそう。&lt;/p&gt;
&lt;p&gt;Podのログを確認してみる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nv"&gt;pod&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;kubectl -n prometheus get pods -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;prometheus -o &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;{.items[0].metadata.name}&amp;#34;&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n prometheus logs &lt;span class="nv"&gt;$pod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;ts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2022-11-28T14:26:56.150Z &lt;span class="nv"&gt;caller&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes.go:326 &lt;span class="nv"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;info &lt;span class="nv"&gt;component&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;discovery manager scrape&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;discovery&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes &lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Using pod service account via in-cluster config&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;ts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2022-11-28T14:26:56.150Z &lt;span class="nv"&gt;caller&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;main.go:1234 &lt;span class="nv"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;info &lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Completed loading of configuration file&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/config/prometheus.yml &lt;span class="nv"&gt;totalDuration&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2.798834ms &lt;span class="nv"&gt;db_storage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.208µs &lt;span class="nv"&gt;remote_storage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.417µs &lt;span class="nv"&gt;web_handler&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;375ns &lt;span class="nv"&gt;query_engine&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.042µs &lt;span class="nv"&gt;scrape&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;250.917µs &lt;span class="nv"&gt;scrape_sd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2.159042ms &lt;span class="nv"&gt;notify&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.083µs &lt;span class="nv"&gt;notify_sd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5.709µs &lt;span class="nv"&gt;rules&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.584µs &lt;span class="nv"&gt;tracing&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;12.958µs
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;ts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2022-11-28T14:26:56.150Z &lt;span class="nv"&gt;caller&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;main.go:978 &lt;span class="nv"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;info &lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Server is ready to receive web requests.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;ts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2022-11-28T14:26:56.150Z &lt;span class="nv"&gt;caller&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;manager.go:944 &lt;span class="nv"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;info &lt;span class="nv"&gt;component&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;rule manager&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Starting rule manager...&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;ts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2022-11-28T14:26:56.156Z &lt;span class="nv"&gt;caller&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;klog.go:108 &lt;span class="nv"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;warn &lt;span class="nv"&gt;component&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;k8s_client_runtime &lt;span class="nv"&gt;func&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Warningf &lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;pkg/mod/k8s.io/client-go@v0.25.3/tools/cache/reflector.go:169: failed to list *v1.Service: services is forbidden: User \&amp;#34;system:serviceaccount:prometheus:default\&amp;#34; cannot list resource \&amp;#34;services\&amp;#34; in API group \&amp;#34;\&amp;#34; at the cluster scope&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;ts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2022-11-28T14:26:56.156Z &lt;span class="nv"&gt;caller&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;klog.go:108 &lt;span class="nv"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;warn &lt;span class="nv"&gt;component&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;k8s_client_runtime &lt;span class="nv"&gt;func&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Warningf &lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;pkg/mod/k8s.io/client-go@v0.25.3/tools/cache/reflector.go:169: failed to list *v1.Pod: pods is forbidden: User \&amp;#34;system:serviceaccount:prometheus:default\&amp;#34; cannot list resource \&amp;#34;pods\&amp;#34; in API group \&amp;#34;\&amp;#34; at the cluster scope&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;ts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2022-11-28T14:26:56.156Z &lt;span class="nv"&gt;caller&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;klog.go:116 &lt;span class="nv"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;error &lt;span class="nv"&gt;component&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;k8s_client_runtime &lt;span class="nv"&gt;func&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ErrorDepth &lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;pkg/mod/k8s.io/client-go@v0.25.3/tools/cache/reflector.go:169: Failed to watch *v1.Service: failed to list *v1.Service: services is forbidden: User \&amp;#34;system:serviceaccount:prometheus:default\&amp;#34; cannot list resource \&amp;#34;services\&amp;#34; in API group \&amp;#34;\&amp;#34; at the cluster scope&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;ts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2022-11-28T14:26:56.156Z &lt;span class="nv"&gt;caller&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;klog.go:108 &lt;span class="nv"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;warn &lt;span class="nv"&gt;component&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;k8s_client_runtime &lt;span class="nv"&gt;func&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Warningf &lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;pkg/mod/k8s.io/client-go@v0.25.3/tools/cache/reflector.go:169: failed to list *v1.Endpoints: endpoints is forbidden: User \&amp;#34;system:serviceaccount:prometheus:default\&amp;#34; cannot list resource \&amp;#34;endpoints\&amp;#34; in API group \&amp;#34;\&amp;#34; at the cluster scope&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;ts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2022-11-28T14:26:56.156Z &lt;span class="nv"&gt;caller&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;klog.go:116 &lt;span class="nv"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;error &lt;span class="nv"&gt;component&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;k8s_client_runtime &lt;span class="nv"&gt;func&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ErrorDepth &lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;pkg/mod/k8s.io/client-go@v0.25.3/tools/cache/reflector.go:169: Failed to watch *v1.Endpoints: failed to list *v1.Endpoints: endpoints is forbidden: User \&amp;#34;system:serviceaccount:prometheus:default\&amp;#34; cannot list resource \&amp;#34;endpoints\&amp;#34; in API group \&amp;#34;\&amp;#34; at the cluster scope&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;エラーメッセージ的に&amp;quot;デフォルトで設定されたServiceAccount(&lt;code&gt;prometheus:default&lt;/code&gt;)にPodとかServiceを見る権限が無いよ!&amp;ldquo;って感じなので、&lt;br&gt;
ServiceAccount, ClusterRole, ClusterRoleBindingを作ってやる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n prometheus create serviceaccount prometheus
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;serviceaccount/prometheus created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create clusterrole prometheus --verb&lt;span class="o"&gt;=&lt;/span&gt;get,list,watch --resource&lt;span class="o"&gt;=&lt;/span&gt;pods,services,endpoints
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;clusterrole.rbac.authorization.k8s.io/prometheus created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create clusterrolebinding prometheus --clusterrole&lt;span class="o"&gt;=&lt;/span&gt;prometheus --serviceaccount&lt;span class="o"&gt;=&lt;/span&gt;prometheus:prometheus
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;clusterrolebinding.rbac.authorization.k8s.io/prometheus created&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;またまたDeploymentをいじって↑で権限を付与したServiceAccountを使ってPodを立てるようにする。&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/f4d81f8f3b5bcb4b83e5dc759251242f.js"&gt;&lt;/script&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f deployment.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps/prometheus configured&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;再度立ち上がったPrometheusを確認すると今度はService Discoveryに成功している。&lt;/p&gt;
&lt;p&gt;&lt;img alt="とれてる" class="gallery-image" data-flex-basis="458px" data-flex-grow="191" height="662" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor-ja/sc06-service-discovery-success.png" srcset="https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor-ja/sc06-service-discovery-success_hu_17d78e907eb74ff3.png 800w, https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor-ja/sc06-service-discovery-success.png 1265w" width="1265"&gt;&lt;/p&gt;
&lt;p&gt;試しにPrometheus自身のPod, コンテナのメトリクスをクエリで探すと確かに値が返ってくる。&lt;/p&gt;
&lt;p&gt;&lt;img alt="kube-state-metricsとcAdvisorのメトリクスが取れている" class="gallery-image" data-flex-basis="318px" data-flex-grow="132" height="954" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor-ja/sc07-prometheus-metrics.png" srcset="https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor-ja/sc07-prometheus-metrics_hu_58e6c0c1003747e9.png 800w, https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor-ja/sc07-prometheus-metrics.png 1265w" width="1265"&gt;&lt;/p&gt;
&lt;p&gt;ええやん。&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;Kubernetesクラスタにkube-state-metricsとcAdvisorを導入し、&lt;br&gt;
クラスタ内のPrometheusでそれらのメトリクスをモニタリングするところまでやってみた。&lt;/p&gt;
&lt;p&gt;今回は&lt;a class="link" href="https://github.com/prometheus-operator/prometheus-operator" target="_blank" rel="noopener"
 &gt;prometheus-operator&lt;/a&gt;とか使わずに全部手作業で立てたので結構面倒だったが、&lt;br&gt;
たまにこうやって遊ぶと楽しいし、こういうやつを勝手に作成してくれる仕組みのありがたさがよくわかる気がする。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="!って感じのねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor-ja/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor-ja/sotochan_hu_9c529dff509805ad.jpeg 800w, https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor-ja/sotochan_hu_b1123a897c589f0c.jpeg 1600w, https://blog.uzimihsr.com/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor-ja/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>10月のそとちゃん(2022)</title><link>https://blog.uzimihsr.com/post/2022-11-09-sotochan/</link><pubDate>Wed, 09 Nov 2022 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2022-11-09-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan.jpeg" alt="Featured image of post 10月のそとちゃん(2022)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e6%af%9b%e5%b8%83" &gt;毛布&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%88%e3%83%83%e3%83%94%e3%83%b3%e3%82%b0" &gt;トッピング&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%8f%e3%83%ad%e3%82%a6%e3%82%a3%e3%83%b3" &gt;ハロウィン&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="毛布"&gt;毛布
&lt;/h3&gt;&lt;p&gt;ちょっと寒くなってきたので毛布を出した。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;毛布出しました &lt;a href="https://t.co/KmlAMRIXk8"&gt;pic.twitter.com/KmlAMRIXk8&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1578958850807726080?ref_src=twsrc%5Etfw"&gt;October 9, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;そとちゃんは毛布の上に乗るのが好き。&lt;/p&gt;
&lt;p&gt;昼間はずっと毛布の上でごろごろしている。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ずっといる &lt;a href="https://t.co/TOvtXOUp2F"&gt;pic.twitter.com/TOvtXOUp2F&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1582961236240912386?ref_src=twsrc%5Etfw"&gt;October 20, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;ひなたぼっこが気持ちよさそう。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;かぁ〜っ &lt;a href="https://t.co/bvE24ZiB0C"&gt;pic.twitter.com/bvE24ZiB0C&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1585866748326469632?ref_src=twsrc%5Etfw"&gt;October 28, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2022-03-10-sotochan/#%E6%AF%9B%E5%B8%83" target="_blank" rel="noopener"
 &gt;以前&lt;/a&gt;とは違って、毛布の上で寝落ちするようになった。&lt;/p&gt;
&lt;p&gt;たまらなくかわいい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ねむい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan01_hu_bd0646e463d3bc02.jpeg 800w, https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan01_hu_d204ef7eee02f332.jpeg 1600w, https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="寝落ち" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan02_hu_69aca42c34382dbe.jpeg 800w, https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan02_hu_4f0ea5622b36f02b.jpeg 1600w, https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;こんなに好きな毛布だけど、上からかぶせると嫌がる。&lt;/p&gt;
&lt;p&gt;毛布より軽いブランケットを掛けても逃げるので、たぶん何かこだわりがある。&lt;/p&gt;
&lt;p&gt;圧迫感があるのかな？&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ブランケットの上はすき&lt;br&gt;被るのはだめ &lt;a href="https://t.co/PahXiRgWFL"&gt;pic.twitter.com/PahXiRgWFL&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1583310701351047168?ref_src=twsrc%5Etfw"&gt;October 21, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;ちなみに日が出てない日も毛布の上で転がって外を眺めている。&lt;/p&gt;
&lt;p&gt;楽しそうでなにより。&lt;/p&gt;
&lt;p&gt;&lt;img alt="これは鳥が来るまでねばっている" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan03_hu_764cdc13b59b6709.jpeg 800w, https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan03_hu_69f24bdc0453bec0.jpeg 1600w, https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan03_hu_754940a8c817df3f.jpeg 2400w, https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan03.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;h3 id="トッピング"&gt;トッピング
&lt;/h3&gt;&lt;p&gt;最近の我が家のルールとして、&lt;br&gt;
朝昼のカリカリを食べた量に応じて晩ごはんのトッピングのレベルが変わる報酬制が採用されている。&lt;br&gt;
(そとちゃんがあまりにもカリカリを残すので俺が勝手に制定した)&lt;/p&gt;
&lt;p&gt;このため、カリカリをガッツリ残した日は晩ごはんの猫缶が素の状態で出てくる。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;晩ごはんにトッピングが無くて固まるねこ&lt;br&gt;&lt;br&gt;(今日はカリカリ爆残しなのでトッピングなし) &lt;a href="https://t.co/MjDE9UH051"&gt;pic.twitter.com/MjDE9UH051&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1580148683899039744?ref_src=twsrc%5Etfw"&gt;October 12, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;トッピングがないと露骨に食いつきが悪くなり、目つきも悪くなる。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;今日もトッピングなしです &lt;a href="https://t.co/9hMjBbSKdU"&gt;pic.twitter.com/9hMjBbSKdU&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1580853322759929856?ref_src=twsrc%5Etfw"&gt;October 14, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;&lt;img alt="それでもやっぱり食べる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan04_hu_36a879b03100c521.jpeg 800w, https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan04_hu_875f8a136b3f24f4.jpeg 1600w, https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;その代わりカリカリを半分くらい食べた日はかつお節がかかったり、&lt;br&gt;
完食した日はなんとちゅーるがトッピングされる。&lt;/p&gt;
&lt;p&gt;おいしそう。&lt;/p&gt;
&lt;p&gt;&lt;img alt="マシマシ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan05_hu_c8d0da389c3089eb.jpeg 800w, https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan05_hu_dec5e95d34bad7a.jpeg 1600w, https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan05.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;でも次の日はまたカリカリをガッツリ残してトッピング無しに戻ることもしばしば。&lt;/p&gt;
&lt;p&gt;たぶんまだこの因果関係を理解していない。&lt;/p&gt;
&lt;p&gt;いつかそとちゃんがこれに気づいてカリカリを毎日完食してくれるといいなと思う。&lt;/p&gt;
&lt;h3 id="ハロウィン"&gt;ハロウィン
&lt;/h3&gt;&lt;p&gt;気づいたらハロウィンだったので今年もそとちゃんに仮装してもらった。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ドラキュラねこ&lt;a href="https://twitter.com/hashtag/HappyHalloween?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#HappyHalloween&lt;/a&gt; &lt;a href="https://t.co/VvYsHk6jWW"&gt;pic.twitter.com/VvYsHk6jWW&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1587019826719264768?ref_src=twsrc%5Etfw"&gt;October 31, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;例年通りドラキュラマント。&lt;/p&gt;
&lt;p&gt;かわいい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="かわいいね" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan06_hu_3b11a9124d6cd025.jpeg 800w, https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan06_hu_153301bca3674f8f.jpeg 1600w, https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan06.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2021-11-08-sotochan/#%E3%83%8F%E3%83%AD%E3%82%A6%E3%82%A3%E3%83%B3" target="_blank" rel="noopener"
 &gt;去年のこうもりポンチョ&lt;/a&gt;はあんまり気に入ってくれなかったけど、&lt;br&gt;
やっぱりこのマントは平気らしい。&lt;/p&gt;
&lt;p&gt;マントつけたまま部屋の中をうろうろしたり、あまり気にならないようだった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="かっこいい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan07_hu_790e58bb96fed038.jpeg 800w, https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan07_hu_11f732cd7e864dd7.jpeg 1600w, https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan07.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;俺のわがままにつきあってくれたので、&lt;br&gt;
もちろんごほうびをあげた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="報酬" class="gallery-image" data-flex-basis="341px" data-flex-grow="142" height="823" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan08.png" srcset="https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan08_hu_807388399fbf4eb3.png 800w, https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan08.png 1172w" width="1172"&gt;&lt;/p&gt;
&lt;p&gt;来年もやろう&amp;hellip;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;今年もあっという間に10月が終わってしまった。&lt;/p&gt;
&lt;p&gt;とはいえそとちゃんも俺も特に変わらず毎日平和にごろごろしている。&lt;/p&gt;
&lt;p&gt;たのしい。&lt;/p&gt;
&lt;p&gt;今は毛布で耐えていられるけど、本格的に寒くなったらそろそろ&amp;quot;アレ&amp;quot;の出番が来るかもしれない&amp;hellip;&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="横からのドラキュラそとちゃん(マントは毛だらけ)" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan_hu_e694ba59f3cae1d9.jpeg 800w, https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan_hu_a715d58d9255482a.jpeg 1600w, https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan_hu_6dd7a857bbd16f54.jpeg 2400w, https://blog.uzimihsr.com/post/2022-11-09-sotochan/sotochan.jpeg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>9月のそとちゃん(2022)</title><link>https://blog.uzimihsr.com/post/2022-10-07-sotochan/</link><pubDate>Fri, 07 Oct 2022 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2022-10-07-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2022-10-07-sotochan/sotochan.jpeg" alt="Featured image of post 9月のそとちゃん(2022)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e7%97%85%e9%99%a2" &gt;病院&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%8a%e6%95%a3%e6%ad%a9" &gt;お散歩&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e7%aa%93%e9%9a%9b%e6%97%8f" &gt;窓際族&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="病院"&gt;病院
&lt;/h3&gt;&lt;p&gt;年に1回のワクチンを打つため、久しぶりに病院に行った。&lt;/p&gt;
&lt;p&gt;キャリーにはすんなり入るそとちゃん。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;お出かけします &lt;a href="https://t.co/jv2XlTOjq7"&gt;pic.twitter.com/jv2XlTOjq7&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1571279629352308736?ref_src=twsrc%5Etfw"&gt;September 17, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;この日は雨だったので車移動。&lt;/p&gt;
&lt;p&gt;キャリーケースに入れられて車の中だとあんまり外の景色が見られなくてつまらなさそうだった。&lt;/p&gt;
&lt;p&gt;病院についてすぐに診察。&lt;/p&gt;
&lt;p&gt;体重は4.04kg。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2022-04-07-sotochan/#%E7%97%85%E9%99%A2" target="_blank" rel="noopener"
 &gt;前回行ったときに聞き忘れた&lt;/a&gt;ごはんの量は体重が4kgくらいをキープできてるならこのままでいいらしい。&lt;/p&gt;
&lt;p&gt;ちょっと不安なのは歯石が気になると言われたこと。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2021-09-30-sotochan/#%E7%97%85%E9%99%A2" target="_blank" rel="noopener"
 &gt;去年&lt;/a&gt;歯肉炎の兆候があったときは塗り薬を処方してもらったり、&lt;br&gt;
それからも毎晩できる範囲で(めっちゃ嫌がるが)歯みがきをしてきたものの、&lt;br&gt;
あまり良くなってないようだった。&lt;/p&gt;
&lt;p&gt;今の状態だと全身麻酔をして歯石のクリーニングをするしかないらしい。&lt;/p&gt;
&lt;p&gt;全身麻酔は&lt;a class="link" href="https://uzimihsr.github.io/post/2021-12-31-sotochan/" target="_blank" rel="noopener"
 &gt;昨年末の手術&lt;/a&gt;で一度経験しているので大丈夫そうだが、&lt;br&gt;
この日は去年歯を診てくれた先生と違う若手の先生で割とアグレッシブにおすすめしてきたので、&lt;br&gt;
勢いで決めるのも怖いと思ってこの日は手術の申し込みをしなかった。&lt;/p&gt;
&lt;p&gt;肝心のワクチンもしっかり打ってもらった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Vaccinated" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-10-07-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2022-10-07-sotochan/sotochan03_hu_56ac44fa285666be.jpeg 800w, https://blog.uzimihsr.com/post/2022-10-07-sotochan/sotochan03_hu_2ac7903100eae836.jpeg 1600w, https://blog.uzimihsr.com/post/2022-10-07-sotochan/sotochan03.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;前回と全く同じでおしりに体温計を入れるときに一番暴れて(体温は37.6℃)、&lt;br&gt;
注射のときだけおとなしかった(なんで？)。&lt;/p&gt;
&lt;p&gt;診察が終わってすぐ帰れると思ったらちょうど受付が混み出す時間帯にぶつかってしまい、&lt;br&gt;
会計が出るまで待合室で待つことになった。&lt;/p&gt;
&lt;p&gt;いつもそうだけど病院の待合室はキャリーに入ってない犬がいっぱいいて、&lt;br&gt;
俺は犬がダメなのでかなりこわかった。&lt;/p&gt;
&lt;p&gt;そとちゃんはやっぱり他の犬猫には興味ないみたいで、&lt;br&gt;
いつも通りキャリーの中でごろごろしていた。&lt;/p&gt;
&lt;p&gt;&amp;hellip;というわけでもなく、この日はかなり興奮した子犬が1頭暴れ回っていて、&lt;br&gt;
流石にちょっと驚いていた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="やべーやつを見る顔" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-10-07-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2022-10-07-sotochan/sotochan01_hu_30290961c4ee39b5.jpeg 800w, https://blog.uzimihsr.com/post/2022-10-07-sotochan/sotochan01_hu_2a8598085df14a5d.jpeg 1600w, https://blog.uzimihsr.com/post/2022-10-07-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;以降は特に何もなくさっさと帰宅。&lt;/p&gt;
&lt;p&gt;病院に行くときはいつも診察室を探検して楽しそうなのに、&lt;br&gt;
この日は混んでたこともあり診察が終わってすぐキャリーに入れられてしまったそとちゃん。&lt;/p&gt;
&lt;p&gt;帰宅してからもなんか元気がなくて少しかわいそうだった。&lt;br&gt;
(その後起きておやつをガッツリ食べた)&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;つかれた &lt;a href="https://t.co/JD1qG6EgY4"&gt;pic.twitter.com/JD1qG6EgY4&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1571345261666111489?ref_src=twsrc%5Etfw"&gt;September 18, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;&lt;img alt="俺のお腹の上でふて寝した" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-10-07-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2022-10-07-sotochan/sotochan02_hu_5e88f0ae119ce0.jpeg 800w, https://blog.uzimihsr.com/post/2022-10-07-sotochan/sotochan02_hu_a0269dbd04349653.jpeg 1600w, https://blog.uzimihsr.com/post/2022-10-07-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="お散歩"&gt;お散歩
&lt;/h3&gt;&lt;p&gt;せっかくのおでかけ(病院)がつまんなくてかわいそうだったのと、&lt;br&gt;
なんか最近ドアの前で鳴くことが多かったので、&lt;br&gt;
気分転換に家の周りを何回かお散歩してみた。&lt;/p&gt;
&lt;p&gt;とはいえそとちゃんは&lt;a class="link" href="https://uzimihsr.github.io/post/2021-09-09-sotochan/#%E3%81%8A%E3%81%A7%E3%81%8B%E3%81%91" target="_blank" rel="noopener"
 &gt;ハーネスをつけられると動かなくなってしまう&lt;/a&gt;ので、&lt;br&gt;
はじめは抱っこしてお散歩。&lt;/p&gt;
&lt;p&gt;これだと数分で腕が疲れてくるし、&lt;br&gt;
何より俺の両手が塞がってちょっと危ないので別の方法を考えた。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;散歩した &lt;a href="https://t.co/IsV4NaWq6T"&gt;pic.twitter.com/IsV4NaWq6T&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1573859309565677568?ref_src=twsrc%5Etfw"&gt;September 25, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;↑の写真のようにハーネスをつけた状態で昔使ってたリュック型のキャリーに入れ、&lt;br&gt;
キャリーの窓を開けてみた。&lt;/p&gt;
&lt;p&gt;これだと両手も使えるし、そとちゃんも楽な姿勢で外の景色を堪能できていい感じ。&lt;/p&gt;
&lt;p&gt;散歩してみて気づいたのだが新居の周りは犬を散歩させてる人が結構いて、&lt;br&gt;
ねこの散歩は珍しいようで何度か話しかけられた。&lt;/p&gt;
&lt;p&gt;そとちゃんは人見知りしないので、&lt;br&gt;
知らない人に話しかけられてもちゃんとお返事をしていい子だった。&lt;/p&gt;
&lt;p&gt;その人が連れてる犬のことはガン無視していた。&lt;/p&gt;
&lt;h3 id="窓際族"&gt;窓際族
&lt;/h3&gt;&lt;p&gt;引越してから約1ヶ月経ち、&lt;br&gt;
そとちゃんもちょっとずつ新居の良さ(?)がわかってきた様子。&lt;/p&gt;
&lt;p&gt;特に日当たりの良い窓際がいい感じ。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ひなたぼっこ &lt;a href="https://t.co/Dw4PJ5J3Sc"&gt;pic.twitter.com/Dw4PJ5J3Sc&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1572444670613147648?ref_src=twsrc%5Etfw"&gt;September 21, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;天気の良い日は高確率で窓際にいる。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ねてる &lt;a href="https://t.co/h3Dy8BHqLC"&gt;pic.twitter.com/h3Dy8BHqLC&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1574992669134450689?ref_src=twsrc%5Etfw"&gt;September 28, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;西日をガッツリ浴びて楽しそう。&lt;/p&gt;
&lt;p&gt;&lt;img alt="背中もしっかり日にあてる(?)" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-10-07-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2022-10-07-sotochan/sotochan04_hu_8249856ce128d00f.jpeg 800w, https://blog.uzimihsr.com/post/2022-10-07-sotochan/sotochan04_hu_439f82e0ec207dd3.jpeg 1600w, https://blog.uzimihsr.com/post/2022-10-07-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="気持ちよさそうに毛づくろい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-10-07-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2022-10-07-sotochan/sotochan05_hu_6e81a24fd0bbea24.jpeg 800w, https://blog.uzimihsr.com/post/2022-10-07-sotochan/sotochan05_hu_916173f9d48505d1.jpeg 1600w, https://blog.uzimihsr.com/post/2022-10-07-sotochan/sotochan05.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;あとたまにベランダ(正確には向かいのお家の屋上)にカラスがくるのがアツいっぽい。&lt;/p&gt;
&lt;p&gt;ねこの天敵だから怖がるかと思ったけど、&lt;br&gt;
そとちゃんは自分が安全な所にいるのがわかっているから(?)いつも面白そうにみている。&lt;/p&gt;
&lt;p&gt;ちなみにクラッキングはしない。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ベランダに鳥が来た &lt;a href="https://t.co/dM1QGdKhRQ"&gt;pic.twitter.com/dM1QGdKhRQ&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1575041525146587137?ref_src=twsrc%5Etfw"&gt;September 28, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;はじめはなかなかひなたぼっこしてくれなかったりして不安だったが、&lt;br&gt;
今は毎日楽しそうなので、やっぱり引っ越してよかった。&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;9月はおでかけする機会が多かった。&lt;/p&gt;
&lt;p&gt;そろそろ涼しくなってきて虫も減るし、散歩の頻度を増やしてもいいかもしれない。&lt;/p&gt;
&lt;p&gt;歯石のクリーニングについては心配なので自分でももう少し情報を集めてから慎重に判断したいと思う。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="ねこトースト" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-10-07-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2022-10-07-sotochan/sotochan_hu_14856e7894be489a.jpeg 800w, https://blog.uzimihsr.com/post/2022-10-07-sotochan/sotochan_hu_8e57fbe34234c33.jpeg 1600w, https://blog.uzimihsr.com/post/2022-10-07-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>golang: Trust a self-signed certificate in a scratch image</title><link>https://blog.uzimihsr.com/post/2022-09-29-golang-scratch-trust-cert/</link><pubDate>Thu, 29 Sep 2022 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2022-09-29-golang-scratch-trust-cert/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2022-09-29-golang-scratch-trust-cert/sotochan.jpeg" alt="Featured image of post golang: Trust a self-signed certificate in a scratch image" /&gt;&lt;h2 id="summary"&gt;Summary
&lt;/h2&gt;&lt;p&gt;To trust a self-signed certificate in a scratch image, copy the certificate at the build stage, update the trusted ca-certificates, and then copy it to the scratch image.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/4ed140a8b9a15a19b0537460e9b857c8.js"&gt;&lt;/script&gt;
&lt;h2 id="prerequisites"&gt;Prerequisites
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Docker version 20.10.17, build 100c701&lt;/li&gt;
&lt;li&gt;go version go1.18.1 darwin/arm64&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/layers/library/nginx/1.23.1/images/sha256-79c77eb7ca32f9a117ef91bc6ac486014e0d0e75f2f06683ba24dc298f9f4dd4?context=explore" target="_blank" rel="noopener"
 &gt;nginx:1.23.1&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="example"&gt;Example
&lt;/h2&gt;&lt;h3 id="create-a-self-signed-certificate-and-run-a-https-server-on-nginx"&gt;Create a self-signed certificate and run a HTTPS server on nginx
&lt;/h3&gt;&lt;p&gt;First, create a self-signed certificate.&lt;br&gt;
There are many ways to do this, but I prefer to do it with openssl in Docker.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run --rm -it -v&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt;&lt;span class="s2"&gt;:/workdir&amp;#34;&lt;/span&gt; -w&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/workdir&amp;#34;&lt;/span&gt; --entrypoint&lt;span class="o"&gt;=&lt;/span&gt;/bin/bash nginx:1.23.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;root@e08bb1ebe3da:/workdir# openssl version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;OpenSSL 1.1.1n &lt;span class="m"&gt;15&lt;/span&gt; Mar &lt;span class="m"&gt;2022&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;root@e08bb1ebe3da:/workdir# openssl genpkey -algorithm RSA -out server-private-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...................+++++
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;......................................................................................................+++++
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;root@e08bb1ebe3da:/workdir# openssl req -x509 -key server-private-key.pem -out server-cert.pem -addext &lt;span class="s1"&gt;&amp;#39;subjectAltName = DNS:hogehoge.uzimihsr.com&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;You are about to be asked to enter information that will be incorporated
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;into your certificate request.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;What you are about to enter is what is called a Distinguished Name or a DN.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;There are quite a few fields but you can leave some blank
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;For some fields there will be a default value,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;If you enter &lt;span class="s1"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;, the field will be left blank.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-----
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Country Name &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; letter code&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;AU&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;State or Province Name &lt;span class="o"&gt;(&lt;/span&gt;full name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Some-State&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Locality Name &lt;span class="o"&gt;(&lt;/span&gt;eg, city&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Organization Name &lt;span class="o"&gt;(&lt;/span&gt;eg, company&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Internet Widgits Pty Ltd&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Organizational Unit Name &lt;span class="o"&gt;(&lt;/span&gt;eg, section&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Common Name &lt;span class="o"&gt;(&lt;/span&gt;e.g. server FQDN or YOUR name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:hogehoge.uzimihsr.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Email Address &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;root@e08bb1ebe3da:/workdir#
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# the private key and the self-signed certificates are created on the host&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;server-cert.pem		server-private-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then start a HTTPS server on nginx.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/8a34bfd167ccf683963f9e79bad2b246.js"&gt;&lt;/script&gt;
&lt;script src="https://gist.github.com/uzimihsr/266c50a5ec15a6b8d325cda8be4e9053.js"&gt;&lt;/script&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ tree .
.
├── docker-compose.yaml
├── https.conf
├── server-cert.pem
└── server-private-key.pem

0 directories, 4 files

$ docker compose up -d

$ docker compose ps
NAME COMMAND SERVICE STATUS PORTS
hogehoge.uzimihsr.com &amp;#34;/docker-entrypoint.…&amp;#34; nginx running 80/tcp, 0.0.0.0:443-&amp;gt;443/tcp

$ curl -I https://hogehoge.uzimihsr.com --cacert ./server-cert.pem --resolve &amp;#34;hogehoge.uzimihsr.com:443:127.0.0.1&amp;#34;
HTTP/1.1 200 OK
...
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="create-an-application-that-sends-http-requests-in-go"&gt;Create an application that sends HTTP requests in Go
&lt;/h3&gt;&lt;p&gt;Next, create a simple HTTP status checker in Go.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/d2d4625c92c0550d3720f106344c4450.js"&gt;&lt;/script&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ go run main.go https://example.com
2022/09/28 23:45:32 target: https://example.com, insecure: false
2022/09/28 23:45:33 status: 200 OK
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Build and run this application with Docker.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/fae361191dccfed061e023271572281c.js"&gt;&lt;/script&gt;
&lt;script src="https://gist.github.com/uzimihsr/07dcc3e1539ac646e9dccd61b2d0af5c.js"&gt;&lt;/script&gt;
&lt;p&gt;Oops! The &lt;code&gt;http-status-checker&lt;/code&gt; container failed due to the certificate error.😭&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ tree .
.
├── Dockerfile
├── docker-compose.yaml
├── go.mod
├── https.conf
├── main.go
├── server-cert.pem
└── server-private-key.pem

0 directories, 7 files

$ cat go.mod
module http-status-checker

go 1.18

$ docker compose up -d

$ docker compose ps
NAME COMMAND SERVICE STATUS PORTS
hogehoge.uzimihsr.com &amp;#34;/docker-entrypoint.…&amp;#34; nginx running 80/tcp, 0.0.0.0:443-&amp;gt;443/tcp
http-status-checker &amp;#34;./app https://hogeh…&amp;#34; http-status-checker exited (1)

$ docker compose logs http-status-checker
http-status-checker | 2022/09/28 12:17:41 target: https://hogehoge.uzimihsr.com/, insecure: false
http-status-checker | 2022/09/28 12:17:41 [ERROR] HTTP(S) request failed: Get &amp;#34;https://hogehoge.uzimihsr.com/&amp;#34;: x509: certificate signed by unknown authority
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="trust-the-certificate-in-a-scratch-image"&gt;Trust the certificate in a scratch image
&lt;/h3&gt;&lt;p&gt;To avoid the certificate error, the self-signed certificate should be trusted in a scratch image.&lt;br&gt;
(Of course, it is possible to set &lt;a class="link" href="https://pkg.go.dev/crypto/tls#Config" target="_blank" rel="noopener"
 &gt;tls.Config.InsecureSkipVerify&lt;/a&gt; as a workaround, but I have tried to trust the self-signed certificate.)&lt;/p&gt;
&lt;p&gt;Since the &lt;a class="link" href="https://hub.docker.com/_/golang" target="_blank" rel="noopener"
 &gt;golang&lt;/a&gt; image is Debian-based, the list of CA certificates can be updated with the &lt;a class="link" href="https://manpages.ubuntu.com/manpages/xenial/man8/update-ca-certificates.8.html" target="_blank" rel="noopener"
 &gt;update-ca-certificates&lt;/a&gt; command.&lt;/p&gt;
&lt;p&gt;The Dockerfile is rewrited as follows.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/4ed140a8b9a15a19b0537460e9b857c8.js"&gt;&lt;/script&gt;
&lt;p&gt;The following operations are added: copy the certificate we want to trust with &lt;code&gt;.crt&lt;/code&gt; extension and run the update-ca-certificates command.&lt;br&gt;
This allows &lt;code&gt;/etc/ssl/certs/ca-certificates.crt&lt;/code&gt; in the build stage to trust the specified certificate.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-dockerfile" data-lang="dockerfile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; server-cert.pem /usr/local/share/ca-certificates/server-cert.crt&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; update-ca-certificates&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Finally, rebuild and restart the container.&lt;br&gt;
This time it worked fine with no certificate errors.🎉&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ docker compose up -d --remove-orphans --build

$ docker compose ps
NAME COMMAND SERVICE STATUS PORTS
hogehoge.uzimihsr.com &amp;#34;/docker-entrypoint.…&amp;#34; nginx running 80/tcp, 0.0.0.0:443-&amp;gt;443/tcp
http-status-checker &amp;#34;./app https://hogeh…&amp;#34; http-status-checker exited (0)

$ docker compose logs http-status-checker
http-status-checker | 2022/09/28 13:44:43 target: https://hogehoge.uzimihsr.com/, insecure: false
http-status-checker | 2022/09/28 13:44:43 status: 200 OK
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>scratchイメージ上のGoで任意の証明書を信頼する</title><link>https://blog.uzimihsr.com/post/2022-09-29-golang-scratch-trust-cert-ja/</link><pubDate>Thu, 29 Sep 2022 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2022-09-29-golang-scratch-trust-cert-ja/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2022-09-29-golang-scratch-trust-cert-ja/sotochan.jpeg" alt="Featured image of post scratchイメージ上のGoで任意の証明書を信頼する" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;マルチステージビルドで実行用のバイナリをscratchに載せる場合、&lt;br&gt;
ビルドと同じタイミングで信頼したい証明書を用意して、&lt;br&gt;
CA証明書のリストを更新したものをアプリと一緒にコピーすればよさそう。&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/4ed140a8b9a15a19b0537460e9b857c8.js"&gt;&lt;/script&gt;
&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Docker version 20.10.17, build 100c701&lt;/li&gt;
&lt;li&gt;go version go1.18.1 darwin/arm64&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/layers/library/nginx/1.23.1/images/sha256-79c77eb7ca32f9a117ef91bc6ac486014e0d0e75f2f06683ba24dc298f9f4dd4?context=explore" target="_blank" rel="noopener"
 &gt;nginx:1.23.1&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;h3 id="オレオレ証明書を作成してnginxをhttpsで建てる"&gt;オレオレ証明書を作成してnginxをHTTPSで建てる
&lt;/h3&gt;&lt;p&gt;まずは検証用にオレオレ証明書を作成する。&lt;br&gt;
&lt;code&gt;openssl&lt;/code&gt;が使えるならどんなやり方でもいいが、自分は&lt;code&gt;Docker&lt;/code&gt;上で作ってホストに持ってくるのがすき。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ホストOSのボリュームをマウントする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run --rm -it -v&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt;&lt;span class="s2"&gt;:/workdir&amp;#34;&lt;/span&gt; -w&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/workdir&amp;#34;&lt;/span&gt; --entrypoint&lt;span class="o"&gt;=&lt;/span&gt;/bin/bash nginx:1.23.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;root@e08bb1ebe3da:/workdir# openssl version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;OpenSSL 1.1.1n &lt;span class="m"&gt;15&lt;/span&gt; Mar &lt;span class="m"&gt;2022&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 秘密鍵の作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;root@e08bb1ebe3da:/workdir# openssl genpkey -algorithm RSA -out server-private-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...................+++++
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;......................................................................................................+++++
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# オレオレ証明書の作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;root@e08bb1ebe3da:/workdir# openssl req -x509 -key server-private-key.pem -out server-cert.pem -addext &lt;span class="s1"&gt;&amp;#39;subjectAltName = DNS:hogehoge.uzimihsr.com&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;You are about to be asked to enter information that will be incorporated
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;into your certificate request.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;What you are about to enter is what is called a Distinguished Name or a DN.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;There are quite a few fields but you can leave some blank
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;For some fields there will be a default value,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;If you enter &lt;span class="s1"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;, the field will be left blank.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-----
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Country Name &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; letter code&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;AU&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;State or Province Name &lt;span class="o"&gt;(&lt;/span&gt;full name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Some-State&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Locality Name &lt;span class="o"&gt;(&lt;/span&gt;eg, city&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Organization Name &lt;span class="o"&gt;(&lt;/span&gt;eg, company&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Internet Widgits Pty Ltd&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Organizational Unit Name &lt;span class="o"&gt;(&lt;/span&gt;eg, section&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Common Name &lt;span class="o"&gt;(&lt;/span&gt;e.g. server FQDN or YOUR name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:hogehoge.uzimihsr.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Email Address &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;root@e08bb1ebe3da:/workdir#
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ホスト上に鍵と証明書が置かれている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;server-cert.pem		server-private-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;作成した秘密鍵とオレオレ証明書を使ってnginxをHTTPSで立ててみる。&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/8a34bfd167ccf683963f9e79bad2b246.js"&gt;&lt;/script&gt;
&lt;script src="https://gist.github.com/uzimihsr/266c50a5ec15a6b8d325cda8be4e9053.js"&gt;&lt;/script&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# ディレクトリの状態
$ tree .
.
├── docker-compose.yaml
├── https.conf
├── server-cert.pem
└── server-private-key.pem

0 directories, 4 files

# nginxを起動
$ docker compose up -d

$ docker compose ps
NAME COMMAND SERVICE STATUS PORTS
hogehoge.uzimihsr.com &amp;#34;/docker-entrypoint.…&amp;#34; nginx running 80/tcp, 0.0.0.0:443-&amp;gt;443/tcp

# CA証明書を指定して叩くとHTTPSで通信できている
$ curl -I https://hogehoge.uzimihsr.com --cacert ./server-cert.pem --resolve &amp;#34;hogehoge.uzimihsr.com:443:127.0.0.1&amp;#34;
HTTP/1.1 200 OK
...
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="httpリクエストを送るgoアプリの作成"&gt;HTTPリクエストを送るGoアプリの作成
&lt;/h3&gt;&lt;p&gt;先ほど立てたnginx(HTTPS)に対してHTTPリクエストを送る簡単なアプリを実装する。&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/d2d4625c92c0550d3720f106344c4450.js"&gt;&lt;/script&gt;
&lt;p&gt;内容としては引数で指定されたURLに対してHTTP GETしてそのステータスコードを表示する(200系以外は異常終了する)だけのもの。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ go run main.go https://example.com
2022/09/28 23:45:32 target: https://example.com, insecure: false
2022/09/28 23:45:33 status: 200 OK
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;これをマルチステージビルドでscratchに乗せて動かしてみる。&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/fae361191dccfed061e023271572281c.js"&gt;&lt;/script&gt;
&lt;script src="https://gist.github.com/uzimihsr/07dcc3e1539ac646e9dccd61b2d0af5c.js"&gt;&lt;/script&gt;
&lt;p&gt;起動したコンテナを確認すると、オレオレ証明書を信頼できずにエラーとなっている。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ tree .
.
├── Dockerfile
├── docker-compose.yaml
├── go.mod
├── https.conf
├── main.go
├── server-cert.pem
└── server-private-key.pem

0 directories, 7 files

$ cat go.mod
module http-status-checker

go 1.18

$ docker compose up -d

$ docker compose ps
NAME COMMAND SERVICE STATUS PORTS
hogehoge.uzimihsr.com &amp;#34;/docker-entrypoint.…&amp;#34; nginx running 80/tcp, 0.0.0.0:443-&amp;gt;443/tcp
http-status-checker &amp;#34;./app https://hogeh…&amp;#34; http-status-checker exited (1)

$ docker compose logs http-status-checker
http-status-checker | 2022/09/28 12:17:41 target: https://hogehoge.uzimihsr.com/, insecure: false
http-status-checker | 2022/09/28 12:17:41 [ERROR] HTTP(S) request failed: Get &amp;#34;https://hogehoge.uzimihsr.com/&amp;#34;: x509: certificate signed by unknown authority
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="オレオレ証明書を信頼する"&gt;オレオレ証明書を信頼する
&lt;/h3&gt;&lt;p&gt;こんなとき、実装にもあるように&lt;a class="link" href="https://pkg.go.dev/crypto/tls#Config" target="_blank" rel="noopener"
 &gt;tls.Config.InsecureSkipVerify&lt;/a&gt;を指定することで証明書エラーを回避することは可能だが、&lt;br&gt;
どうしてもオレオレ証明書を信頼する設定で動かしたくなった。&lt;/p&gt;
&lt;p&gt;どうしたものかと悩んだが、単純に&lt;a class="link" href="https://manpages.ubuntu.com/manpages/xenial/man8/update-ca-certificates.8.html" target="_blank" rel="noopener"
 &gt;update-ca-certificates&lt;/a&gt;で信頼した証明書をコピーする方法に落ち着いた。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Dockerfile&lt;/code&gt;の設定を次のように書き換える。&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/4ed140a8b9a15a19b0537460e9b857c8.js"&gt;&lt;/script&gt;
&lt;p&gt;変更点は次の部分。&lt;br&gt;
信頼したい証明書を&lt;code&gt;/usr/local/share/ca-certificates/&lt;/code&gt;配下に&lt;code&gt;.crt&lt;/code&gt;という名前でコピーして、&lt;code&gt;update-ca-certificates&lt;/code&gt;を実行している。&lt;br&gt;
これにより、ビルド用コンテナ内の&lt;code&gt;/etc/ssl/certs/ca-certificates.crt&lt;/code&gt;が更新されて対象の証明書を信頼できるようになる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-dockerfile" data-lang="dockerfile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; server-cert.pem /usr/local/share/ca-certificates/server-cert.crt&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; update-ca-certificates&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;再度実行してみると、今度はオレオレ証明書が信頼できていてエラーが発生しなくなった。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ docker compose up -d --remove-orphans --build

$ docker compose ps
NAME COMMAND SERVICE STATUS PORTS
hogehoge.uzimihsr.com &amp;#34;/docker-entrypoint.…&amp;#34; nginx running 80/tcp, 0.0.0.0:443-&amp;gt;443/tcp
http-status-checker &amp;#34;./app https://hogeh…&amp;#34; http-status-checker exited (0)

$ docker compose logs http-status-checker
http-status-checker | 2022/09/28 13:44:43 target: https://hogehoge.uzimihsr.com/, insecure: false
http-status-checker | 2022/09/28 13:44:43 status: 200 OK
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;今回は&lt;a class="link" href="https://hub.docker.com/_/golang" target="_blank" rel="noopener"
 &gt;golang&lt;/a&gt;のimageがdebian系だったのでこの手順で試したが、&lt;br&gt;
Red Hat系なら同様に&lt;code&gt;.crt&lt;/code&gt;ファイルを&lt;code&gt;/usr/share/pki/ca-trust-source/anchors/&lt;/code&gt;配下にコピーして、&lt;br&gt;
&lt;a class="link" href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/security_hardening/using-shared-system-certificates_security-hardening#adding-new-certificates_using-shared-system-certificates" target="_blank" rel="noopener"
 &gt;update-ca-trust&lt;/a&gt;すると&lt;code&gt;/etc/pki/tls/certs/ca-bundle.crt&lt;/code&gt;が更新されたはず。(試してない)&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;久しぶりにGo+scratchでimageを作ったときに詰まったのでおさらいした。&lt;br&gt;
こんなことしてる暇があったら&lt;a class="link" href="https://github.com/GoogleContainerTools/distroless" target="_blank" rel="noopener"
 &gt;distroless&lt;/a&gt;に移行しろと言われればそれはそう&amp;hellip;&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="自分のしっぽを踏むねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-09-29-golang-scratch-trust-cert-ja/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2022-09-29-golang-scratch-trust-cert-ja/sotochan_hu_666a0104ff65ab99.jpeg 800w, https://blog.uzimihsr.com/post/2022-09-29-golang-scratch-trust-cert-ja/sotochan_hu_7249bff623ee28ed.jpeg 1600w, https://blog.uzimihsr.com/post/2022-09-29-golang-scratch-trust-cert-ja/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>8月のそとちゃん(2022)</title><link>https://blog.uzimihsr.com/post/2022-09-07-sotochan/</link><pubDate>Wed, 07 Sep 2022 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2022-09-07-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan.jpeg" alt="Featured image of post 8月のそとちゃん(2022)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e5%bc%95%e8%b6%8a%e3%81%97" &gt;引越し&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%b2%e3%81%aa%e3%81%9f%e3%81%bc%e3%81%a3%e3%81%93" &gt;ひなたぼっこ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e8%a2%8b" &gt;袋&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="引越し"&gt;引越し
&lt;/h3&gt;&lt;p&gt;色々あってまた家を引っ越すことになった。&lt;/p&gt;
&lt;p&gt;今回も荷造りを&lt;del&gt;邪魔する&lt;/del&gt;手伝うそとちゃん。&lt;/p&gt;
&lt;p&gt;布団袋(かなりでかい)に興味津々。&lt;/p&gt;
&lt;p&gt;&lt;img alt="入念な調査" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan04_hu_6ab909b38e3dece2.jpeg 800w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan04_hu_12c112444890dc37.jpeg 1600w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="一度入ると出てこない" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan01_hu_dba2bb9a7519114a.jpeg 800w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan01_hu_b4a9c3581ad6b637.jpeg 1600w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;段ボールの調査も抜かりない。&lt;/p&gt;
&lt;p&gt;&lt;img alt="組み立てる前から調べる気合の入りよう" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan05_hu_3805360a8130dcb1.jpeg 800w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan05_hu_ea71d8b70a424dc4.jpeg 1600w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan05.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="断面の強度まで調べるんですか?" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan06_hu_cf9fe8c032765ea8.jpeg 800w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan06_hu_2bd6e280f89c4559.jpeg 1600w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan06.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="完成後は内部をチェック" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan02_hu_9feee9001063cb17.jpeg 800w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan02_hu_b47e63666d1a1471.jpeg 1600w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="上に乗って強度を調べる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan03_hu_9c6170ba57eb2e15.jpeg 800w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan03_hu_31a8972f55fdbe12.jpeg 1600w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan03.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;新居到着後は早速探検。&lt;br&gt;
そとちゃんは新しい場所が大好きなので速攻で慣れてくれて助かった。&lt;br&gt;
&lt;del&gt;というかむしろ大興奮で暴れまわり荷解きをめちゃくちゃ邪魔した&lt;/del&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="遊び疲れた" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan07_hu_2ee31277f0a4807a.jpeg 800w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan07_hu_ee1cf5f265990743.jpeg 1600w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan07.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="ひなたぼっこ"&gt;ひなたぼっこ
&lt;/h3&gt;&lt;p&gt;今回引越しを決断した一番の理由は前の家の日当たりの悪さだった。&lt;/p&gt;
&lt;p&gt;全く日が入らないわけではないが日照時間が極端に短いので、&lt;br&gt;
前の家では抱っこ状態で外に出して陽に当てていた。&lt;/p&gt;
&lt;p&gt;それだと昼に毎回抱っこして外まで行くのが面倒だったのと、&lt;br&gt;
やっぱり自分のタイミングで好きなようにひなたぼっこさせてあげたいと思い引越しを決断。&lt;br&gt;
(そとちゃん的に抱っこは好きでも嫌いでもなさそうだが)&lt;/p&gt;
&lt;p&gt;新居の日当たりはそこそこ良く、&lt;br&gt;
昼間は部屋の中にしっかり陽が入ってくる。&lt;/p&gt;
&lt;p&gt;&lt;img alt="直射日光を浴びる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan08_hu_7cc48d71efa5db85.jpeg 800w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan08_hu_3dc0c848b1c4dc7b.jpeg 1600w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan08.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&amp;hellip;のだが、引越して数日間はそとちゃんがなかなか自分から陽に当たらず&amp;hellip;&lt;br&gt;
この2年弱の間抱っこされてひなたぼっこするのが当たり前になっていて、&lt;br&gt;
自分でひなたぼっこすることを忘れてしまっていたのかも？&lt;/p&gt;
&lt;p&gt;&lt;img alt="インドア派" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan09.jpeg" srcset="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan09_hu_df54c154931527d7.jpeg 800w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan09_hu_a9e6711bacbee317.jpeg 1600w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan09.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;せっかく引越したのにこれじゃあんまりなので、&lt;br&gt;
陽が入るたびにそとちゃんを窓際に運ぶのを数日繰り返したところ(低頻度だが)自分でもひなたぼっこしてくれるようになった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="最初はなぜかめんどくさそう" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan10.jpeg" srcset="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan10_hu_35abf6482f23da57.jpeg 800w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan10_hu_eff898111168f25b.jpeg 1600w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan10.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="2年間置物状態だった窓ハンモックが有効活用される" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan11.jpeg" srcset="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan11_hu_9b5f7891d21b23c6.jpeg 800w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan11_hu_53cc8aefe7157379.jpeg 1600w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan11.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="元気にバリバリ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan12.jpeg" srcset="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan12_hu_c20bbcab8672d2f7.jpeg 800w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan12_hu_50bb4efb0c05f5e4.jpeg 1600w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan12.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;とはいえ陽に当たり過ぎても良くないと思うので、適度に楽しんでもらいたい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="太極拳?" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan13.jpeg" srcset="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan13_hu_917021b2f37d0ff2.jpeg 800w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan13_hu_9ec7c248491ca66a.jpeg 1600w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan13.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="袋"&gt;袋
&lt;/h3&gt;&lt;p&gt;やっぱり袋が好き。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;袋 &lt;a href="https://t.co/ArcBAlCQ8W"&gt;pic.twitter.com/ArcBAlCQ8W&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1561539864050700288?ref_src=twsrc%5Etfw"&gt;August 22, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;最近は特にニトリの大きいサイズのレジ袋に入って暴れるのが好き。&lt;/p&gt;
&lt;p&gt;&lt;img alt="5円で買える最高のおもちゃ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan14.jpeg" srcset="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan14_hu_476440314407a3f6.jpeg 800w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan14_hu_c1365af78a847334.jpeg 1600w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan14.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;袋の中で動く→カサカサ音がする→獲物と勘違いして追っかけ回す→カサカサ音がする をひたすら繰り返す。&lt;/p&gt;
&lt;p&gt;&lt;img alt="紙袋(だったもの)を入れるとさらにカサカサ感UPしていい感じ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan15.jpeg" srcset="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan15_hu_b97ffedecd99e8b2.jpeg 800w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan15_hu_8a9139feaeed0c7c.jpeg 1600w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan15.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;あとは王道(そとちゃん基準)だけど袋の中に投げ入れたおもちゃをひたすら外からしばくのも楽しいらしい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="しばく" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan16.jpeg" srcset="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan16_hu_47f10dd472bf7fc0.jpeg 800w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan16_hu_ef68c7a3d83c593c.jpeg 1600w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan16.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;引越し後にニトリで買うものがちょいちょいあったので、さらに新しい袋が補給された。&lt;br&gt;
これで当分は耐えられそう。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ニトリ最高!" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan17.jpeg" srcset="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan17_hu_6aa3c0eb8ffcff3.jpeg 800w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan17_hu_66ca940b4184528d.jpeg 1600w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan17.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;2度目の引越しを終えて、やっぱりそとちゃんは環境の変化に強いなと感じた。&lt;br&gt;
本当はストレスになっているのかもしれないが、&lt;br&gt;
病院に行った時の様子とかを見ると肝が据わっているというか単純に普段と違う場所に行くのが好きなんだと思う。&lt;/p&gt;
&lt;p&gt;何はともあれ無事に引っ越しできてよかった。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="陽に当たりながら得意のポーズを決めるそとちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan_hu_8df55c7b9aeb3410.jpeg 800w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan_hu_fedd9ef5b603311.jpeg 1600w, https://blog.uzimihsr.com/post/2022-09-07-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>7月のそとちゃん(2022)</title><link>https://blog.uzimihsr.com/post/2022-08-06-sotochan/</link><pubDate>Sat, 06 Aug 2022 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2022-08-06-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan.jpeg" alt="Featured image of post 7月のそとちゃん(2022)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%94%e3%82%8d%e3%81%94%e3%82%8d" &gt;ごろごろ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%8a%e9%a2%a8%e5%91%82" &gt;お風呂&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%ab%e3%83%aa%e3%82%ab%e3%83%aa" &gt;カリカリ&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="ごろごろ"&gt;ごろごろ
&lt;/h3&gt;&lt;p&gt;いつものことなんだけどそとちゃんはよくごろごろしている。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;転がってる &lt;a href="https://t.co/PFpU1soXb8"&gt;pic.twitter.com/PFpU1soXb8&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1543953179788079104?ref_src=twsrc%5Etfw"&gt;July 4, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;遊び疲れてごろごろするときもあるけど、&lt;br&gt;
なにもなくただ床に落ちていることが多い。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;落ちてる &lt;a href="https://t.co/vTzBUMGNGY"&gt;pic.twitter.com/vTzBUMGNGY&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1546664235631259648?ref_src=twsrc%5Etfw"&gt;July 12, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;あとはなんとなく左側を下にして落ちてる傾向がある気がする。&lt;/p&gt;
&lt;p&gt;&lt;img alt="これは遊び疲れているやつ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan01_hu_d1972681446c8da9.jpeg 800w, https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan01_hu_1f8cdf84417072a9.jpeg 1600w, https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;落ちてる時におなかを突っつくとよく転がって面白い。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;踊ってる &lt;a href="https://t.co/GiUotnoYNF"&gt;pic.twitter.com/GiUotnoYNF&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1552802080393658368?ref_src=twsrc%5Etfw"&gt;July 28, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;たまに椅子の下とかドアの前で転がってて危ないのでやめてほしい。😅&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;椅子を動かせなくする技 &lt;a href="https://t.co/sBhW26qLrT"&gt;pic.twitter.com/sBhW26qLrT&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1549914707687272449?ref_src=twsrc%5Etfw"&gt;July 21, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;h3 id="お風呂"&gt;お風呂
&lt;/h3&gt;&lt;p&gt;流石に抜け毛が多くなってきたので、約1年ぶりのお風呂に入ってもらった。🛁&lt;/p&gt;
&lt;p&gt;&lt;img alt="ここまでは遊びにきたつもりだった" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan02_hu_db85a35f473d1f49.jpeg 800w, https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan02_hu_c45d5e6a663ba8a0.jpeg 1600w, https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2021-05-12-sotochan/#%e3%82%b7%e3%83%a3%e3%83%b3%e3%83%97%e3%83%bc" target="_blank" rel="noopener"
 &gt;前回&lt;/a&gt;はシャワーだけだったけど、&lt;br&gt;
今回はしっかり洗って抜け毛を流すためにお風呂(バスタブ)に挑戦。&lt;/p&gt;
&lt;p&gt;シャワーは耐えられるそとちゃんでもバスタブにはかなりビビっていた。&lt;br&gt;
顔の近くにお湯があるのが怖いみたいで、若干パニックになっていてかわいそうだった。&lt;br&gt;
(が、シャンプーのためにちゃんと濡らした😂)&lt;/p&gt;
&lt;p&gt;&lt;img alt="しっかり濡らした" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="2160" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan03.JPG" srcset="https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan03_hu_85b46bd118742f85.JPG 800w, https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan03_hu_c09380c7a517b750.JPG 1600w, https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan03_hu_5e4f4bc0fb64b86.JPG 2400w, https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan03.JPG 3840w" width="3840"&gt;&lt;/p&gt;
&lt;p&gt;脱走を繰り返しながらもバスタブでしっかり毛を濡らして、ようやくシャンプー。&lt;br&gt;
みゃおみゃお文句言いながらもなんとか耐えてくれた。えらい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="瞳孔ガン開き" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="2160" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan04.JPG" srcset="https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan04_hu_7367fd0734149583.JPG 800w, https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan04_hu_4e423fce55ef721c.JPG 1600w, https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan04_hu_9f83179995bccc58.JPG 2400w, https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan04.JPG 3840w" width="3840"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="シャワーで流した" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="2160" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan05.JPG" srcset="https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan05_hu_85acfc7f9da39812.JPG 800w, https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan05_hu_fd3f5e312a6f294e.JPG 1600w, https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan05_hu_e0cb784b67b2c055.JPG 2400w, https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan05.JPG 3840w" width="3840"&gt;&lt;/p&gt;
&lt;p&gt;最後にもう1回お風呂に浸かってしっかり抜け毛を流してもらった。&lt;br&gt;
そとちゃんの「もう終わりだと思ってたのに&amp;hellip;なんでや&amp;hellip;」みたいな顔がかわいそうだけど面白くてちょっと笑ってしまった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="見たことないくらい顔が逆三角" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="2160" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan06.JPG" srcset="https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan06_hu_208e39c1a295e52a.JPG 800w, https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan06_hu_c70cf9eda50ec87c.JPG 1600w, https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan06_hu_87c2572efab17992.JPG 2400w, https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan06.JPG 3840w" width="3840"&gt;&lt;/p&gt;
&lt;p&gt;あとは乾かして今度こそお風呂は終わり。&lt;br&gt;
ここまでされても噛んだり引っ掻いたり「シャーッ」とか言わないのでそとちゃんは本当に優しい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="この世の全てを憎んでいる" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="2160" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan07.JPG" srcset="https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan07_hu_a75d5eec2a6382f1.JPG 800w, https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan07_hu_62dcdc0143b3a2ca.JPG 1600w, https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan07_hu_61c72aeffde74425.JPG 2400w, https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan07.JPG 3840w" width="3840"&gt;&lt;/p&gt;
&lt;p&gt;大変な思いをしてかわいそうだったけど、&lt;br&gt;
毛はフワッフワになったし毛玉も吐かなくなったので良かった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="外気浴?" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="1116" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan08.JPG" srcset="https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan08_hu_6988477c77af3da6.JPG 800w, https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan08_hu_c7c3899eccbecdd6.JPG 1600w, https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan08.JPG 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="激おこちゅーる摂取" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="1116" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan09.JPG" srcset="https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan09_hu_1e0eaba4bbc56e58.JPG 800w, https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan09_hu_d33aec4f2fd8c40c.JPG 1600w, https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan09.JPG 1984w" width="1984"&gt;&lt;/p&gt;
&lt;div class="video-wrapper"&gt;
 &lt;iframe loading="lazy" 
 src="https://www.youtube.com/embed/CKlk8awp0Qs" 
 allowfullscreen 
 title="YouTube Video"
 &gt;
 &lt;/iframe&gt;
&lt;/div&gt;

&lt;h3 id="カリカリ"&gt;カリカリ
&lt;/h3&gt;&lt;p&gt;そとちゃんがカリカリをちょっとだけ食べるようになった。&lt;/p&gt;
&lt;p&gt;(ちょっとかわいそうだけど)猫缶をあげるときのトッピングとか夜のおやつを少なめにしたら、&lt;br&gt;
流石にお腹が空いたみたいで次の日から朝と昼のカリカリを渋々食べてくれた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="えらい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan10.jpeg" srcset="https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan10_hu_3503678cf15cb99b.jpeg 800w, https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan10_hu_b5d2ed1ab85a8e2d.jpeg 1600w, https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan10.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;まだ完食とまではいかないけど、全然食べなかった時期に比べるとだいぶ進歩した。&lt;br&gt;
完食したらもっとえらい&amp;hellip;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;7月のそとちゃんは水責めに遭ったりおやつを減らされたりで散々だった。&lt;/p&gt;
&lt;p&gt;それでいじけることもあるけど、おしりを叩いたり撫でたりすればすぐごきげんになってしまうので助かる。&lt;br&gt;
単純でかわいい。えらい。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="廊下に落ちてるねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan_hu_615b1256cd6c2612.jpeg 800w, https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan_hu_cd8572b3eab5b821.jpeg 1600w, https://blog.uzimihsr.com/post/2022-08-06-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>6月のそとちゃん(2022)</title><link>https://blog.uzimihsr.com/post/2022-07-22-sotochan/</link><pubDate>Fri, 22 Jul 2022 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2022-07-22-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2022-07-22-sotochan/sotochan.jpeg" alt="Featured image of post 6月のそとちゃん(2022)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%be%e3%81%9f%e3%81%9f%e3%81%b3" &gt;またたび&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%ad%e3%83%a3%e3%83%aa%e3%83%bc%e3%82%b1%e3%83%bc%e3%82%b9" &gt;キャリーケース&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e5%90%90%e3%81%8f" &gt;吐く&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%ab%e3%83%aa%e3%82%ab%e3%83%aa%e9%a3%9f%e3%81%b9%e3%81%aa%e3%81%84" &gt;カリカリ食べない&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="またたび"&gt;またたび
&lt;/h3&gt;&lt;p&gt;新しいおもちゃを買った。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://www.ai-pro.co.jp/%E8%A4%87%E8%A3%BD-%E7%8C%AB%E8%8F%AF" target="_blank" rel="noopener"
 &gt;CAT CHAP ペンタゴン&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="またたびボール" class="gallery-image" data-flex-basis="313px" data-flex-grow="130" height="1301" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-07-22-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2022-07-22-sotochan/sotochan01_hu_a516cd592541b336.jpeg 800w, https://blog.uzimihsr.com/post/2022-07-22-sotochan/sotochan01_hu_5fd58db59ab719ac.jpeg 1600w, https://blog.uzimihsr.com/post/2022-07-22-sotochan/sotochan01.jpeg 1701w" width="1701"&gt;&lt;/p&gt;
&lt;p&gt;そとちゃんは結構気に入ってくれたみたいでゴロゴロ転がして遊んでくれた。&lt;/p&gt;
&lt;p&gt;せっかくなので動画を撮ってみた。&lt;/p&gt;
&lt;div class="video-wrapper"&gt;
 &lt;iframe loading="lazy" 
 src="https://www.youtube.com/embed/06ctYqZ0xY0" 
 allowfullscreen 
 title="YouTube Video"
 &gt;
 &lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;以前から俺がヤベーと思っていたそとちゃんのまたたびのキメ方をようやく映像に残すことができた。🌿&lt;/p&gt;
&lt;p&gt;動画にも映ってるが実は転がして遊ぶのは本当に最初だけで、&lt;br&gt;
一度動きを止めるコツを掴んだらあとは押さえてひたすら舐めてヤバい成分を摂取し続ける。&lt;/p&gt;
&lt;p&gt;またたびジャンキーのそとちゃんは耐性がついてしまっているようで、&lt;br&gt;
10分程度キメ続けてようやくトリップ。🥴&lt;/p&gt;
&lt;p&gt;最後は謎のうねうね踊り(かわいい)を見せてから数十秒で寝落ちしてしまった。&lt;/p&gt;
&lt;p&gt;満足してくれたようでよかった。&lt;/p&gt;
&lt;h3 id="キャリーケース"&gt;キャリーケース
&lt;/h3&gt;&lt;p&gt;ちょっと前まで地震が多かったのもあって、&lt;br&gt;
万が一に備えて大きめのキャリーケースを買ってみた。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://www.richell.co.jp/shop/pet/detail/059930" target="_blank" rel="noopener"
 &gt;キャンピングキャリー 折りたたみ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;梱包を開ける前からそとちゃんは興味津々で、&lt;br&gt;
廊下に置いたらすぐに入ってくれた。&lt;/p&gt;
&lt;div class="video-wrapper"&gt;
 &lt;iframe loading="lazy" 
 src="https://www.youtube.com/embed/Vb33C7e5T-4" 
 allowfullscreen 
 title="YouTube Video"
 &gt;
 &lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;実物を見ずに通販で買ったので大きさが不安だったが、&lt;br&gt;
4kgくらいのそとちゃんには十分だった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="そこそこでかい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-07-22-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2022-07-22-sotochan/sotochan02_hu_6afe0f00afcc88c7.jpeg 800w, https://blog.uzimihsr.com/post/2022-07-22-sotochan/sotochan02_hu_c6c18436867652c7.jpeg 1600w, https://blog.uzimihsr.com/post/2022-07-22-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;両サイドの扉が取り外しできたのでいい感じのお部屋になり、&lt;br&gt;
居間が暑い日なんかはよくここで涼んでいる。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;つかれた &lt;a href="https://t.co/qWwPk5p4F3"&gt;pic.twitter.com/qWwPk5p4F3&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1532889129788538881?ref_src=twsrc%5Etfw"&gt;June 4, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;ちなみにダンボールトンネル(ぼろぼろ)と組み合わせて一気に走り抜けるのが流行っている。&lt;/p&gt;
&lt;p&gt;&lt;img alt="この後突進してくる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-07-22-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2022-07-22-sotochan/sotochan03_hu_2108184686db6d77.jpeg 800w, https://blog.uzimihsr.com/post/2022-07-22-sotochan/sotochan03_hu_aecd81e2d5767ad9.jpeg 1600w, https://blog.uzimihsr.com/post/2022-07-22-sotochan/sotochan03.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h3 id="吐く"&gt;吐く
&lt;/h3&gt;&lt;p&gt;6月はなんかめっちゃ吐いた。&lt;/p&gt;
&lt;p&gt;&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;吐いた &lt;a href="https://t.co/KUyEWnres8"&gt;pic.twitter.com/KUyEWnres8&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1535123425886601216?ref_src=twsrc%5Etfw"&gt;June 10, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;吐いた &lt;a href="https://t.co/UyW8EwZjzL"&gt;pic.twitter.com/UyW8EwZjzL&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1538345578983264256?ref_src=twsrc%5Etfw"&gt;June 19, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;

&lt;/p&gt;
&lt;p&gt;今までは2,3ヶ月に1回吐くか吐かないかだったのに、&lt;br&gt;
6月は結構なペースで(3回くらい)吐いてしまった。&lt;/p&gt;
&lt;p&gt;今月はおやつのにぼしをなぜか焦って飲み込んですぐにオエって吐き出したのと、&lt;br&gt;
ブラッシングの後にめちゃ毛繕いして毛玉を吐いたのが数回。&lt;/p&gt;
&lt;p&gt;前者はゆっくり食べれば防げるので今後あげるときに気をつけたい。&lt;br&gt;
毛玉の方はブラッシングを頑張って抜け毛を減らすしかないが、&lt;br&gt;
そとちゃんはブラシ嫌い(週に1回30分が限界)な上にブラシするとめちゃめちゃ毛繕いするのでどうしようもない&amp;hellip;&lt;/p&gt;
&lt;h3 id="カリカリ食べない"&gt;カリカリ食べない
&lt;/h3&gt;&lt;p&gt;そとちゃんがまたカリカリを残すようになってしまった。😭&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;この状況で「わたしはごはんをもらえていません」みたいな顔しないでほしい&lt;br&gt;&lt;br&gt;(このあと猫缶をあげました) &lt;a href="https://t.co/foZzpmEMeJ"&gt;pic.twitter.com/foZzpmEMeJ&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1538836603359346688?ref_src=twsrc%5Etfw"&gt;June 20, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;おそらく湿気が高い日に食べたカリカリが若干傷んでいて、&lt;br&gt;
それが美味しくなかったからそれ以降全然食べなくなってしまったのだと思う。&lt;/p&gt;
&lt;p&gt;自動給餌器の中に乾燥剤を取り付けて湿気対策はしたものの、&lt;br&gt;
そこから出たカリカリをそとちゃんが食べずに放置するとそれがまた湿気ってさらに食べない&amp;hellip;という負のループに😭😭😭&lt;/p&gt;
&lt;p&gt;特に湿気がひどい日には自動給餌器を使わずに手でカリカリをあげるんだけど、&lt;br&gt;
それでも一度不味いと判断したものはなかなか食べてくれない。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2020-08-03-sotochan/" target="_blank" rel="noopener"
 &gt;過去にカリカリを食べなかった時期&lt;/a&gt;とは違って、&lt;br&gt;
俺が部屋にいない時ですら食べないので本当に困ってしまった。&lt;/p&gt;
&lt;p&gt;食欲出すためにおやつをトッピングするとそこだけ舐め取ってしまうし、&lt;br&gt;
万策尽きた&amp;hellip;&lt;br&gt;
どうすりゃいいんだ&amp;hellip;😭&lt;/p&gt;
&lt;p&gt;&lt;img alt="ちなみにウェットフードはモリモリ食べる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-07-22-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2022-07-22-sotochan/sotochan04_hu_fda42245e9ac4adc.jpeg 800w, https://blog.uzimihsr.com/post/2022-07-22-sotochan/sotochan04_hu_9e4c118c58626157.jpeg 1600w, https://blog.uzimihsr.com/post/2022-07-22-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;なんか色々忙しくて書くのがバチクソ遅くなってしまった。&lt;/p&gt;
&lt;p&gt;来月こそは溜めずにすぐ書きたい。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="ユニクロの紙袋めっちゃすき" class="gallery-image" data-flex-basis="321px" data-flex-grow="133" height="1483" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-07-22-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2022-07-22-sotochan/sotochan_hu_c1ae5fdc15d78101.jpeg 800w, https://blog.uzimihsr.com/post/2022-07-22-sotochan/sotochan_hu_16605a100e19604b.jpeg 1600w, https://blog.uzimihsr.com/post/2022-07-22-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>5月のそとちゃん(2022)</title><link>https://blog.uzimihsr.com/post/2022-06-14-sotochan/</link><pubDate>Tue, 14 Jun 2022 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2022-06-14-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan.jpg" alt="Featured image of post 5月のそとちゃん(2022)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#6%e3%81%95%e3%81%84" &gt;6さい&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e8%a8%98%e5%bf%b5%e5%86%99%e7%9c%9f" &gt;記念写真&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="6さい"&gt;6さい
&lt;/h3&gt;&lt;p&gt;そとちゃんがたぶん6さいになった。🎉&lt;/p&gt;
&lt;p&gt;去年は&lt;a class="link" href="https://uzimihsr.github.io/post/2021-06-01-sotochan/#%e8%aa%95%e7%94%9f%e6%97%a5" target="_blank" rel="noopener"
 &gt;奮発して買ったねこ用ケーキをめちゃくちゃ残した&lt;/a&gt;ので、&lt;br&gt;
今年はかなり小さめのタルトでお祝いした。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;たぶん6さいになりました🎂 &lt;a href="https://t.co/oyBvP8ogSW"&gt;pic.twitter.com/oyBvP8ogSW&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1520601910658859008?ref_src=twsrc%5Etfw"&gt;May 1, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;今年は表面のクリームをちょっとだけ舐めて、あとは一度も手をつけなかった。😭&lt;/p&gt;
&lt;p&gt;&lt;img alt="タルト" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan01_hu_adc16c2b475c18ad.jpeg 800w, https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan01_hu_13ab2c6cb29ad2.jpeg 1600w, https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;仕方がないのでトッピングマシマシの特製ごはんでお祝い。&lt;/p&gt;
&lt;p&gt;&lt;img alt="全マシ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan02_hu_d701d4abe6f039bd.jpeg 800w, https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan02_hu_5fbd296c00e15f00.jpeg 1600w, https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan02_hu_2239fcb778b29fec.jpeg 2400w, https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan02.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;こちらはものすごい勢いで完食。&lt;br&gt;
やっぱり甘いものよりしょっぱいものの方がいいみたい。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ちゅーるマシマシごはん &lt;a href="https://t.co/GLChnmvNyx"&gt;pic.twitter.com/GLChnmvNyx&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1520722992141303808?ref_src=twsrc%5Etfw"&gt;May 1, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;div class="video-wrapper"&gt;
 &lt;iframe loading="lazy" 
 src="https://www.youtube.com/embed/pRmf5kvOgxE" 
 allowfullscreen 
 title="YouTube Video"
 &gt;
 &lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;誕生日プレゼントは&lt;a class="link" href="https://www.petio.com/item/4903588264962/" target="_blank" rel="noopener"
 &gt;動くえびのおもちゃ&lt;/a&gt;。&lt;br&gt;
結構おもしろそうだが&amp;hellip;?&lt;/p&gt;
&lt;div class="video-wrapper"&gt;
 &lt;iframe loading="lazy" 
 src="https://www.youtube.com/embed/F6RQxcV6ecw" 
 allowfullscreen 
 title="YouTube Video"
 &gt;
 &lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;残念😭😭😭&lt;/p&gt;
&lt;p&gt;でもそとちゃんがちょっとだけ嬉しそうだったのでヨシ！&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;満足 &lt;a href="https://t.co/36VmfBEVqk"&gt;pic.twitter.com/36VmfBEVqk&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1520745820110585858?ref_src=twsrc%5Etfw"&gt;May 1, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;h3 id="記念写真"&gt;記念写真
&lt;/h3&gt;&lt;p&gt;今年も去年と同じ写真屋さんに記念写真を撮りに行った。📷&lt;/p&gt;
&lt;p&gt;そとちゃんは今年も全然おとなしくできなかった。😂&lt;/p&gt;
&lt;p&gt;&lt;img alt="目線をくれない" class="gallery-image" data-flex-basis="360px" data-flex-grow="150" height="3333" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan03.jpg" srcset="https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan03_hu_ed388906c6025151.jpg 800w, https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan03_hu_595779a9305d3ef9.jpg 1600w, https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan03_hu_5a335061507a84dc.jpg 2400w, https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan03.jpg 5000w" width="5000"&gt;&lt;/p&gt;
&lt;p&gt;隣のスタジオ(部屋は繋がっている)で撮ってた人が気になってしまい、&lt;br&gt;
ずっと目で追いかけていた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ちょっとかっこいい" class="gallery-image" data-flex-basis="360px" data-flex-grow="150" height="3333" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan04.jpg" srcset="https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan04_hu_2f5050b1d39fbb32.jpg 800w, https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan04_hu_75ab151a60d96e4a.jpg 1600w, https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan04_hu_5b524ffe606b9481.jpg 2400w, https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan04.jpg 5000w" width="5000"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="貴重なカメラ目線" class="gallery-image" data-flex-basis="159px" data-flex-grow="66" height="5000" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan05.jpg" srcset="https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan05_hu_1bb15f08c76bb483.jpg 800w, https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan05_hu_e893ae87ebe71538.jpg 1600w, https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan05_hu_d6352fa75d0009a0.jpg 2400w, https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan05.jpg 3333w" width="3333"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="スマホの待受にした" class="gallery-image" data-flex-basis="159px" data-flex-grow="66" height="5000" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan06.jpg" srcset="https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan06_hu_e4c4f38c8c719b22.jpg 800w, https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan06_hu_73464c145eeb5e98.jpg 1600w, https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan06_hu_58c5e8046c8c0694.jpg 2400w, https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan06.jpg 3333w" width="3333"&gt;&lt;/p&gt;
&lt;p&gt;入っちゃいけないところを探検したりなかなかカメラの方を向いてくれなかったりで撮影は本当に大変だった。&lt;/p&gt;
&lt;p&gt;気が済むまで遊ばせたりしてなんとか最低限の枚数は撮れたが、&lt;br&gt;
今度は疲れて集中力が無くなってしまったのでそれ以上はあまり撮れなかった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="カオス" class="gallery-image" data-flex-basis="360px" data-flex-grow="150" height="3333" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan07.jpg" srcset="https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan07_hu_795fdecad6694c79.jpg 800w, https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan07_hu_31638632416293f0.jpg 1600w, https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan07_hu_5e71e5b6020b138e.jpg 2400w, https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan07.jpg 5000w" width="5000"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="一仕事終えた顔" class="gallery-image" data-flex-basis="159px" data-flex-grow="66" height="5000" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan08.jpg" srcset="https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan08_hu_f7c234294306d1af.jpg 800w, https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan08_hu_43f28fdc190aabba.jpg 1600w, https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan08_hu_6d30eed56c993b54.jpg 2400w, https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan08.jpg 3333w" width="3333"&gt;&lt;/p&gt;
&lt;p&gt;俺とカメラマンさんは大変な思いをしたけどそとちゃんは楽しめたみたいなのでよかった(?)。&lt;br&gt;
また来年も撮りに行きたい。&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;そとちゃんと暮らし始めてからもう3年経つことに驚いた。&lt;br&gt;
あっという間だった。&lt;/p&gt;
&lt;p&gt;初めて会った時から割と懐いてくれてたけど、&lt;br&gt;
この3年でさらに仲良くなれたように思う。&lt;br&gt;
(ちなみに一緒にベッドで寝たのは数回しかない。&lt;del&gt;ガードが固い&lt;/del&gt;)&lt;/p&gt;
&lt;p&gt;ついでにふてぶてしさが日に日に増している気がするが、&lt;br&gt;
ねこは幸せになるほどそうなっていくものだと信じたい&amp;hellip;&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="今年のベストショット" class="gallery-image" data-flex-basis="363px" data-flex-grow="151" height="3239" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan_hu_bce381a4e1000ad.jpg 800w, https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan_hu_7600629109a11365.jpg 1600w, https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan_hu_8c5cc2b573f4a0ca.jpg 2400w, https://blog.uzimihsr.com/post/2022-06-14-sotochan/sotochan.jpg 4906w" width="4906"&gt;&lt;/p&gt;</description></item><item><title>Setting up my MacBook Pro(2021) (brew+zsh+iterm2)</title><link>https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/</link><pubDate>Sun, 15 May 2022 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sotochan.jpeg" alt="Featured image of post Setting up my MacBook Pro(2021) (brew+zsh+iterm2)" /&gt;&lt;p&gt;&lt;a class="link" href="#%e3%81%be%e3%81%a8%e3%82%81" &gt;日本語/Japanese&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="summary"&gt;Summary
&lt;/h2&gt;&lt;p&gt;This is a note on setting up the terminal on my new MacBook.&lt;/p&gt;
&lt;h2 id="prerequisites"&gt;Prerequisites
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;MacBook Pro 16-inch 2021
&lt;ul&gt;
&lt;li&gt;macOS Monterey 12.2.1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="details"&gt;Details
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#install-homebrew" &gt;Install Homebrew&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#install-zsh-plugins" &gt;Install zsh plugins&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#configure-prompt" &gt;Configure PROMPT&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#install-iterm2" &gt;Install iterm2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="install-homebrew"&gt;Install Homebrew
&lt;/h3&gt;&lt;p&gt;Since Catalina, the default login shell for Mac is zsh.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$SHELL&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/bin/zsh
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % zsh --version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;zsh 5.8 &lt;span class="o"&gt;(&lt;/span&gt;x86_64-apple-darwin21.0&lt;span class="o"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;At first, install &lt;strong&gt;Homebrew&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Open &lt;a class="link" href="https://brew.sh" target="_blank" rel="noopener"
 &gt;https://brew.sh&lt;/a&gt; and copy and paste the command in the terminal.&lt;/p&gt;
&lt;p&gt;&lt;img alt="https://brew.sh" class="gallery-image" data-flex-basis="335px" data-flex-grow="139" height="632" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc01.png" srcset="https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc01_hu_a56d9f7eb996545b.png 800w, https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc01.png 883w" width="883"&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % /bin/bash -c &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Warning: /opt/homebrew/bin is not in your PATH.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Instructions on how to configure your shell &lt;span class="k"&gt;for&lt;/span&gt; Homebrew
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; can be found in the &lt;span class="s1"&gt;&amp;#39;Next steps&amp;#39;&lt;/span&gt; section below.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;==&lt;/span&gt;&amp;gt; Installation successful!
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;==&lt;/span&gt;&amp;gt; Next steps:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- Run these two commands in your terminal to add Homebrew to your PATH:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;eval &amp;#34;$(/opt/homebrew/bin/brew shellenv)&amp;#34;&amp;#39;&lt;/span&gt; &amp;gt;&amp;gt; /Users/uzimihsr/.zprofile
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;/opt/homebrew/bin/brew shellenv&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- Run brew &lt;span class="nb"&gt;help&lt;/span&gt; to get started
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- Further documentation:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; https://docs.brew.sh&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Follow the instructions to update the &lt;strong&gt;PATH&lt;/strong&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;eval &amp;#34;$(/opt/homebrew/bin/brew shellenv)&amp;#34;&amp;#39;&lt;/span&gt; &amp;gt;&amp;gt; /Users/&lt;span class="nv"&gt;$USER&lt;/span&gt;/.zprofile
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % &lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;/opt/homebrew/bin/brew shellenv&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % brew doctor
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Your system is ready to brew.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % which brew
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/opt/homebrew/bin/brew
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % brew --version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Homebrew 3.4.10
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Homebrew/homebrew-core &lt;span class="o"&gt;(&lt;/span&gt;git revision 239cad746ef&lt;span class="p"&gt;;&lt;/span&gt; last commit 2022-05-03&lt;span class="o"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Good.&lt;br&gt;
Now I can use the &lt;strong&gt;brew&lt;/strong&gt; command.&lt;/p&gt;
&lt;h3 id="install-zsh-plugins"&gt;Install zsh plugins
&lt;/h3&gt;&lt;p&gt;Next, install the following zsh plugins with &lt;strong&gt;brew&lt;/strong&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/zsh-users/zsh-autosuggestions" target="_blank" rel="noopener"
 &gt;zsh-autosuggestions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/zsh-users/zsh-completions" target="_blank" rel="noopener"
 &gt;zsh-completions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/zsh-users/zsh-syntax-highlighting" target="_blank" rel="noopener"
 &gt;zsh-syntax-highlighting&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % brew install zsh-autosuggestions
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;==&lt;/span&gt;&amp;gt; Caveats
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;To activate the autosuggestions, add the following at the end of your .zshrc:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;source&lt;/span&gt; /opt/homebrew/share/zsh-autosuggestions/zsh-autosuggestions.zsh
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;You will also need to restart your terminal &lt;span class="k"&gt;for&lt;/span&gt; this change to take effect.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % brew install zsh-completions
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;==&lt;/span&gt;&amp;gt; Caveats
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;To activate these completions, add the following to your .zshrc:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; brew &lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&amp;gt;/dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;FPATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;brew --prefix&lt;span class="k"&gt;)&lt;/span&gt;/share/zsh-completions:&lt;span class="nv"&gt;$FPATH&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; autoload -Uz compinit
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; compinit
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;You may also need to force rebuild &lt;span class="sb"&gt;`&lt;/span&gt;zcompdump&lt;span class="sb"&gt;`&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; rm -f ~/.zcompdump&lt;span class="p"&gt;;&lt;/span&gt; compinit
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Additionally, &lt;span class="k"&gt;if&lt;/span&gt; you receive &lt;span class="s2"&gt;&amp;#34;zsh compinit: insecure directories&amp;#34;&lt;/span&gt; warnings when attempting
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;to load these completions, you may need to run this:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; chmod -R go-w &lt;span class="s1"&gt;&amp;#39;/opt/homebrew/share/zsh&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % brew install zsh-syntax-highlighting
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;==&lt;/span&gt;&amp;gt; Caveats
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;To activate the syntax highlighting, add the following at the end of your .zshrc:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;source&lt;/span&gt; /opt/homebrew/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;If you receive &lt;span class="s2"&gt;&amp;#34;highlighters directory not found&amp;#34;&lt;/span&gt; error message,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;you may need to add the following to your .zshenv:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;ZSH_HIGHLIGHT_HIGHLIGHTERS_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/opt/homebrew/share/zsh-syntax-highlighting/highlighters
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Follow the instructions to create &lt;strong&gt;~/.zshrc&lt;/strong&gt;, then restart the terminal.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % cat ~/.zshrc 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# zsh-autosuggestions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;source&lt;/span&gt; /opt/homebrew/share/zsh-autosuggestions/zsh-autosuggestions.zsh
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# zsh-completions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; brew &lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&amp;gt;/dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;FPATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;brew --prefix&lt;span class="k"&gt;)&lt;/span&gt;/share/zsh-completions:&lt;span class="nv"&gt;$FPATH&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; autoload -Uz compinit
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; compinit
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# zsh-syntax-highlighting&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;source&lt;/span&gt; /opt/homebrew/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Follow the instructions on &lt;strong&gt;zsh-completions&lt;/strong&gt; to rebuild &lt;strong&gt;zcompdump&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The &amp;ldquo;zsh compinit: insecure directories&amp;rdquo; error did not go away with the command as instructed, so I was a bit worn out.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % rm -f ~/.zcompdump&lt;span class="p"&gt;;&lt;/span&gt; compinit
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;zsh compinit: insecure directories, run compaudit &lt;span class="k"&gt;for&lt;/span&gt; list.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Ignore insecure directories and &lt;span class="k"&gt;continue&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;y&lt;span class="o"&gt;]&lt;/span&gt; or abort compinit &lt;span class="o"&gt;[&lt;/span&gt;n&lt;span class="o"&gt;]&lt;/span&gt;? y
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % chmod -R go-w &lt;span class="s1"&gt;&amp;#39;/opt/homebrew/share/zsh&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % rm -f ~/.zcompdump&lt;span class="p"&gt;;&lt;/span&gt; compinit
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;zsh compinit: insecure directories, run compaudit &lt;span class="k"&gt;for&lt;/span&gt; list.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Ignore insecure directories and &lt;span class="k"&gt;continue&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;y&lt;span class="o"&gt;]&lt;/span&gt; or abort compinit &lt;span class="o"&gt;[&lt;/span&gt;n&lt;span class="o"&gt;]&lt;/span&gt;? y
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % compaudit 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;There are insecure directories:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/opt/homebrew/share
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % chmod -R go-w &lt;span class="s1"&gt;&amp;#39;/opt/homebrew/share&amp;#39;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % rm -f ~/.zcompdump&lt;span class="p"&gt;;&lt;/span&gt; compinit&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Restart the terminal again, and all plugins are enabled.&lt;/p&gt;
&lt;h3 id="configure-prompt"&gt;Configure PROMPT
&lt;/h3&gt;&lt;p&gt;Set up the &lt;strong&gt;PROMPT&lt;/strong&gt; to be more convenient.&lt;/p&gt;
&lt;p&gt;My PROMPT shows the current directory and a newlined &lt;strong&gt;$&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://zsh.sourceforge.io/Doc/Release/Prompt-Expansion.html#Prompt-Expansion" target="_blank" rel="noopener"
 &gt;The Z Shell Manual&lt;/a&gt; has more details on the variables that can be used with the PROMPT.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % &lt;span class="nv"&gt;PROMPT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="s1"&gt;$&amp;#39;\n&amp;#39;&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;%d&amp;#34;&lt;/span&gt;&lt;span class="s1"&gt;$&amp;#39;\n&amp;#39;&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;$&lt;span class="s2"&gt; &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/Users/uzimihsr
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Finally, update &lt;strong&gt;~/.zshrc&lt;/strong&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat ~/.zshrc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;PROMPT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="s1"&gt;$&amp;#39;\n&amp;#39;&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;%d&amp;#34;&lt;/span&gt;&lt;span class="s1"&gt;$&amp;#39;\n&amp;#39;&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;$&lt;span class="s2"&gt; &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="install-iterm2"&gt;Install iterm2
&lt;/h3&gt;&lt;p&gt;Install &lt;a class="link" href="https://iterm2.com/" target="_blank" rel="noopener"
 &gt;iterm2&lt;/a&gt; with &lt;a class="link" href="https://formulae.brew.sh/cask/iterm2" target="_blank" rel="noopener"
 &gt;homebrew cask&lt;/a&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ brew install --cask &lt;span class="nv"&gt;iterm2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;==&lt;/span&gt;&amp;gt; Tapping homebrew/cask
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Cloning into &lt;span class="s1"&gt;&amp;#39;/opt/homebrew/Library/Taps/homebrew/homebrew-cask&amp;#39;&lt;/span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;remote: Enumerating objects: 635835, &lt;span class="k"&gt;done&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;remote: Counting objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;9/9&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;remote: Compressing objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;5/5&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;remote: Total &lt;span class="m"&gt;635835&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;delta 4&lt;span class="o"&gt;)&lt;/span&gt;, reused &lt;span class="m"&gt;9&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;delta 4&lt;span class="o"&gt;)&lt;/span&gt;, pack-reused &lt;span class="m"&gt;635826&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Receiving objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;635835/635835&lt;span class="o"&gt;)&lt;/span&gt;, 299.65 MiB &lt;span class="p"&gt;|&lt;/span&gt; 4.39 MiB/s, &lt;span class="k"&gt;done&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Resolving deltas: 100% &lt;span class="o"&gt;(&lt;/span&gt;450073/450073&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Tapped &lt;span class="m"&gt;3994&lt;/span&gt; casks &lt;span class="o"&gt;(&lt;/span&gt;4,066 files, 320.0MB&lt;span class="o"&gt;)&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;==&lt;/span&gt;&amp;gt; Downloading https://iterm2.com/downloads/stable/iTerm2-3_4_15.zip
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;######################################################################## 100.0%&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;==&lt;/span&gt;&amp;gt; Installing Cask &lt;span class="nv"&gt;iterm2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;==&lt;/span&gt;&amp;gt; Moving App &lt;span class="s1"&gt;&amp;#39;iTerm.app&amp;#39;&lt;/span&gt; to &lt;span class="s1"&gt;&amp;#39;/Applications/iTerm.app&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🍺 iterm2 was successfully installed!&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I like to double-tap &lt;strong&gt;Control(⌃)&lt;/strong&gt; to show and hide the terminal with &lt;a class="link" href="https://iterm2.com/documentation-hotkey.html" target="_blank" rel="noopener"
 &gt;Hotkeys&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Open &amp;ldquo;Preference(&lt;strong&gt;⌘,&lt;/strong&gt;)&amp;quot;→&amp;ldquo;Keys&amp;rdquo;→&amp;ldquo;Hotkey&amp;rdquo;→&amp;ldquo;Create a Dedicated Hotkey window&amp;hellip;&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="“Create a Dedicated Hotkey window…”" class="gallery-image" data-flex-basis="620px" data-flex-grow="258" height="694" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc02.png" srcset="https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc02_hu_1758054e0394c32b.png 800w, https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc02_hu_2f54c7593aff2863.png 1600w, https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc02.png 1794w" width="1794"&gt;&lt;/p&gt;
&lt;p&gt;Set up the Hotkey window as shown in the images below.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Double-tap key: ⌃Control" class="gallery-image" data-flex-basis="388px" data-flex-grow="161" height="697" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc03.png" srcset="https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc03_hu_39372a7504a4d13.png 800w, https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc03.png 1128w" width="1128"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="configure Style, Screen, Space" class="gallery-image" data-flex-basis="357px" data-flex-grow="149" height="1398" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc04.png" srcset="https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc04_hu_515e8dd422fca602.png 800w, https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc04_hu_e8dc8f8f339756a.png 1600w, https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc04.png 2084w" width="2084"&gt;&lt;/p&gt;
&lt;p&gt;In addition, go to &amp;ldquo;Advanced&amp;rdquo;→&amp;ldquo;Open a new window when you click the dock icon&amp;hellip;&amp;rdquo; and specify &amp;ldquo;No&amp;rdquo; to prevent opening a new terminal window except with a hotkey.&lt;/p&gt;
&lt;p&gt;&lt;img alt="prevent opening a new terminal window except with a hotkey" class="gallery-image" data-flex-basis="440px" data-flex-grow="183" height="615" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc05.png" srcset="https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc05_hu_b23f20a28cc9b157.png 800w, https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc05.png 1130w" width="1130"&gt;&lt;/p&gt;
&lt;p&gt;Restart iterm2 and hit Control(⌃) repeatedly and the terminal will flap open and close.&lt;/p&gt;
&lt;p&gt;&lt;img alt="after configuration" class="gallery-image" data-flex-basis="371px" data-flex-grow="154" height="2234" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc06.png" srcset="https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc06_hu_c29fcfdc72a74ff1.png 800w, https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc06_hu_c8d48960415dd09d.png 1600w, https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc06_hu_bcd78609b43ee45a.png 2400w, https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc06.png 3456w" width="3456"&gt;&lt;/p&gt;
&lt;p&gt;(The following is the same content in Japanese.)&lt;/p&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;MacBookを買い換えたので、ターミナル周りの設定をした。&lt;br&gt;
あんまりやる機会もないけど一応自分用にログを残しておく。&lt;/p&gt;
&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;MacBook Pro 16-inch 2021
&lt;ul&gt;
&lt;li&gt;macOS Monterey 12.2.1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#homebrew%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" &gt;Homebrewのインストール&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#zsh%e3%83%97%e3%83%a9%e3%82%b0%e3%82%a4%e3%83%b3%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" &gt;zshプラグインのインストール&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%97%e3%83%ad%e3%83%b3%e3%83%97%e3%83%88%e3%82%92%e3%81%84%e3%81%98%e3%82%8b" &gt;プロンプトをいじる&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#iterm2%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" &gt;iterm2のインストール&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="homebrewのインストール"&gt;Homebrewのインストール
&lt;/h3&gt;&lt;p&gt;新しいMacが起動したのでまずはシェルをzshに&amp;hellip;&lt;br&gt;
と思ったらだいぶ前(Catalina?)からデフォルトでシェルがzshになっていたらしい。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$SHELL&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/bin/zsh
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % zsh --version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;zsh 5.8 &lt;span class="o"&gt;(&lt;/span&gt;x86_64-apple-darwin21.0&lt;span class="o"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;zshのプラグインを入れたいし、後でいろんなものを入れるのに使うのでまずはbrewが使えるようにする。&lt;/p&gt;
&lt;p&gt;ターミナルを開き、&lt;a class="link" href="https://brew.sh" target="_blank" rel="noopener"
 &gt;https://brew.sh&lt;/a&gt;からコマンドをコピーしてきて貼り付け。&lt;/p&gt;
&lt;p&gt;&lt;img alt="https://brew.sh" class="gallery-image" data-flex-basis="335px" data-flex-grow="139" height="632" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc01.png" srcset="https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc01_hu_a56d9f7eb996545b.png 800w, https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc01.png 883w" width="883"&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % /bin/bash -c &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Warning: /opt/homebrew/bin is not in your PATH.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Instructions on how to configure your shell &lt;span class="k"&gt;for&lt;/span&gt; Homebrew
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; can be found in the &lt;span class="s1"&gt;&amp;#39;Next steps&amp;#39;&lt;/span&gt; section below.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;==&lt;/span&gt;&amp;gt; Installation successful!
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;==&lt;/span&gt;&amp;gt; Next steps:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- Run these two commands in your terminal to add Homebrew to your PATH:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;eval &amp;#34;$(/opt/homebrew/bin/brew shellenv)&amp;#34;&amp;#39;&lt;/span&gt; &amp;gt;&amp;gt; /Users/uzimihsr/.zprofile
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;/opt/homebrew/bin/brew shellenv&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- Run brew &lt;span class="nb"&gt;help&lt;/span&gt; to get started
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- Further documentation:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; https://docs.brew.sh&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;途中でPATHを通せ的な指示があったのでそれに従い、動作を確認する。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;eval &amp;#34;$(/opt/homebrew/bin/brew shellenv)&amp;#34;&amp;#39;&lt;/span&gt; &amp;gt;&amp;gt; /Users/&lt;span class="nv"&gt;$USER&lt;/span&gt;/.zprofile
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % &lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;/opt/homebrew/bin/brew shellenv&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % brew doctor
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Your system is ready to brew.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % which brew
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/opt/homebrew/bin/brew
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % brew --version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Homebrew 3.4.10
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Homebrew/homebrew-core &lt;span class="o"&gt;(&lt;/span&gt;git revision 239cad746ef&lt;span class="p"&gt;;&lt;/span&gt; last commit 2022-05-03&lt;span class="o"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;これでbrewが使えるようになった。&lt;/p&gt;
&lt;h3 id="zshプラグインのインストール"&gt;zshプラグインのインストール
&lt;/h3&gt;&lt;p&gt;zshを快適に使うために下記のプラグインをbrewで入れる。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/zsh-users/zsh-autosuggestions" target="_blank" rel="noopener"
 &gt;zsh-autosuggestions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/zsh-users/zsh-completions" target="_blank" rel="noopener"
 &gt;zsh-completions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/zsh-users/zsh-syntax-highlighting" target="_blank" rel="noopener"
 &gt;zsh-syntax-highlighting&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % brew install zsh-autosuggestions
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;==&lt;/span&gt;&amp;gt; Caveats
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;To activate the autosuggestions, add the following at the end of your .zshrc:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;source&lt;/span&gt; /opt/homebrew/share/zsh-autosuggestions/zsh-autosuggestions.zsh
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;You will also need to restart your terminal &lt;span class="k"&gt;for&lt;/span&gt; this change to take effect.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % brew install zsh-completions
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;==&lt;/span&gt;&amp;gt; Caveats
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;To activate these completions, add the following to your .zshrc:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; brew &lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&amp;gt;/dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;FPATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;brew --prefix&lt;span class="k"&gt;)&lt;/span&gt;/share/zsh-completions:&lt;span class="nv"&gt;$FPATH&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; autoload -Uz compinit
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; compinit
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;You may also need to force rebuild &lt;span class="sb"&gt;`&lt;/span&gt;zcompdump&lt;span class="sb"&gt;`&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; rm -f ~/.zcompdump&lt;span class="p"&gt;;&lt;/span&gt; compinit
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Additionally, &lt;span class="k"&gt;if&lt;/span&gt; you receive &lt;span class="s2"&gt;&amp;#34;zsh compinit: insecure directories&amp;#34;&lt;/span&gt; warnings when attempting
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;to load these completions, you may need to run this:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; chmod -R go-w &lt;span class="s1"&gt;&amp;#39;/opt/homebrew/share/zsh&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % brew install zsh-syntax-highlighting
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;==&lt;/span&gt;&amp;gt; Caveats
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;To activate the syntax highlighting, add the following at the end of your .zshrc:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;source&lt;/span&gt; /opt/homebrew/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;If you receive &lt;span class="s2"&gt;&amp;#34;highlighters directory not found&amp;#34;&lt;/span&gt; error message,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;you may need to add the following to your .zshenv:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;ZSH_HIGHLIGHT_HIGHLIGHTERS_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/opt/homebrew/share/zsh-syntax-highlighting/highlighters
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;インストール時の指示に従い、&lt;strong&gt;~/.zshrc&lt;/strong&gt;を作成する。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % cat ~/.zshrc 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# zsh-autosuggestions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;source&lt;/span&gt; /opt/homebrew/share/zsh-autosuggestions/zsh-autosuggestions.zsh
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# zsh-completions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; brew &lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&amp;gt;/dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;FPATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;brew --prefix&lt;span class="k"&gt;)&lt;/span&gt;/share/zsh-completions:&lt;span class="nv"&gt;$FPATH&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; autoload -Uz compinit
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; compinit
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# zsh-syntax-highlighting&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;source&lt;/span&gt; /opt/homebrew/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;ここで一旦ターミナルを閉じてから再度起動する。&lt;/p&gt;
&lt;p&gt;zsh-completionsのインストール時に指示された通り、zcompdumpを再作成する。&lt;/p&gt;
&lt;p&gt;指示された通りのコマンドでは&amp;quot;zsh compinit: insecure directories&amp;quot;のエラーが消えなかったのでちょっと消耗した。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % rm -f ~/.zcompdump&lt;span class="p"&gt;;&lt;/span&gt; compinit
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;zsh compinit: insecure directories, run compaudit &lt;span class="k"&gt;for&lt;/span&gt; list.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Ignore insecure directories and &lt;span class="k"&gt;continue&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;y&lt;span class="o"&gt;]&lt;/span&gt; or abort compinit &lt;span class="o"&gt;[&lt;/span&gt;n&lt;span class="o"&gt;]&lt;/span&gt;? y
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % chmod -R go-w &lt;span class="s1"&gt;&amp;#39;/opt/homebrew/share/zsh&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % rm -f ~/.zcompdump&lt;span class="p"&gt;;&lt;/span&gt; compinit
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;zsh compinit: insecure directories, run compaudit &lt;span class="k"&gt;for&lt;/span&gt; list.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Ignore insecure directories and &lt;span class="k"&gt;continue&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;y&lt;span class="o"&gt;]&lt;/span&gt; or abort compinit &lt;span class="o"&gt;[&lt;/span&gt;n&lt;span class="o"&gt;]&lt;/span&gt;? y
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % compaudit 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;There are insecure directories:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/opt/homebrew/share
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % chmod -R go-w &lt;span class="s1"&gt;&amp;#39;/opt/homebrew/share&amp;#39;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % rm -f ~/.zcompdump&lt;span class="p"&gt;;&lt;/span&gt; compinit&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;もう一度再起動すると今回追加したプラグインが全て有効になっている。&lt;/p&gt;
&lt;h3 id="プロンプトをいじる"&gt;プロンプトをいじる
&lt;/h3&gt;&lt;p&gt;初期設定のプロンプトだと使いづらいのでここでいじっておく。&lt;/p&gt;
&lt;p&gt;PROMPTで使える変数については&lt;a class="link" href="https://zsh.sourceforge.io/Doc/Release/Prompt-Expansion.html#Prompt-Expansion" target="_blank" rel="noopener"
 &gt;The Z Shell Manual&lt;/a&gt;が詳しい。&lt;/p&gt;
&lt;p&gt;自分は割とシンプルなのが好きで、&lt;br&gt;
直前のコマンド実行結果から改行されてカレントディレクトリが表示できていればそれでいい。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr@MacBook ~ % &lt;span class="nv"&gt;PROMPT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="s1"&gt;$&amp;#39;\n&amp;#39;&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;%d&amp;#34;&lt;/span&gt;&lt;span class="s1"&gt;$&amp;#39;\n&amp;#39;&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;$&lt;span class="s2"&gt; &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/Users/uzimihsr
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;色々試して気に入ったものができたので、&lt;strong&gt;~/.zshrc&lt;/strong&gt;に書いておく。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat ~/.zshrc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;PROMPT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="s1"&gt;$&amp;#39;\n&amp;#39;&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;%d&amp;#34;&lt;/span&gt;&lt;span class="s1"&gt;$&amp;#39;\n&amp;#39;&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;$&lt;span class="s2"&gt; &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="iterm2のインストール"&gt;iterm2のインストール
&lt;/h3&gt;&lt;p&gt;ターミナルも標準のままだと不便なので、&lt;br&gt;
&lt;a class="link" href="https://formulae.brew.sh/cask/iterm2" target="_blank" rel="noopener"
 &gt;homebrew cask&lt;/a&gt;を使って&lt;a class="link" href="https://iterm2.com/" target="_blank" rel="noopener"
 &gt;iterm2&lt;/a&gt;をインストールする。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-zsh" data-lang="zsh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ brew install --cask &lt;span class="nv"&gt;iterm2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;==&lt;/span&gt;&amp;gt; Tapping homebrew/cask
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Cloning into &lt;span class="s1"&gt;&amp;#39;/opt/homebrew/Library/Taps/homebrew/homebrew-cask&amp;#39;&lt;/span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;remote: Enumerating objects: 635835, &lt;span class="k"&gt;done&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;remote: Counting objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;9/9&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;remote: Compressing objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;5/5&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;remote: Total &lt;span class="m"&gt;635835&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;delta 4&lt;span class="o"&gt;)&lt;/span&gt;, reused &lt;span class="m"&gt;9&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;delta 4&lt;span class="o"&gt;)&lt;/span&gt;, pack-reused &lt;span class="m"&gt;635826&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Receiving objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;635835/635835&lt;span class="o"&gt;)&lt;/span&gt;, 299.65 MiB &lt;span class="p"&gt;|&lt;/span&gt; 4.39 MiB/s, &lt;span class="k"&gt;done&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Resolving deltas: 100% &lt;span class="o"&gt;(&lt;/span&gt;450073/450073&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Tapped &lt;span class="m"&gt;3994&lt;/span&gt; casks &lt;span class="o"&gt;(&lt;/span&gt;4,066 files, 320.0MB&lt;span class="o"&gt;)&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;==&lt;/span&gt;&amp;gt; Downloading https://iterm2.com/downloads/stable/iTerm2-3_4_15.zip
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;######################################################################## 100.0%&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;==&lt;/span&gt;&amp;gt; Installing Cask &lt;span class="nv"&gt;iterm2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;==&lt;/span&gt;&amp;gt; Moving App &lt;span class="s1"&gt;&amp;#39;iTerm.app&amp;#39;&lt;/span&gt; to &lt;span class="s1"&gt;&amp;#39;/Applications/iTerm.app&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🍺 iterm2 was successfully installed!&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;自分はCtrl(&lt;code&gt;⌃&lt;/code&gt;)を2回叩いてターミナルを出したり消したりできるのが好きなので、&lt;br&gt;
&lt;a class="link" href="https://iterm2.com/documentation-hotkey.html" target="_blank" rel="noopener"
 &gt;Hotkeys&lt;/a&gt;を参考にitermの設定をいじっていく。&lt;/p&gt;
&lt;p&gt;Preferenceを開き、&amp;ldquo;Keys&amp;rdquo;→&amp;ldquo;Hotkey&amp;rdquo;→&amp;ldquo;Create a Dedicated Hotkey window&amp;hellip;&amp;ldquo;と進む。&lt;/p&gt;
&lt;p&gt;&lt;img alt="“Create a Dedicated Hotkey window…”" class="gallery-image" data-flex-basis="620px" data-flex-grow="258" height="694" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc02.png" srcset="https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc02_hu_1758054e0394c32b.png 800w, https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc02_hu_2f54c7593aff2863.png 1600w, https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc02.png 1794w" width="1794"&gt;&lt;/p&gt;
&lt;p&gt;下記画像のように設定していく。&lt;/p&gt;
&lt;p&gt;&lt;img alt="CtrlをDouble-tap keyにして\"OK”" class="gallery-image" data-flex-basis="388px" data-flex-grow="161" height="697" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc03.png" srcset="https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc03_hu_39372a7504a4d13.png 800w, https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc03.png 1128w" width="1128"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Style, Screen, Spaceを指定する" class="gallery-image" data-flex-basis="357px" data-flex-grow="149" height="1398" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc04.png" srcset="https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc04_hu_515e8dd422fca602.png 800w, https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc04_hu_e8dc8f8f339756a.png 1600w, https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc04.png 2084w" width="2084"&gt;&lt;/p&gt;
&lt;p&gt;また、ターミナルを開くのはhotkeyだけにしたいので、itermの起動時に自動で新規ターミナルを開かないようにする。&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Advanced&amp;quot;から&amp;quot;Open a new window when you click the dock icon&amp;hellip;&amp;ldquo;を&amp;quot;No&amp;quot;に変更する。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Iterm起動時に勝手にウィンドウを開かないようにする" class="gallery-image" data-flex-basis="440px" data-flex-grow="183" height="615" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc05.png" srcset="https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc05_hu_b23f20a28cc9b157.png 800w, https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc05.png 1130w" width="1130"&gt;&lt;/p&gt;
&lt;p&gt;iterm2を再起動し、Ctrl(&lt;code&gt;⌃&lt;/code&gt;)を連打するとターミナルがパカパカ開いたり閉じたりするようになる。&lt;/p&gt;
&lt;p&gt;&lt;img alt="設定後のiterm2" class="gallery-image" data-flex-basis="371px" data-flex-grow="154" height="2234" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc06.png" srcset="https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc06_hu_c29fcfdc72a74ff1.png 800w, https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc06_hu_c8d48960415dd09d.png 1600w, https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc06_hu_bcd78609b43ee45a.png 2400w, https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sc06.png 3456w" width="3456"&gt;&lt;/p&gt;
&lt;p&gt;他にもやりたいことはあるけど、一旦ここまで。&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;新しく買ったMacBookでターミナルの設定をしてみた。&lt;/p&gt;
&lt;p&gt;M1チップが出た当初はbrewとかも結構大変だったみたいだけど、&lt;br&gt;
もう1年以上経っていたおかげかだいぶ設定もしやすかった。&lt;/p&gt;
&lt;p&gt;本当はdotfilesをちゃんと定期的に管理した方が賢いと思うけど、&lt;br&gt;
手作業で設定していくのも結構楽しい&amp;hellip;&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="耐久性をチェックするねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sotochan_hu_c5ac63cdb54d7510.jpeg 800w, https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sotochan_hu_b4518a7611d04a2a.jpeg 1600w, https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sotochan_hu_61852aac92bf7cc3.jpeg 2400w, https://blog.uzimihsr.com/post/2022-05-15-setup-macbook-brew-zsh-iterm2/sotochan.jpeg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>Convert a multi line string into a single line string leaving newline characters(LF \n) with sed</title><link>https://blog.uzimihsr.com/post/2022-05-05-sed-convert-multiline-into-singleline-leaving-newline-characters/</link><pubDate>Thu, 05 May 2022 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2022-05-05-sed-convert-multiline-into-singleline-leaving-newline-characters/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2022-05-05-sed-convert-multiline-into-singleline-leaving-newline-characters/sotochan.jpeg" alt="Featured image of post Convert a multi line string into a single line string leaving newline characters(LF \n) with sed" /&gt;&lt;p&gt;&lt;a class="link" href="#%e3%81%be%e3%81%a8%e3%82%81" &gt;日本語/Japanese&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="summary"&gt;Summary
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;sed&lt;/strong&gt; command can convert a multi line string into a single line string without deleting &lt;code&gt;\n&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# a multi line string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat text
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aaa
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bbb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ccc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# convert a multi line string into a single line&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat text &lt;span class="p"&gt;|&lt;/span&gt; sed -z &lt;span class="s1"&gt;&amp;#39;s/\n//g&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aaabbbccc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# leave newline characters(\n)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat text &lt;span class="p"&gt;|&lt;/span&gt; sed -z &lt;span class="s1"&gt;&amp;#39;s/\n/\\n/g&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aaa&lt;span class="se"&gt;\n&lt;/span&gt;bbb&lt;span class="se"&gt;\n&lt;/span&gt;ccc&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="prerequisites"&gt;Prerequisites
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;sed (GNU sed) 4.7
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;NOTE: BSD sed has different options&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="detail"&gt;Detail
&lt;/h2&gt;&lt;p&gt;I wanted to convert a multi line string into a single line string, leaving newline characters in place.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# a multi line string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat text
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aaa
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bbb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ccc&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a class="link" href="https://www.gnu.org/software/sed/manual/sed.html#Command_002dLine-Options" target="_blank" rel="noopener"
 &gt;sed -z&lt;/a&gt; can treat newline characters(&lt;code&gt;\n&lt;/code&gt;) as normal characters.&lt;br&gt;
Here is what I often do.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# convert a multi line string into a single line&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat text &lt;span class="p"&gt;|&lt;/span&gt; sed -z &lt;span class="s1"&gt;&amp;#39;s/\n//g&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aaabbbccc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# &amp;#34;-z&amp;#34; cannot be omitted&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat text &lt;span class="p"&gt;|&lt;/span&gt; sed &lt;span class="s1"&gt;&amp;#39;s/\n//g&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aaa
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bbb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ccc&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This time, I tried an another method because I had to leave newline characters.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat text &lt;span class="p"&gt;|&lt;/span&gt; sed -z &lt;span class="s1"&gt;&amp;#39;s/\n/\\n/g&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aaa&lt;span class="se"&gt;\n&lt;/span&gt;bbb&lt;span class="se"&gt;\n&lt;/span&gt;ccc&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Good.&lt;br&gt;
It seems to be working.&lt;/p&gt;
&lt;p&gt;(The following is the same content in Japanese.)&lt;/p&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;こんな感じで複数行の文字列を&lt;code&gt;\n&lt;/code&gt;を含んだまま1行にできる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 複数行の文字列&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat text
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aaa
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bbb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ccc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 普通に改行文字を消す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat text &lt;span class="p"&gt;|&lt;/span&gt; sed -z &lt;span class="s1"&gt;&amp;#39;s/\n//g&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aaabbbccc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 改行文字を\nとして表示するが改行はしない&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat text &lt;span class="p"&gt;|&lt;/span&gt; sed -z &lt;span class="s1"&gt;&amp;#39;s/\n/\\n/g&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aaa&lt;span class="se"&gt;\n&lt;/span&gt;bbb&lt;span class="se"&gt;\n&lt;/span&gt;ccc&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;sed (GNU sed) 4.7
&lt;ul&gt;
&lt;li&gt;Macにデフォルトで入ってるBSD版のsedだとオプションが違うので注意&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="詳細"&gt;詳細
&lt;/h2&gt;&lt;p&gt;複数行の文字列を改行文字(&lt;code&gt;\n&lt;/code&gt;)を残したまま1行に変換したいことがあった。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 複数行の文字列&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat text
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aaa
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bbb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ccc&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a class="link" href="https://www.gnu.org/software/sed/manual/sed.html#Command_002dLine-Options" target="_blank" rel="noopener"
 &gt;sedの-zオプション&lt;/a&gt;を使うと改行文字(&lt;code&gt;\n&lt;/code&gt;)を操作できる。&lt;br&gt;
よくやるのはこんな感じ。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 改行文字を消して1行にする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat text &lt;span class="p"&gt;|&lt;/span&gt; sed -z &lt;span class="s1"&gt;&amp;#39;s/\n//g&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aaabbbccc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# -zオプションがないと改行文字を操作できない&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat text &lt;span class="p"&gt;|&lt;/span&gt; sed &lt;span class="s1"&gt;&amp;#39;s/\n//g&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aaa
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bbb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ccc&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;今回は改行は無くしたいが改行文字(&lt;code&gt;\n&lt;/code&gt;)は残したかったので、&lt;br&gt;
次のように書いてみた。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat text &lt;span class="p"&gt;|&lt;/span&gt; sed -z &lt;span class="s1"&gt;&amp;#39;s/\n/\\n/g&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aaa&lt;span class="se"&gt;\n&lt;/span&gt;bbb&lt;span class="se"&gt;\n&lt;/span&gt;ccc&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;いい感じ。&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;なんかJSONの値に改行文字を含むテキストの内容を入れたくなることがあったんだけど調べてもやり方がすぐに出てこなかったので試してみた。&lt;br&gt;
他にもっと簡単な方法があるかも?&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="凛々しいねこ" class="gallery-image" data-flex-basis="307px" data-flex-grow="128" height="1548" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-05-05-sed-convert-multiline-into-singleline-leaving-newline-characters/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2022-05-05-sed-convert-multiline-into-singleline-leaving-newline-characters/sotochan_hu_2e5b0224b9ad1c00.jpeg 800w, https://blog.uzimihsr.com/post/2022-05-05-sed-convert-multiline-into-singleline-leaving-newline-characters/sotochan_hu_d77f1399354eb53e.jpeg 1600w, https://blog.uzimihsr.com/post/2022-05-05-sed-convert-multiline-into-singleline-leaving-newline-characters/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>4月のそとちゃん(2022)</title><link>https://blog.uzimihsr.com/post/2022-05-04-sotochan/</link><pubDate>Wed, 04 May 2022 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2022-05-04-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2022-05-04-sotochan/sotochan.jpeg" alt="Featured image of post 4月のそとちゃん(2022)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%a4%e3%82%81%e3%81%a8%e3%81%8e" &gt;つめとぎ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e6%af%9b%e5%b8%83%e3%81%a0%e3%81%84%e3%81%99%e3%81%8d" &gt;毛布だいすき&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%88%e3%81%8f%e3%81%97%e3%82%83%e3%81%b9%e3%82%8b" &gt;よくしゃべる&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="つめとぎ"&gt;つめとぎ
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2022-04-07-sotochan/#%e3%81%a4%e3%82%81%e3%81%a8%e3%81%8e%e3%83%99%e3%83%83%e3%83%89" target="_blank" rel="noopener"
 &gt;先月買ったつめとぎベッド&lt;/a&gt;をちょっと使ってくれるようになった。&lt;/p&gt;
&lt;p&gt;とてもえらい。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;えらい &lt;a href="https://t.co/yqEarIA2J2"&gt;pic.twitter.com/yqEarIA2J2&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1509818753542139904?ref_src=twsrc%5Etfw"&gt;April 1, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;でもやっぱり元のつめとぎ(ソファ)が好きみたい。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;まだソファ率の方が高い &lt;a href="https://t.co/nAGGOBtgkE"&gt;pic.twitter.com/nAGGOBtgkE&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1509834635794345985?ref_src=twsrc%5Etfw"&gt;April 1, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;そして現在&amp;hellip;&lt;/p&gt;
&lt;p&gt;ついに布が破けて中身が見えるようになってしまった&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="やりきった感" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-05-04-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2022-05-04-sotochan/sotochan01_hu_f6713a655e39812e.jpeg 800w, https://blog.uzimihsr.com/post/2022-05-04-sotochan/sotochan01_hu_b09e6b261e06ffb1.jpeg 1600w, https://blog.uzimihsr.com/post/2022-05-04-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="つめとぎだったもの" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-05-04-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2022-05-04-sotochan/sotochan02_hu_ddc27331c8c0417f.jpeg 800w, https://blog.uzimihsr.com/post/2022-05-04-sotochan/sotochan02_hu_bdcaabba4009ae42.jpeg 1600w, https://blog.uzimihsr.com/post/2022-05-04-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;逆側の肘掛けももう長くないかもしれない😭&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;あなたがバリバリしたんですよ &lt;a href="https://t.co/j7MvKmv2Oh"&gt;pic.twitter.com/j7MvKmv2Oh&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1512683094410952705?ref_src=twsrc%5Etfw"&gt;April 9, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;どうして&amp;hellip;&lt;/p&gt;
&lt;h3 id="毛布だいすき"&gt;毛布だいすき
&lt;/h3&gt;&lt;p&gt;理由は忘れちゃったけど何かの機会に&lt;a class="link" href="https://uzimihsr.github.io/post/2022-03-10-sotochan/#%e6%af%9b%e5%b8%83" target="_blank" rel="noopener"
 &gt;ベッドに敷いてる毛布&lt;/a&gt;とは別の毛布を出して、&lt;br&gt;
片付けるのが面倒でそのままソファに置いていたらねこに気に入られてしまった。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;この毛布も好き &lt;a href="https://t.co/pDolLa3wOh"&gt;pic.twitter.com/pDolLa3wOh&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1511681510067556353?ref_src=twsrc%5Etfw"&gt;April 6, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;あんなに好きだったおひるねスポットの本棚の上にも登らずに昼間はずっとここで寝ている。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ねてる &lt;a href="https://t.co/JzyLHvRKqg"&gt;pic.twitter.com/JzyLHvRKqg&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1513330193221697538?ref_src=twsrc%5Etfw"&gt;April 11, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;&lt;img alt="しっぽまくら" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-05-04-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2022-05-04-sotochan/sotochan03_hu_19e81a77c56e97ad.jpeg 800w, https://blog.uzimihsr.com/post/2022-05-04-sotochan/sotochan03_hu_8aac288663b05aff.jpeg 1600w, https://blog.uzimihsr.com/post/2022-05-04-sotochan/sotochan03.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;肌触りが好き?みたいで、よく体をこすりつけている。&lt;/p&gt;
&lt;p&gt;&lt;img alt="すりすり" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-05-04-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2022-05-04-sotochan/sotochan04_hu_65590343f84ea21.jpeg 800w, https://blog.uzimihsr.com/post/2022-05-04-sotochan/sotochan04_hu_fd4d5cda0de63a8f.jpeg 1600w, https://blog.uzimihsr.com/post/2022-05-04-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;毛布の上に乗っているときはいつもごきげん。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ごきげん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-05-04-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2022-05-04-sotochan/sotochan05_hu_d74360de70a3bb2d.jpeg 800w, https://blog.uzimihsr.com/post/2022-05-04-sotochan/sotochan05_hu_2c4430a2e0e1242c.jpeg 1600w, https://blog.uzimihsr.com/post/2022-05-04-sotochan/sotochan05.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;とはいえそろそろ暖かくなってきたので片付けたいが、&lt;br&gt;
なかなかお許しが出ない。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;攻撃の構え &lt;a href="https://t.co/Fi7Aoxm1p9"&gt;pic.twitter.com/Fi7Aoxm1p9&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1513726016250068994?ref_src=twsrc%5Etfw"&gt;April 12, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;&lt;img alt="怒" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-05-04-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2022-05-04-sotochan/sotochan06_hu_3f11fa75dbf1f830.jpeg 800w, https://blog.uzimihsr.com/post/2022-05-04-sotochan/sotochan06_hu_96dc4a06a9034b3e.jpeg 1600w, https://blog.uzimihsr.com/post/2022-05-04-sotochan/sotochan06.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;ちなみにベッドに敷いてる茶色の毛布もまだすき。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;寝てる &lt;a href="https://t.co/Pf3qVRfLuj"&gt;pic.twitter.com/Pf3qVRfLuj&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1515126509702610951?ref_src=twsrc%5Etfw"&gt;April 16, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;h3 id="よくしゃべる"&gt;よくしゃべる
&lt;/h3&gt;&lt;p&gt;そとちゃんはよくしゃべる。&lt;/p&gt;
&lt;p&gt;特に夕方の晩ごはん前はすごい。&lt;/p&gt;
&lt;p&gt;おひるねから起きてからごはんをもらうまではずっと話しかけてくる。&lt;/p&gt;
&lt;div class="video-wrapper"&gt;
 &lt;iframe loading="lazy" 
 src="https://www.youtube.com/embed/bm8gLpZqjw0" 
 allowfullscreen 
 title="YouTube Video"
 &gt;
 &lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;割とまったりしてるときにも喋ってくれる。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ひざには乗るけどかまってほしくないときがある &lt;a href="https://t.co/WTqoIZgskF"&gt;pic.twitter.com/WTqoIZgskF&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1520374358681997314?ref_src=twsrc%5Etfw"&gt;April 30, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;これくらい喋ってくれるとコミュニケーションがとれているような気分になって楽しい。&lt;/p&gt;
&lt;p&gt;あとはまだ撮れたことがないけど、遊んでるときとか早朝は爆音で叫ぶのでいつか動画にしたい。&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;そとちゃんはいつも通り元気だった。&lt;/p&gt;
&lt;p&gt;何気なく動画をいくつか撮ってみたら結構楽しかったので、&lt;br&gt;
もうちょっと頻繁に撮ってもいいかもしれない。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="狩りに夢中なねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-05-04-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2022-05-04-sotochan/sotochan_hu_82aff50b6f09d862.jpeg 800w, https://blog.uzimihsr.com/post/2022-05-04-sotochan/sotochan_hu_19e942cb95b9541e.jpeg 1600w, https://blog.uzimihsr.com/post/2022-05-04-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>Read the specified YAML file with golang</title><link>https://blog.uzimihsr.com/post/2022-04-25-read-yaml-file-golang/</link><pubDate>Mon, 25 Apr 2022 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2022-04-25-read-yaml-file-golang/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2022-04-25-read-yaml-file-golang/sotochan.jpeg" alt="Featured image of post Read the specified YAML file with golang" /&gt;&lt;p&gt;&lt;a class="link" href="#%e3%81%be%e3%81%a8%e3%82%81" &gt;日本語版/Japanese&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="summary"&gt;Summary
&lt;/h2&gt;&lt;p&gt;The following code is an example of reading a YAML file with the name specified by a command line flag.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/afd285ac5d7d61a61d4f70e60816e9ad.js"&gt;&lt;/script&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat members.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;members:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- name: &lt;span class="s2"&gt;&amp;#34;John Doe&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; age: &lt;span class="m"&gt;20&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; privileged: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; languages:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - language: &lt;span class="s2"&gt;&amp;#34;Java&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; years: &lt;span class="m"&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - language: &lt;span class="s2"&gt;&amp;#34;Go&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; years: &lt;span class="m"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- name: &lt;span class="s2"&gt;&amp;#34;Jane Doe&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; age: &lt;span class="m"&gt;30&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; privileged: &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go run main.go -yaml-file members.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;name: John Doe
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;age: &lt;span class="m"&gt;20&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;privileged: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;language 0: Java &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt; year&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;language 1: Go &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; year&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;name: Jane Doe
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;age: &lt;span class="m"&gt;30&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;privileged: true&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="prerequisites"&gt;Prerequisites
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;go 1.18&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="detail"&gt;Detail
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Parse a flag with the &lt;a class="link" href="https://pkg.go.dev/flag" target="_blank" rel="noopener"
 &gt;flag&lt;/a&gt; package&lt;/li&gt;
&lt;li&gt;Read a YAML file with the &lt;a class="link" href="https://pkg.go.dev/os" target="_blank" rel="noopener"
 &gt;os&lt;/a&gt; package&lt;/li&gt;
&lt;li&gt;Convert YAML values into a Go struct with the &lt;a class="link" href="https://pkg.go.dev/gopkg.in/yaml.v2" target="_blank" rel="noopener"
 &gt;yaml&lt;/a&gt; package&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="parse-a-flag"&gt;Parse a flag
&lt;/h3&gt;&lt;p&gt;Use &lt;a class="link" href="https://pkg.go.dev/flag" target="_blank" rel="noopener"
 &gt;flag&lt;/a&gt; package to parse command line flags.&lt;br&gt;
In this case, the number of flags must be 1 and no arg is allowed.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;yamlFile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StringVar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;yamlFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;yaml-file&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;path to the YAML file&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NFlag&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NArg&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;you must give one flag and no arg: #(flags)=%v, #(args)=%v\n&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NFlag&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NArg&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;yamlFile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;you must specify yaml file\n&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="read-a-file"&gt;Read a file
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://pkg.go.dev/os#ReadFile" target="_blank" rel="noopener"
 &gt;os.Readfile&lt;/a&gt; can open a file to read.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// yamlFile: string&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;yamlFile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;ERROR in reading file: %v\n&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="convert-yaml-values-into-a-go-struct"&gt;Convert YAML values into a Go struct
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://pkg.go.dev/gopkg.in/yaml.v2#Unmarshal" target="_blank" rel="noopener"
 &gt;yaml&lt;/a&gt; package converts YAML values into a Go struct.&lt;br&gt;
In this case, assume the following YAML and define a struct representing values.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;members&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;John Doe&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;privileged&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;languages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;language&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Java&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;years&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;language&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Go&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;years&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Jane Doe&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;privileged&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Some fields can be omitted if there is no need to read it.&lt;br&gt;
&lt;code&gt;map[interface{}]interface{}&lt;/code&gt; can be used instead of the struct, but I do not like that way.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// data: []byte&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Members&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;`yaml:&amp;#34;name&amp;#34;`&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Age&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;`yaml:&amp;#34;age&amp;#34;`&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Privileged&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;`yaml:&amp;#34;privileged&amp;#34;`&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Languages&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Language&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;`yaml:&amp;#34;language&amp;#34;`&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Years&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;`yaml:&amp;#34;years&amp;#34;`&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;`yaml:&amp;#34;languages&amp;#34;`&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;`yaml:&amp;#34;members&amp;#34;`&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;yaml&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Unmarshal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;ERROR in parsing YAML: %v\n&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then the values can be accessed by the field name of the struct representing the key name.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;name: %v\n&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Members&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;(The following is the same content in Japanese.)&lt;/p&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;コマンドラインで指定された&lt;code&gt;YAML&lt;/code&gt;ファイルを開いて要素を取り出すまでの&lt;code&gt;Go&lt;/code&gt;コードは以下のように書けそう&lt;br&gt;
(以下コピペ用)&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/afd285ac5d7d61a61d4f70e60816e9ad.js"&gt;&lt;/script&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat members.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;members:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- name: &lt;span class="s2"&gt;&amp;#34;John Doe&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; age: &lt;span class="m"&gt;20&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; privileged: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; languages:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - language: &lt;span class="s2"&gt;&amp;#34;Java&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; years: &lt;span class="m"&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - language: &lt;span class="s2"&gt;&amp;#34;Go&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; years: &lt;span class="m"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- name: &lt;span class="s2"&gt;&amp;#34;Jane Doe&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; age: &lt;span class="m"&gt;30&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; privileged: &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go run main.go -yaml-file members.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;name: John Doe
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;age: &lt;span class="m"&gt;20&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;privileged: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;language 0: Java &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt; year&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;language 1: Go &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; year&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;name: Jane Doe
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;age: &lt;span class="m"&gt;30&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;privileged: true&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;go 1.18&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="詳細"&gt;詳細
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;flagで指定されたYAMLファイル名をコード内で使用する&lt;/li&gt;
&lt;li&gt;指定されたファイルを開く&lt;/li&gt;
&lt;li&gt;ファイルの内容を構造体にパースしてkeyで値を取り出せる状態にする&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="flagの処理"&gt;flagの処理
&lt;/h3&gt;&lt;p&gt;まずは標準の&lt;a class="link" href="https://pkg.go.dev/flag" target="_blank" rel="noopener"
 &gt;flag&lt;/a&gt;パッケージを使い、実行時に対象のファイル名を指定できるようにする。 &lt;br&gt;
4行目以降でflag数と入力値のバリデーションをかけてみたが、特に気にならなければ消してもいい。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;yamlFile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StringVar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;yamlFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;yaml-file&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;path to the YAML file&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NFlag&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NArg&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;you must give one flag and no arg: #(flags)=%v, #(args)=%v\n&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NFlag&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NArg&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;yamlFile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;you must specify yaml file\n&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="ファイルの読み込み"&gt;ファイルの読み込み
&lt;/h3&gt;&lt;p&gt;次に&lt;a class="link" href="https://pkg.go.dev/os" target="_blank" rel="noopener"
 &gt;os&lt;/a&gt;パッケージで対象のファイルを開く。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// yamlFile: string&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;yamlFile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;ERROR in reading file: %v\n&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="yamlにパース"&gt;YAMLにパース
&lt;/h3&gt;&lt;p&gt;最後に&lt;a class="link" href="https://github.com/go-yaml/yaml" target="_blank" rel="noopener"
 &gt;yaml&lt;/a&gt;パッケージで対象のyamlを構造体にパースする。&lt;/p&gt;
&lt;p&gt;今回は下記のような&lt;code&gt;YAML&lt;/code&gt;を想定し、&lt;br&gt;
その構造をパース用の構造体に定義する。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;members&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;John Doe&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;privileged&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;languages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;language&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Java&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;years&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;language&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Go&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;years&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Jane Doe&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;privileged&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;パースが不要な要素については定義しなくても問題ない。&lt;br&gt;
また、構造体の代わりに&lt;code&gt;map[interface{}]interface{}&lt;/code&gt;を使う方法もあるが、&lt;br&gt;
要素を呼び出すたびに型をアサーションして使うのはあまり好きではない。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// data: []byte&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Members&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;`yaml:&amp;#34;name&amp;#34;`&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Age&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;`yaml:&amp;#34;age&amp;#34;`&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Privileged&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;`yaml:&amp;#34;privileged&amp;#34;`&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Languages&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Language&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;`yaml:&amp;#34;language&amp;#34;`&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Years&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;`yaml:&amp;#34;years&amp;#34;`&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;`yaml:&amp;#34;languages&amp;#34;`&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;`yaml:&amp;#34;members&amp;#34;`&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;yaml&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Unmarshal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;ERROR in parsing YAML: %v\n&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;構造体にパースできたら、&lt;br&gt;
あとはフィールド名を指定して要素にアクセスができる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;name: %v\n&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Members&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;久しぶりに&lt;code&gt;Go&lt;/code&gt;に触ったらいろいろ消耗してしまったので自分のコピペ用に書いてみた。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;YAML&lt;/code&gt;を設定ファイルとして読み込むものを書く機会が多いので、出番があるといいな&amp;hellip;&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="ソファの裏から出てくるねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-04-25-read-yaml-file-golang/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2022-04-25-read-yaml-file-golang/sotochan_hu_4b734dfd634067bc.jpeg 800w, https://blog.uzimihsr.com/post/2022-04-25-read-yaml-file-golang/sotochan_hu_3bd51998a5fb00d4.jpeg 1600w, https://blog.uzimihsr.com/post/2022-04-25-read-yaml-file-golang/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>Read and update Kubernetes YAML with yq(v4)</title><link>https://blog.uzimihsr.com/post/2022-04-14-yq-v4-kubernetes-yaml/</link><pubDate>Thu, 14 Apr 2022 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2022-04-14-yq-v4-kubernetes-yaml/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2022-04-14-yq-v4-kubernetes-yaml/sotochan.jpeg" alt="Featured image of post Read and update Kubernetes YAML with yq(v4)" /&gt;&lt;p&gt;&lt;a class="link" href="#%e3%81%be%e3%81%a8%e3%82%81" &gt;日本語版/Japanese&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="summary"&gt;Summary
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://github.com/mikefarah/yq/" target="_blank" rel="noopener"
 &gt;yq&lt;/a&gt; is very useful for reading or updating Kubernetes YAML.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;## read the value(key=spec.containers[0].image) from YAML(pod.yaml)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# specify the file&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;yq &lt;span class="s1"&gt;&amp;#39;.spec.containers[0].image&amp;#39;&lt;/span&gt; pod.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# pipe from stdout&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat pod.yaml &lt;span class="p"&gt;|&lt;/span&gt; yq &lt;span class="s1"&gt;&amp;#39;.spec.containers[0].image&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;## update the YAML value(key=spec.containers[0].image) to &amp;#34;nginx:1.20.2&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# stdout&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat pod.yaml &lt;span class="p"&gt;|&lt;/span&gt; yq &lt;span class="s1"&gt;&amp;#39;.spec.containers[0].image = &amp;#34;nginx:1.20.2&amp;#34;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# update the file&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;yq -i &lt;span class="s1"&gt;&amp;#39;.spec.containers[0].image = &amp;#34;nginx:1.20.2&amp;#34;&amp;#39;&lt;/span&gt; pod.yaml&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="prerequisites"&gt;Prerequisites
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mikefarah/yq/" target="_blank" rel="noopener"
 &gt;yq&lt;/a&gt; version 4.24.2&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="read-and-update-kubernetes-yaml-with-yq"&gt;Read and Update Kubernetes YAML with yq
&lt;/h2&gt;&lt;p&gt;Let&amp;rsquo;s read and update the &lt;strong&gt;pod.yaml&lt;/strong&gt; with yq.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/3717717a866f8373755a2384426c89c4.js"&gt;&lt;/script&gt;
&lt;h3 id="read"&gt;Read
&lt;/h3&gt;&lt;p&gt;We can extract the value by specifying the key.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# extract the image name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ yq &lt;span class="s1"&gt;&amp;#39;.spec.containers[0].image&amp;#39;&lt;/span&gt; pod.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nginx:latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# extract the tag&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ yq &lt;span class="s1"&gt;&amp;#39;.spec.containers[0].image&amp;#39;&lt;/span&gt; pod.yaml &lt;span class="p"&gt;|&lt;/span&gt; grep -o &lt;span class="s1"&gt;&amp;#39;^[^:]\+&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ yq &lt;span class="s1"&gt;&amp;#39;.spec.containers[0].image&amp;#39;&lt;/span&gt; pod.yaml &lt;span class="p"&gt;|&lt;/span&gt; grep -o &lt;span class="s1"&gt;&amp;#39;[^:]\+$&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# pipe from stdout&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat pod.yaml &lt;span class="p"&gt;|&lt;/span&gt; yq &lt;span class="s1"&gt;&amp;#39;.spec.containers[0].image&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nginx:latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat pod.yaml &lt;span class="p"&gt;|&lt;/span&gt; yq &lt;span class="s1"&gt;&amp;#39;.spec.containers[0].image&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; grep -o &lt;span class="s1"&gt;&amp;#39;^[^:]\+&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat pod.yaml &lt;span class="p"&gt;|&lt;/span&gt; yq &lt;span class="s1"&gt;&amp;#39;.spec.containers[0].image&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; grep -o &lt;span class="s1"&gt;&amp;#39;[^:]\+$&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;latest&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="update"&gt;Update
&lt;/h3&gt;&lt;p&gt;You can change the value of the specified key.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# change the image name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat pod.yaml &lt;span class="p"&gt;|&lt;/span&gt; yq &lt;span class="s1"&gt;&amp;#39;.spec.containers[0].image = &amp;#34;nginx:1.20.2&amp;#34;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apiVersion: v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kind: Pod
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: nginx-pod
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; containers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - name: nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; image: nginx:1.20.2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# update the file directly&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ yq -i &lt;span class="s1"&gt;&amp;#39;.spec.containers[0].image = &amp;#34;nginx:1.20.2&amp;#34;&amp;#39;&lt;/span&gt; pod.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat pod.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apiVersion: v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kind: Pod
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: nginx-pod
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; containers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - name: nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; image: nginx:1.20.2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;(The following is the same content in Japanese.)&lt;/p&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;yq&lt;/code&gt;はv4でもやっぱり便利。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;## YAML(pod.yaml)の値(key=spec.containers[0].image)を抽出&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ファイル名を指定するパターン&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;yq &lt;span class="s1"&gt;&amp;#39;.spec.containers[0].image&amp;#39;&lt;/span&gt; pod.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 標準出力からパイプで受けるパターン&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat pod.yaml &lt;span class="p"&gt;|&lt;/span&gt; yq &lt;span class="s1"&gt;&amp;#39;.spec.containers[0].image&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;## YAML(pod.yaml)の値(key=spec.containers[0].image)を&amp;#34;nginx:1.20.2&amp;#34;で上書き&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 標準出力に出すだけ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat pod.yaml &lt;span class="p"&gt;|&lt;/span&gt; yq &lt;span class="s1"&gt;&amp;#39;.spec.containers[0].image = &amp;#34;nginx:1.20.2&amp;#34;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ファイルの値を直接更新する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;yq -i &lt;span class="s1"&gt;&amp;#39;.spec.containers[0].image = &amp;#34;nginx:1.20.2&amp;#34;&amp;#39;&lt;/span&gt; pod.yaml&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mikefarah/yq/" target="_blank" rel="noopener"
 &gt;yq&lt;/a&gt; version 4.24.2
&lt;ul&gt;
&lt;li&gt;v3については&lt;a class="link" href="https://uzimihsr.github.io/post/2020-07-06-yq-kubernetes-yaml/" target="_blank" rel="noopener"
 &gt;過去記事&lt;/a&gt;を参照&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="yqでkubernetes-yamlをいじる"&gt;yqでKubernetes YAMLをいじる
&lt;/h2&gt;&lt;p&gt;こんな感じの &lt;strong&gt;pod.yaml&lt;/strong&gt; を&lt;code&gt;yq&lt;/code&gt;でいじる。&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/3717717a866f8373755a2384426c89c4.js"&gt;&lt;/script&gt;
&lt;h3 id="読む"&gt;読む
&lt;/h3&gt;&lt;p&gt;keyを指定して特定の要素を取り出す。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# image名を抜き出す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ yq &lt;span class="s1"&gt;&amp;#39;.spec.containers[0].image&amp;#39;&lt;/span&gt; pod.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nginx:latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# grepと合わせてtagを取り出す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ yq &lt;span class="s1"&gt;&amp;#39;.spec.containers[0].image&amp;#39;&lt;/span&gt; pod.yaml &lt;span class="p"&gt;|&lt;/span&gt; grep -o &lt;span class="s1"&gt;&amp;#39;^[^:]\+&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ yq &lt;span class="s1"&gt;&amp;#39;.spec.containers[0].image&amp;#39;&lt;/span&gt; pod.yaml &lt;span class="p"&gt;|&lt;/span&gt; grep -o &lt;span class="s1"&gt;&amp;#39;[^:]\+$&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# パイプで渡すパターン&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat pod.yaml &lt;span class="p"&gt;|&lt;/span&gt; yq &lt;span class="s1"&gt;&amp;#39;.spec.containers[0].image&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nginx:latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat pod.yaml &lt;span class="p"&gt;|&lt;/span&gt; yq &lt;span class="s1"&gt;&amp;#39;.spec.containers[0].image&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; grep -o &lt;span class="s1"&gt;&amp;#39;^[^:]\+&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat pod.yaml &lt;span class="p"&gt;|&lt;/span&gt; yq &lt;span class="s1"&gt;&amp;#39;.spec.containers[0].image&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; grep -o &lt;span class="s1"&gt;&amp;#39;[^:]\+$&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;latest&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="更新する"&gt;更新する
&lt;/h3&gt;&lt;p&gt;指定したkeyの値を上書きする。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# image名を更新する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat pod.yaml &lt;span class="p"&gt;|&lt;/span&gt; yq &lt;span class="s1"&gt;&amp;#39;.spec.containers[0].image = &amp;#34;nginx:1.20.2&amp;#34;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apiVersion: v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kind: Pod
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: nginx-pod
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; containers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - name: nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; image: nginx:1.20.2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ファイルを直接上書きする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ yq -i &lt;span class="s1"&gt;&amp;#39;.spec.containers[0].image = &amp;#34;nginx:1.20.2&amp;#34;&amp;#39;&lt;/span&gt; pod.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat pod.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apiVersion: v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kind: Pod
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: nginx-pod
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; containers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - name: nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; image: nginx:1.20.2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;yqのv3→v4へのアップデートでかなり大規模な変更があり、&lt;br&gt;
&lt;a class="link" href="https://uzimihsr.github.io/post/2020-07-06-yq-kubernetes-yaml/" target="_blank" rel="noopener"
 &gt;過去に書いた記事&lt;/a&gt;の内容がそのままだと使えなくなってしまっていたので急いで書いてみた。&lt;br&gt;
今までずっとv3を使っていたので、v4になった途端動かなくてびっくりした&amp;hellip;&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="秘密基地で爆睡するねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-04-14-yq-v4-kubernetes-yaml/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2022-04-14-yq-v4-kubernetes-yaml/sotochan_hu_46e6061f1debb844.jpeg 800w, https://blog.uzimihsr.com/post/2022-04-14-yq-v4-kubernetes-yaml/sotochan_hu_cc84d3ae5d0ef082.jpeg 1600w, https://blog.uzimihsr.com/post/2022-04-14-yq-v4-kubernetes-yaml/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>3月のそとちゃん(2022)</title><link>https://blog.uzimihsr.com/post/2022-04-07-sotochan/</link><pubDate>Thu, 07 Apr 2022 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2022-04-07-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2022-04-07-sotochan/sotochan.jpeg" alt="Featured image of post 3月のそとちゃん(2022)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%b2%e3%81%a3%e3%81%8f%e3%82%8a%e8%bf%94%e3%82%8b" &gt;ひっくり返る&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e7%97%85%e9%99%a2" &gt;病院&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%a4%e3%82%81%e3%81%a8%e3%81%8e%e3%83%99%e3%83%83%e3%83%89" &gt;つめとぎベッド&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="ひっくり返る"&gt;ひっくり返る
&lt;/h3&gt;&lt;p&gt;そとちゃんはいつもごろごろしている。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ごろごろ &lt;a href="https://t.co/QqaIjjgXzv"&gt;pic.twitter.com/QqaIjjgXzv&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1501711637862318080?ref_src=twsrc%5Etfw"&gt;March 10, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;床でもベッドでも俺の上でも、機嫌がいいときは常にごろごろ。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ごきげん &lt;a href="https://t.co/SVYYmPLxZE"&gt;pic.twitter.com/SVYYmPLxZE&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1509544427895029761?ref_src=twsrc%5Etfw"&gt;March 31, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;鼻と口の⅄がひっくり返ってるところがたまらなくかわいい。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="und" dir="ltr"&gt;Y &lt;a href="https://t.co/4tXzJK0Acc"&gt;pic.twitter.com/4tXzJK0Acc&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1504104554086170628?ref_src=twsrc%5Etfw"&gt;March 16, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;&amp;hellip;たまにひっくり返りすぎてちょっと怖い顔になってるのもおもしろい。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="zxx" dir="ltr"&gt;？ &lt;a href="https://t.co/NxjWvGcW1w"&gt;pic.twitter.com/NxjWvGcW1w&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1500432609540964354?ref_src=twsrc%5Etfw"&gt;March 6, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;h3 id="病院"&gt;病院
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2021-12-31-sotochan/" target="_blank" rel="noopener"
 &gt;12月に受けた手術&lt;/a&gt;のときに血液検査の数値が少し怪しかったそとちゃん。&lt;/p&gt;
&lt;p&gt;予定通り3ヶ月経ったので再検査にいった。&lt;/p&gt;
&lt;p&gt;以前はお出かけの気配を察して自分から進んでキャリーに入ってたのに、&lt;br&gt;
手術がよっぽど嫌だったのか今回はおもちゃで釣らないと入ってくれなかった。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;病院いく &lt;a href="https://t.co/nrApEsqhtX"&gt;pic.twitter.com/nrApEsqhtX&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1507506503158476802?ref_src=twsrc%5Etfw"&gt;March 25, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;病院の待合室でたまたま向かいに別のねこちゃんが居て、&lt;br&gt;
キャリー越しにいっぱい話しかけてくれた(ような気がした)んだけどそとちゃんはガン無視。&lt;br&gt;
他のねこには興味がないのかもしれない。&lt;br&gt;
(普段ねこが出てるテレビ番組とか動画を見せてもそんなに食いつかない)&lt;/p&gt;
&lt;p&gt;今回は前回までと違うベテランの先生で、&lt;br&gt;
いつもは診察室でやりたい放題のそとちゃんがあっさり捕まって検査に連れて行かれたのがちょっとおもしろかった。&lt;/p&gt;
&lt;p&gt;血液検査の結果は良好。&lt;br&gt;
12月は1.7mg/dLだったクレアチニンの値が今回は1.2mg/dLまで下がっていた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="下がった" class="gallery-image" data-flex-basis="681px" data-flex-grow="283" height="1092" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-04-07-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2022-04-07-sotochan/sotochan01_hu_a6d1e6784b69402d.jpeg 800w, https://blog.uzimihsr.com/post/2022-04-07-sotochan/sotochan01_hu_b44e0452a541c13e.jpeg 1600w, https://blog.uzimihsr.com/post/2022-04-07-sotochan/sotochan01_hu_53486678c7f7250e.jpeg 2400w, https://blog.uzimihsr.com/post/2022-04-07-sotochan/sotochan01.jpeg 3101w" width="3101"&gt;&lt;/p&gt;
&lt;p&gt;クレアチニンの値には元々波があって、前回のようにたまに高い値が出ることがあるらしい。&lt;br&gt;
本当に腎臓が悪くなっていると慢性的に高い値で推移するようになるので、&lt;br&gt;
今回低い値がでたのは良い傾向ということだった。&lt;/p&gt;
&lt;p&gt;その他聴診や触診も問題なく、追加の通院や検査も不要になって安心した。&lt;br&gt;
割と健康児なので年1回の健康診断で十分らしい。🎉&lt;/p&gt;
&lt;p&gt;ちなみに、血液検査の結果で頭がいっぱいで最近のごはんの量について相談するのを忘れてしまった&amp;hellip;&lt;br&gt;
体重が3.98kgと少し軽めだったので、おやつの量をちょっと増やすくらいはいいのかも？&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;病院がんばった &lt;a href="https://t.co/sr6dVRJG70"&gt;pic.twitter.com/sr6dVRJG70&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1507532446623211520?ref_src=twsrc%5Etfw"&gt;March 26, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;h3 id="つめとぎベッド"&gt;つめとぎベッド
&lt;/h3&gt;&lt;p&gt;そとちゃんのつめとぎ(俺のソファ)がボロボロで流石に壊れそうなので、&lt;br&gt;
新しい&lt;a class="link" href="https://www.necoichi.co.jp/Products/detail/id=7749" target="_blank" rel="noopener"
 &gt;つめとぎベッド&lt;/a&gt;を買ってみた。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;新しい爪とぎを献上 &lt;a href="https://t.co/1tkteN4kDq"&gt;pic.twitter.com/1tkteN4kDq&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1507720197377241089?ref_src=twsrc%5Etfw"&gt;March 26, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;が、やはり使い慣れたつめとぎが良いらしく&amp;hellip;&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;バリバリ &lt;a href="https://t.co/b7meXIxq0F"&gt;pic.twitter.com/b7meXIxq0F&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1508083628622102531?ref_src=twsrc%5Etfw"&gt;March 27, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;結局ソファは破壊されるもよう。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;新しく買ったつめとぎガン無視で笑っちゃう &lt;a href="https://t.co/mqYvrSjGSB"&gt;pic.twitter.com/mqYvrSjGSB&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1508664798711808008?ref_src=twsrc%5Etfw"&gt;March 29, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;ベッドということは理解しているみたいで、&lt;br&gt;
一応乗ったり寝転がったりはするんだけどそこからなかなかつめとぎに発展しない。&lt;br&gt;
せっかく買ったのに&amp;hellip;😭&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;乗るけど爪とぎはしない &lt;a href="https://t.co/r05aU3njoR"&gt;pic.twitter.com/r05aU3njoR&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1508410494604156933?ref_src=twsrc%5Etfw"&gt;March 28, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;&lt;img alt="とてもきれいなつめとぎ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-04-07-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2022-04-07-sotochan/sotochan02_hu_4238c5565c334eaf.jpeg 800w, https://blog.uzimihsr.com/post/2022-04-07-sotochan/sotochan02_hu_36f2ec598aea6a4a.jpeg 1600w, https://blog.uzimihsr.com/post/2022-04-07-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;3月もそとちゃんは元気だった。&lt;br&gt;
検査の結果も問題なしで、本当に手がかからなくて助かる。&lt;/p&gt;
&lt;p&gt;こんなに一緒に暮らしやすい子は他に居ないんじゃないか??(親バカ)&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="キメ顔" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-04-07-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2022-04-07-sotochan/sotochan_hu_bd6d78932d57ef9a.jpeg 800w, https://blog.uzimihsr.com/post/2022-04-07-sotochan/sotochan_hu_19634a77607eec71.jpeg 1600w, https://blog.uzimihsr.com/post/2022-04-07-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>2月のそとちゃん(2022)</title><link>https://blog.uzimihsr.com/post/2022-03-10-sotochan/</link><pubDate>Thu, 10 Mar 2022 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2022-03-10-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2022-03-10-sotochan/sotochan.jpeg" alt="Featured image of post 2月のそとちゃん(2022)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%81%e3%81%a3%e3%81%a1%e3%82%83%e9%a3%9f%e3%81%b9%e3%82%8b" &gt;めっちゃ食べる&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e6%af%9b%e5%b8%83" &gt;毛布&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="めっちゃ食べる"&gt;めっちゃ食べる
&lt;/h3&gt;&lt;p&gt;そとちゃんの食欲がすごい。&lt;/p&gt;
&lt;p&gt;今までも晩ごはんのウェットフード(猫缶パウチ)は残さずきれいに食べるえらいねこだったんだけど、&lt;br&gt;
最近はカリカリもきれいに平らげるようになった。&lt;/p&gt;
&lt;p&gt;&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;俺が居てもカリカリ食べるようになった&lt;br&gt;えらい &lt;a href="https://t.co/yKkktcpss7"&gt;pic.twitter.com/yKkktcpss7&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1494160521805045760?ref_src=twsrc%5Etfw"&gt;February 17, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


そとちゃんの一日の食事はだいたいこんな感じ。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;時刻&lt;/th&gt;
 &lt;th&gt;ごはん&lt;/th&gt;
 &lt;th&gt;エネルギー(kcal)&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;8:00 AM&lt;/td&gt;
 &lt;td&gt;&lt;a class="link" href="https://www.royalcanin.com/jp/cats/products/vet-products/feline-gastrointestinal-high-energy-dry-cat-food" target="_blank" rel="noopener"
 &gt;療法食カリカリ&lt;/a&gt;約10g&lt;br&gt;(&lt;a class="link" href="https://petelect.jp/lp/karikarimachinesp/" target="_blank" rel="noopener"
 &gt;カリカリマシーン&lt;/a&gt;で出る)&lt;/td&gt;
 &lt;td&gt;40&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;13:00 PM&lt;/td&gt;
 &lt;td&gt;療法食カリカリ約10g&lt;br&gt;(カリカリマシーン)&lt;/td&gt;
 &lt;td&gt;40&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;18:00 PM&lt;/td&gt;
 &lt;td&gt;&lt;a class="link" href="https://www.aixia.jp/product/detail_4571104712992" target="_blank" rel="noopener"
 &gt;黒缶パウチ&lt;/a&gt;+かつお節トッピング&lt;/td&gt;
 &lt;td&gt;56+15&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;不定期(主に就寝前)&lt;/td&gt;
 &lt;td&gt;おやつの&lt;a class="link" href="https://www.lion-pet.jp/product/petkiss/kinou_cat_niboshi.htm" target="_blank" rel="noopener"
 &gt;にぼし&lt;/a&gt;+&lt;a class="link" href="https://www.lion-pet.jp/product/petkiss/kinou_cat_kani.htm" target="_blank" rel="noopener"
 &gt;かにかま&lt;/a&gt;&lt;/td&gt;
 &lt;td&gt;5+7&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;合計&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;td&gt;163&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;体重約4.0kgのそとちゃんの場合&lt;a class="link" href="https://www.aixia.jp/gohanjiten/%E3%82%82%E3%81%86%E8%BF%B7%E3%82%8F%E3%81%AA%E3%81%84%E3%82%AD%E3%83%A3%E3%83%83%E3%83%88%E3%83%95%E3%83%BC%E3%83%89%E3%81%AE%E9%81%B8%E3%81%B3%E6%96%B9-test/" target="_blank" rel="noopener"
 &gt;1日の摂取カロリーは132~190kcal&lt;/a&gt;が適切らしいが、&lt;br&gt;
そとちゃんはちょっと少食で、今まではこの量でもお昼のカリカリを残すことがあった。&lt;br&gt;
(味にうるさいのもあるが&amp;hellip;)&lt;/p&gt;
&lt;p&gt;しかし手術後に元気が倍増したそとちゃんはごはんをもりもり食べる。&lt;br&gt;
以前よりも運動量が増えたせいでお腹が空いているのか、カリカリもほぼ毎回完食。&lt;br&gt;
カリカリマシーンの音でそとちゃんが駆け寄ってくるなんて以前は考えられなかった光景で、初めて見たときはかなり驚いた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="食べてるときは真剣" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-03-10-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2022-03-10-sotochan/sotochan01_hu_37c66eb1d430f19d.jpeg 800w, https://blog.uzimihsr.com/post/2022-03-10-sotochan/sotochan01_hu_5a88a3cfbf98678e.jpeg 1600w, https://blog.uzimihsr.com/post/2022-03-10-sotochan/sotochan01_hu_64fb12f3cc21c49.jpeg 2400w, https://blog.uzimihsr.com/post/2022-03-10-sotochan/sotochan01.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;少し味覚が大人になったのかもしれないが、理由は何であれごはんをよく食べるようになってとてもえらい。&lt;br&gt;
最近はごはんをおねだりすることも増えたので(めっちゃもじもじしてかわいい)、&lt;br&gt;
あげすぎないように注意したい。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;正解 &lt;a href="https://t.co/7ctanyd0Yb"&gt;pic.twitter.com/7ctanyd0Yb&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1494963630122897411?ref_src=twsrc%5Etfw"&gt;February 19, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;h3 id="毛布"&gt;毛布
&lt;/h3&gt;&lt;p&gt;俺のベッドに敷いてる毛布が好き。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;毛布食べないで欲しい &lt;a href="https://t.co/2ZDquN2JYy"&gt;pic.twitter.com/2ZDquN2JYy&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1488317105925951488?ref_src=twsrc%5Etfw"&gt;February 1, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;毎朝暴れて疲れたあとはだいたい毛布の上でごろごろしている。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;しっぽ自分で踏んでる &lt;a href="https://t.co/Ek1z3OwLcM"&gt;pic.twitter.com/Ek1z3OwLcM&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1490490695362174976?ref_src=twsrc%5Etfw"&gt;February 7, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;お昼寝のあとから夕方もたまにごろごろしている。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ぐにゃぐにゃしてる &lt;a href="https://t.co/wJsOFQHVRY"&gt;pic.twitter.com/wJsOFQHVRY&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1491341773226246149?ref_src=twsrc%5Etfw"&gt;February 9, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;だいぶ昔にド○キで適当に買った安物なんだけどなにがそんなに良いのだろうか&amp;hellip;&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;スフィンクス &lt;a href="https://t.co/4PJWM0HOlt"&gt;pic.twitter.com/4PJWM0HOlt&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1496647746782380032?ref_src=twsrc%5Etfw"&gt;February 24, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;ごろごろと遊びは毛布の上でするんだけど、そこで寝ることはめったに無い。&lt;br&gt;
そとちゃんの中で寝る場所はキャットタワーと本棚の上だけと決まっているように見える。&lt;br&gt;
むずかしい。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;うおー &lt;a href="https://t.co/0fiae2qbGd"&gt;pic.twitter.com/0fiae2qbGd&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1493784670873731081?ref_src=twsrc%5Etfw"&gt;February 16, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;ちなみに毛布だけじゃなくて布団も上に乗るのだけは好き。&lt;br&gt;
俺が寝てると上に乗ってくる。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;起きられません &lt;a href="https://t.co/90WkQLkVj3"&gt;pic.twitter.com/90WkQLkVj3&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1490134097616076801?ref_src=twsrc%5Etfw"&gt;February 6, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;が、ガードが固い？ので布団の中に入ってくることは絶対にない。&lt;br&gt;
たまに同衾チャレンジするんだけどすぐに抜け出してマウントポジションを取られる。&lt;br&gt;
とにかく布を上からかけられるのが嫌みたい。&lt;br&gt;
むずかしい&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="自分から乗ってきてイカ耳" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-03-10-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2022-03-10-sotochan/sotochan02_hu_6333119f1fe49552.jpeg 800w, https://blog.uzimihsr.com/post/2022-03-10-sotochan/sotochan02_hu_d8a6c0bca1ada2df.jpeg 1600w, https://blog.uzimihsr.com/post/2022-03-10-sotochan/sotochan02_hu_e9ef2e0131ea0aed.jpeg 2400w, https://blog.uzimihsr.com/post/2022-03-10-sotochan/sotochan02.jpeg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;そとちゃんが変わらず元気いっぱいで嬉しい。&lt;/p&gt;
&lt;p&gt;運動量が明らかに増えたのでごはんの量はちょっと増やしてもいいのかな&amp;hellip;?&lt;/p&gt;
&lt;p&gt;3月に定期検診で病院に行くので、先生とも相談したい。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="紐つきボールで遊ぶねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-03-10-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2022-03-10-sotochan/sotochan_hu_a5ab717bbf9526c4.jpeg 800w, https://blog.uzimihsr.com/post/2022-03-10-sotochan/sotochan_hu_34f21e1898f9a46f.jpeg 1600w, https://blog.uzimihsr.com/post/2022-03-10-sotochan/sotochan_hu_b8423bd2b466ded0.jpeg 2400w, https://blog.uzimihsr.com/post/2022-03-10-sotochan/sotochan.jpeg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>Run CentOS Stream 8 on VirtualBox(Intel Mac)</title><link>https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/</link><pubDate>Thu, 24 Feb 2022 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sotochan.jpg" alt="Featured image of post Run CentOS Stream 8 on VirtualBox(Intel Mac)" /&gt;&lt;h2 id="summary"&gt;Summary
&lt;/h2&gt;&lt;p&gt;This is my note on running CentOS Stream 8 via VirtualBox on MacOS.&lt;/p&gt;
&lt;h2 id="prerequisites"&gt;Prerequisites
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Big Sur 11.6.4
&lt;ul&gt;
&lt;li&gt;2.5GHz quad-core Intel Core i7&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;VirtualBox 6.1.32&lt;/li&gt;
&lt;li&gt;CentOS Stream release 8&lt;/li&gt;
&lt;li&gt;Linux version 4.18.0-365.el8.x86_64&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="what-i-did"&gt;What I did
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#install-virtualbox" &gt;Install VirtualBox&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#create-a-vm" &gt;Create a VM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#install-centos-stream-8" &gt;Install CentOS Stream 8&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#install-guest-additions" &gt;Install Guest Additions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="install-virtualbox"&gt;Install VirtualBox
&lt;/h3&gt;&lt;p&gt;Install the dmg for OS X hosts from &lt;a class="link" href="https://www.virtualbox.org/" target="_blank" rel="noopener"
 &gt;https://www.virtualbox.org/&lt;/a&gt; then run &lt;code&gt;VirtualBox.pkg&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Follow the instructions and VirtualBox will appear on &lt;code&gt;/Applications&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Run VirtualBox.pkg" class="gallery-image" data-flex-basis="349px" data-flex-grow="145" height="1098" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc01.png" srcset="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc01_hu_df61fad6e9685541.png 800w, https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc01.png 1598w" width="1598"&gt;&lt;/p&gt;
&lt;h3 id="create-a-vm"&gt;Create a VM
&lt;/h3&gt;&lt;p&gt;Start VirtualBox and click &amp;ldquo;New&amp;rdquo; to create a VM.&lt;/p&gt;
&lt;p&gt;My settings are as follows.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Give it 8GB memory size" class="gallery-image" data-flex-basis="301px" data-flex-grow="125" height="951" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc02.png" srcset="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc02_hu_da75db5b0158e4e.png 800w, https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc02.png 1196w" width="1196"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="The file size should be at least 16GB" class="gallery-image" data-flex-basis="301px" data-flex-grow="125" height="951" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc03.png" srcset="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc03_hu_efd2b66cd2b8a099.png 800w, https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc03.png 1196w" width="1196"&gt;&lt;/p&gt;
&lt;p&gt;The following is an overview of the VM I created.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Overview" class="gallery-image" data-flex-basis="301px" data-flex-grow="125" height="951" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc04.png" srcset="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc04_hu_6a08fe904c13b295.png 800w, https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc04.png 1196w" width="1196"&gt;&lt;/p&gt;
&lt;h3 id="install-centos-stream-8"&gt;Install CentOS Stream 8
&lt;/h3&gt;&lt;p&gt;In order to run CentOS on a VM, you have to download the image from &lt;a class="link" href="https://www.centos.org/download/" target="_blank" rel="noopener"
 &gt;https://www.centos.org/download/&lt;/a&gt; .&lt;br&gt;
I selected &lt;a class="link" href="http://isoredirect.centos.org/centos/8-stream/isos/x86_64/" target="_blank" rel="noopener"
 &gt;CentOS Stream 8(x86_64)&lt;/a&gt; for this time.&lt;/p&gt;
&lt;p&gt;Any mirror will do, but you need to download &lt;code&gt;CentOS-Stream-8-x86_64-YYYYMMDD-dvd1.iso&lt;/code&gt;.&lt;br&gt;
The file is about 10GB and took about 20 minutes or more to download.&lt;/p&gt;
&lt;p&gt;After downloading the .iso file, mount it in the VM on VirtualBox.&lt;br&gt;
In the &amp;ldquo;Storage&amp;rdquo; section, specify the downloaded .iso file for &amp;ldquo;IDE Secondary Device 0&amp;rdquo;.&lt;br&gt;
Click &amp;ldquo;Start&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Configuration" class="gallery-image" data-flex-basis="301px" data-flex-grow="125" height="951" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc05.png" srcset="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc05_hu_38a0c15f018df028.png 800w, https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc05.png 1196w" width="1196"&gt;&lt;/p&gt;
&lt;p&gt;A new window will appears. Select &amp;ldquo;Install CentOS Stream 8-stream&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="New window" class="gallery-image" data-flex-basis="284px" data-flex-grow="118" height="597" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc06.png" width="708"&gt;&lt;/p&gt;
&lt;p&gt;Select any language you use in the next window.&lt;br&gt;
When the following window appears, fix the options marked with a color.&lt;br&gt;
I configured &amp;ldquo;Installation Destination&amp;rdquo;, &amp;ldquo;Root Password&amp;rdquo;, and &amp;ldquo;User Creation&amp;rdquo; for this time.&lt;br&gt;
After configuration, click &amp;ldquo;Begin Installation&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Configuration" class="gallery-image" data-flex-basis="287px" data-flex-grow="119" height="761" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc07.png" srcset="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc07_hu_4a533e5982cd4f36.png 800w, https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc07.png 912w" width="912"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Installation Destination" class="gallery-image" data-flex-basis="287px" data-flex-grow="119" height="761" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc08.png" srcset="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc08_hu_b8a0cea95841e4b2.png 800w, https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc08.png 912w" width="912"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Root Password" class="gallery-image" data-flex-basis="287px" data-flex-grow="119" height="761" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc09.png" srcset="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc09_hu_b5dc77dba642f25c.png 800w, https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc09.png 912w" width="912"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="User Creation" class="gallery-image" data-flex-basis="287px" data-flex-grow="119" height="761" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc10.png" srcset="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc10_hu_2aa6fe3a528627c0.png 800w, https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc10.png 912w" width="912"&gt;&lt;/p&gt;
&lt;p&gt;It took about 10 minutes to install.&lt;br&gt;
After installation, click &amp;ldquo;Reboot System&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Installation finished" class="gallery-image" data-flex-basis="287px" data-flex-grow="119" height="761" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc11.png" srcset="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc11_hu_33f5193027ff8bc5.png 800w, https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc11.png 912w" width="912"&gt;&lt;/p&gt;
&lt;p&gt;A new window will appear.&lt;br&gt;
Accept the license and click &amp;ldquo;FINISH CONFIGURATION&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Accept the license" class="gallery-image" data-flex-basis="290px" data-flex-grow="121" height="717" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc12.png" srcset="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc12_hu_6ff7371843bc9437.png 800w, https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc12.png 868w" width="868"&gt;&lt;/p&gt;
&lt;p&gt;Some option windows will appear, but you can proceed as you wish.&lt;br&gt;
Finally you can see GNOME Desktop.🎉&lt;/p&gt;
&lt;p&gt;At first, update rpm packages.&lt;br&gt;
Launch a terminal from &amp;ldquo;Activities&amp;rdquo; in the upper-left corner then run &lt;code&gt;yum update&lt;/code&gt;.&lt;br&gt;
Oops! I met the error &amp;ldquo;Could not resolve host&amp;rdquo;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;uzimihsr@localhost ~&lt;span class="o"&gt;]&lt;/span&gt;$ sudo yum update -y
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;CentOS Stream &lt;span class="m"&gt;8&lt;/span&gt; - AppStream 0.0 B/s &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; B 00:00 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Errors during downloading metadata &lt;span class="k"&gt;for&lt;/span&gt; repository &lt;span class="s1"&gt;&amp;#39;appstream&amp;#39;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - Curl error &lt;span class="o"&gt;(&lt;/span&gt;6&lt;span class="o"&gt;)&lt;/span&gt;: Couldn&lt;span class="s1"&gt;&amp;#39;t resolve host name for http://mirrorlist.centos.org/?release=8-stream&amp;amp;arch=x86_64&amp;amp;repo=AppStream&amp;amp;infra=stock [Could not resolve host: mirrorlist.centos.org]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;Error: Failed to download metadata for repo &amp;#39;&lt;/span&gt;appstream&lt;span class="s1"&gt;&amp;#39;: Cannot prepare internal mirrorlist: Curl error (6): Couldn&amp;#39;&lt;/span&gt;t resolve host name &lt;span class="k"&gt;for&lt;/span&gt; http://mirrorlist.centos.org/?release&lt;span class="o"&gt;=&lt;/span&gt;8-stream&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;arch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;x86_64&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;repo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;AppStream&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;infra&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;stock &lt;span class="o"&gt;[&lt;/span&gt;Could not resolve host: mirrorlist.centos.org&lt;span class="o"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can see the status in the upper-right corner shows &amp;ldquo;Wired Off&amp;rdquo;.&lt;br&gt;
Go to &amp;ldquo;Wired Settings&amp;rdquo; &amp;gt; &amp;ldquo;⚙️&amp;rdquo; and enable &amp;ldquo;Connect automatically&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="“Wired Off”" class="gallery-image" data-flex-basis="287px" data-flex-grow="119" height="761" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc13.png" srcset="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc13_hu_95962751daa49608.png 800w, https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc13.png 912w" width="912"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Enable automatic connection" class="gallery-image" data-flex-basis="287px" data-flex-grow="119" height="761" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc14.png" srcset="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc14_hu_9ddc55f73aeb3dbf.png 800w, https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc14.png 912w" width="912"&gt;&lt;/p&gt;
&lt;p&gt;Now we can see &amp;ldquo;Wired Connected&amp;rdquo; in the status.&lt;br&gt;
Try &lt;code&gt;yum update&lt;/code&gt; again. It will succeed this time.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo yum update -y&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;img alt="“yum update” succeeded" class="gallery-image" data-flex-basis="287px" data-flex-grow="119" height="761" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc15.png" srcset="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc15_hu_bb95d28c28915d07.png 800w, https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc15.png 912w" width="912"&gt;&lt;/p&gt;
&lt;h3 id="install-guest-additions"&gt;Install Guest Additions
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Guest Additions&lt;/code&gt; make it easy to integrate VirtualBox VMs and the host OS.&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://www.virtualbox.org/manual/ch04.html" target="_blank" rel="noopener"
 &gt;https://www.virtualbox.org/manual/ch04.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Back to the host OS.&lt;br&gt;
Select &amp;ldquo;VirtualBox VM&amp;rdquo;→&amp;ldquo;Devices&amp;rdquo;→&amp;ldquo;Insert Guest Additions CD image&amp;hellip;&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Insert the CD image" class="gallery-image" data-flex-basis="283px" data-flex-grow="118" height="683" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc16.png" srcset="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc16_hu_c6621474ba877ed3.png 800w, https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc16.png 807w" width="807"&gt;&lt;/p&gt;
&lt;p&gt;You will see some windows with warnings about the software or a request for the administrator password, but proceed anyway.&lt;br&gt;
A new terminal will appear and the scripts will run on it.&lt;br&gt;
Aww. I met the error &amp;ldquo;Kernel headers not found for target kernel&amp;rdquo;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Verifying archive integrity... All good.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Uncompressing VirtualBox 6.1.32 Guest Additions &lt;span class="k"&gt;for&lt;/span&gt; Linux........
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions installer
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Copying additional installer modules ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Installing additional modules ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: Starting.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: Building the VirtualBox Guest Additions kernel 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;modules. This may take a &lt;span class="k"&gt;while&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: To build modules &lt;span class="k"&gt;for&lt;/span&gt; other installed kernels, run
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: /sbin/rcvboxadd quicksetup &amp;lt;version&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: or
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: /sbin/rcvboxadd quicksetup all
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: Kernel headers not found &lt;span class="k"&gt;for&lt;/span&gt; target kernel 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;4.18.0-365.el8.x86_64. Please install them and execute
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; /sbin/rcvboxadd setup
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;modprobe vboxguest failed
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;The log file /var/log/vboxadd-setup.log may contain further information.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Press Return to close this window...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Let&amp;rsquo;s install &lt;code&gt;kernel-headers&lt;/code&gt; and &lt;code&gt;kernel-devel&lt;/code&gt;, then reboot the OS.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo yum install -y kernel-headers kernel-devel
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo reboot&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After rebooting, open a terminal and execute the command shown in the previous message.&lt;br&gt;
Oh, no. I met the different error &amp;ldquo;Please install the gcc make perl packages from your distribution&amp;rdquo;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;uzimihsr@localhost ~&lt;span class="o"&gt;]&lt;/span&gt;$ sudo /sbin/rcvboxadd setup
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: Starting.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: Building the VirtualBox Guest Additions kernel 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;modules. This may take a &lt;span class="k"&gt;while&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: To build modules &lt;span class="k"&gt;for&lt;/span&gt; other installed kernels, run
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: /sbin/rcvboxadd quicksetup &amp;lt;version&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: or
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: /sbin/rcvboxadd quicksetup all
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: Building the modules &lt;span class="k"&gt;for&lt;/span&gt; kernel 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;4.18.0-365.el8.x86_64.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;This system is currently not &lt;span class="nb"&gt;set&lt;/span&gt; up to build kernel modules.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Please install the gcc make perl packages from your distribution.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ValueError: File context &lt;span class="k"&gt;for&lt;/span&gt; /opt/VBoxGuestAdditions-6.1.32/other/mount.vboxsf already defined
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;modprobe vboxguest failed
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;The log file /var/log/vboxadd-setup.log may contain further information.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Install them.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo yum install -y gcc make perl&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Execute the command again.&lt;br&gt;
The new error came out, but I couldn&amp;rsquo;t figure it out.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;uzimihsr@localhost ~&lt;span class="o"&gt;]&lt;/span&gt;$ sudo /sbin/rcvboxadd setup
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: Starting.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: Building the VirtualBox Guest Additions kernel 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;modules. This may take a &lt;span class="k"&gt;while&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: To build modules &lt;span class="k"&gt;for&lt;/span&gt; other installed kernels, run
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: /sbin/rcvboxadd quicksetup &amp;lt;version&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: or
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: /sbin/rcvboxadd quicksetup all
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: Building the modules &lt;span class="k"&gt;for&lt;/span&gt; kernel 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;4.18.0-365.el8.x86_64.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: Look at /var/log/vboxadd-setup.log to find out what 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;went wrong
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ValueError: File context &lt;span class="k"&gt;for&lt;/span&gt; /opt/VBoxGuestAdditions-6.1.32/other/mount.vboxsf already defined
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;modprobe vboxguest failed
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;The log file /var/log/vboxadd-setup.log may contain further information.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Let&amp;rsquo;s open the log file to see the details.&lt;br&gt;
It said &amp;ldquo;please install libelf-dev, libelf-devel or elfutils-libelf-devel&amp;rdquo;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;uzimihsr@localhost ~&lt;span class="o"&gt;]&lt;/span&gt;$ cat /var/log/vboxadd-setup.log
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Building the main Guest Additions 6.1.32 module &lt;span class="k"&gt;for&lt;/span&gt; kernel 4.18.0-365.el8.x86_64.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Error building the module. Build output follows.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;make &lt;span class="nv"&gt;V&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="nv"&gt;CONFIG_MODULE_SIG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;CONFIG_MODULE_SIG_ALL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; -C /lib/modules/4.18.0-365.el8.x86_64/build &lt;span class="nv"&gt;M&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/tmp/vbox.0 &lt;span class="nv"&gt;SRCROOT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/tmp/vbox.0 -j1 modules
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Makefile:985: *** &lt;span class="s2"&gt;&amp;#34;Cannot generate ORC metadata for CONFIG_UNWINDER_ORC=y, please install libelf-dev, libelf-devel or elfutils-libelf-devel&amp;#34;&lt;/span&gt;. Stop.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;make: *** &lt;span class="o"&gt;[&lt;/span&gt;/tmp/vbox.0/Makefile-footer.gmk:117: vboxguest&lt;span class="o"&gt;]&lt;/span&gt; Error &lt;span class="m"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;modprobe vboxguest failed&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I tried &lt;code&gt;yum search&lt;/code&gt; for the package, but there was only &lt;code&gt;elfutils-libelf-devel&lt;/code&gt;.&lt;br&gt;
Install it.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo yum install -y elfutils-libelf-devel
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Try again.&lt;br&gt;
Maybe it worked?&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;uzimihsr@localhost ~&lt;span class="o"&gt;]&lt;/span&gt;$ sudo /sbin/rcvboxadd setup
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: Starting.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: Building the VirtualBox Guest Additions kernel 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;modules. This may take a &lt;span class="k"&gt;while&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: To build modules &lt;span class="k"&gt;for&lt;/span&gt; other installed kernels, run
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: /sbin/rcvboxadd quicksetup &amp;lt;version&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: or
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: /sbin/rcvboxadd quicksetup all
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: Building the modules &lt;span class="k"&gt;for&lt;/span&gt; kernel 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;4.18.0-365.el8.x86_64.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: Look at /var/log/vboxadd-setup.log to find out what 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;went wrong
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ValueError: File context &lt;span class="k"&gt;for&lt;/span&gt; /opt/VBoxGuestAdditions-6.1.32/other/mount.vboxsf already defined
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: Running kernel modules will not be replaced &lt;span class="k"&gt;until&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;the system is restarted
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;uzimihsr@localhost ~&lt;span class="o"&gt;]&lt;/span&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Although there is another compilation error in the log file, but the exit code of the command was 0, and the message told me to reboot to let kernels load the modules.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;uzimihsr@localhost ~&lt;span class="o"&gt;]&lt;/span&gt;$ cat /var/log/vboxadd-setup.log
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Building the main Guest Additions 6.1.32 module &lt;span class="k"&gt;for&lt;/span&gt; kernel 4.18.0-365.el8.x86_64.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Building the shared folder support module.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Building the graphics driver module.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Error building the module. Build output follows.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;make &lt;span class="nv"&gt;V&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="nv"&gt;CONFIG_MODULE_SIG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;CONFIG_MODULE_SIG_ALL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; -C /lib/modules/4.18.0-365.el8.x86_64/build &lt;span class="nv"&gt;M&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/tmp/vbox.0 &lt;span class="nv"&gt;SRCROOT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/tmp/vbox.0 -j1 modules
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;test&lt;/span&gt; -e include/generated/autoconf.h -a -e include/config/auto.conf &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;	&lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;2&lt;span class="p"&gt;;&lt;/span&gt;							&lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; ERROR: Kernel configuration is invalid.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;		&lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; include/generated/autoconf.h or include/config/auto.conf are missing.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; Run &amp;#39;make oldconfig &amp;amp;&amp;amp; make prepare&amp;#39; on kernel src to fix it.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;	&lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;							&lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/bin/false&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mkdir -p /tmp/vbox.0/.tmp_versions &lt;span class="p"&gt;;&lt;/span&gt; rm -f /tmp/vbox.0/.tmp_versions/*
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;make -f ./scripts/Makefile.build &lt;span class="nv"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/tmp/vbox.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;(&lt;/span&gt;cat /dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; kernel//tmp/vbox.0/vboxvideo.ko&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &amp;gt; /tmp/vbox.0/modules.order
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; gcc -Wp,-MD,/tmp/vbox.0/.hgsmi_base.o.d -nostdinc -isystem /usr/lib/gcc/x86_64-redhat-linux/8/include -I./arch/x86/include -I./arch/x86/include/generated -I./include/drm-backport -I./include -I./arch/x86/include/uapi -I./arch/x86/include/generated/uapi -I./include/uapi -I./include/generated/uapi -include ./include/linux/kconfig.h -include ./include/linux/compiler_types.h -D__KERNEL__ -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -fshort-wchar -Werror-implicit-function-declaration -Wno-format-security -std&lt;span class="o"&gt;=&lt;/span&gt;gnu89 -fno-PIE -DCC_HAVE_ASM_GOTO -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -m64 -falign-jumps&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; -falign-loops&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; -mno-80387 -mno-fp-ret-in-387 -mpreferred-stack-boundary&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt; -mskip-rax-setup -mtune&lt;span class="o"&gt;=&lt;/span&gt;generic -mno-red-zone -mcmodel&lt;span class="o"&gt;=&lt;/span&gt;kernel -funit-at-a-time -DCONFIG_AS_CFI&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; -DCONFIG_AS_CFI_SIGNAL_FRAME&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; -DCONFIG_AS_CFI_SECTIONS&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; -DCONFIG_AS_SSSE3&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; -DCONFIG_AS_CRC32&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; -DCONFIG_AS_AVX&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; -DCONFIG_AS_AVX2&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; -DCONFIG_AS_AVX512&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; -DCONFIG_AS_SHA1_NI&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; -DCONFIG_AS_SHA256_NI&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; -DCONFIG_TPAUSE&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; -pipe -Wno-sign-compare -fno-asynchronous-unwind-tables -mindirect-branch&lt;span class="o"&gt;=&lt;/span&gt;thunk-extern -mindirect-branch-register -fno-jump-tables -fno-delete-null-pointer-checks -Wno-frame-address -Wno-format-truncation -Wno-format-overflow -Wno-int-in-bool-context -O2 --param&lt;span class="o"&gt;=&lt;/span&gt;allow-store-data-races&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; -Wframe-larger-than&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2048&lt;/span&gt; -fstack-protector-strong -Wno-unused-but-set-variable -Wno-unused-const-variable -g -gdwarf-4 -pg -mrecord-mcount -mfentry -DCC_USING_FENTRY -fno-inline-functions-called-once -Wdeclaration-after-statement -Wno-pointer-sign -Wno-stringop-truncation -Wno-maybe-uninitialized -fno-strict-overflow -fno-merge-all-constants -fmerge-constants -fno-stack-check -fconserve-stack -Werror&lt;span class="o"&gt;=&lt;/span&gt;implicit-int -Werror&lt;span class="o"&gt;=&lt;/span&gt;strict-prototypes -Werror&lt;span class="o"&gt;=&lt;/span&gt;date-time -Werror&lt;span class="o"&gt;=&lt;/span&gt;incompatible-pointer-types -Werror&lt;span class="o"&gt;=&lt;/span&gt;designated-init -fmacro-prefix-map&lt;span class="o"&gt;=&lt;/span&gt;./&lt;span class="o"&gt;=&lt;/span&gt; -Wno-packed-not-aligned -I./include -I/tmp/vbox.0/ -I./include/drm -D__KERNEL__ -DMODULE -DRT_WITHOUT_PRAGMA_ONCE -DRT_ARCH_AMD64 -DMODULE -DKBUILD_BASENAME&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#34;hgsmi_base&amp;#34;&amp;#39;&lt;/span&gt; -DKBUILD_MODNAME&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#34;vboxvideo&amp;#34;&amp;#39;&lt;/span&gt; -c -o /tmp/vbox.0/.tmp_hgsmi_base.o /tmp/vbox.0/hgsmi_base.c
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;In file included from /tmp/vbox.0/hgsmi_base.c:27:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/tmp/vbox.0/vbox_drv.h:175:11: fatal error: drm/ttm/ttm_memory.h: No such file or directory
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# include &amp;lt;drm/ttm/ttm_memory.h&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ^~~~~~~~~~~~~~~~~~~~~~
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;compilation terminated.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;make&lt;span class="o"&gt;[&lt;/span&gt;2&lt;span class="o"&gt;]&lt;/span&gt;: *** &lt;span class="o"&gt;[&lt;/span&gt;scripts/Makefile.build:316: /tmp/vbox.0/hgsmi_base.o&lt;span class="o"&gt;]&lt;/span&gt; Error &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;make&lt;span class="o"&gt;[&lt;/span&gt;1&lt;span class="o"&gt;]&lt;/span&gt;: *** &lt;span class="o"&gt;[&lt;/span&gt;Makefile:1577: _module_/tmp/vbox.0&lt;span class="o"&gt;]&lt;/span&gt; Error &lt;span class="m"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;make: *** &lt;span class="o"&gt;[&lt;/span&gt;/tmp/vbox.0/Makefile-footer.gmk:117: vboxvideo&lt;span class="o"&gt;]&lt;/span&gt; Error &lt;span class="m"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;uzimihsr@localhost ~&lt;span class="o"&gt;]&lt;/span&gt;$ sudo reboot&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now the mouse pointer moves seamlessly. Yeah.&lt;/p&gt;
&lt;p&gt;As a final touch, enable the shared clipboard.&lt;br&gt;
On VirtualBox, set &amp;ldquo;Settings&amp;rdquo; &amp;gt; &amp;ldquo;General&amp;rdquo; &amp;gt; &amp;ldquo;Advanced&amp;rdquo; &amp;gt; &amp;ldquo;Shared Clipboard&amp;rdquo; to &amp;ldquo;Bidirectional&amp;rdquo;. &lt;br&gt;
Now you can copy and paste across the VM(CentOS) and the host(macOS).&lt;/p&gt;
&lt;p&gt;&lt;img alt="Enable shared clipboard" class="gallery-image" data-flex-basis="310px" data-flex-grow="129" height="839" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc17.png" srcset="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc17_hu_a4fcdecd954baa75.png 800w, https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc17.png 1084w" width="1084"&gt;&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s it for this time.&lt;/p&gt;
&lt;p&gt;(The following is the same content in Japanese.)&lt;/p&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;久しぶりにVirtualBoxで遊ぼうとしたら動かなくなってたので最初から環境構築しなおした。&lt;br&gt;
いろいろ詰まったので手順を残しておく。&lt;/p&gt;
&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Big Sur 11.6.4
&lt;ul&gt;
&lt;li&gt;2.5GHz quad-core Intel Core i7&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;VirtualBox 6.1.32&lt;/li&gt;
&lt;li&gt;CentOS Stream release 8&lt;/li&gt;
&lt;li&gt;Linux version 4.18.0-365.el8.x86_64&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#virtualbox%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" &gt;VirtualBoxのインストール&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#vm%e3%81%ae%e4%bd%9c%e6%88%90" &gt;VMの作成&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#centos-stream-8%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab%e3%81%a8%e3%82%bb%e3%83%83%e3%83%88%e3%82%a2%e3%83%83%e3%83%97" &gt;CentOS Stream 8のインストールとセットアップ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#guest-additions%e3%81%ae%e5%b0%8e%e5%85%a5" &gt;Guest Additionsの導入&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="virtualboxのインストール"&gt;VirtualBoxのインストール
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://www.virtualbox.org/" target="_blank" rel="noopener"
 &gt;https://www.virtualbox.org/&lt;/a&gt; からOSX用のdmgファイルをダウンロードして中に入っているインストーラを起動する。&lt;/p&gt;
&lt;p&gt;インストーラを起動して指示に従っていけば&lt;code&gt;/Applications&lt;/code&gt;配下にVirtualBoxがインストールされる。&lt;/p&gt;
&lt;p&gt;&lt;img alt="インストーラ" class="gallery-image" data-flex-basis="349px" data-flex-grow="145" height="1098" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc01.png" srcset="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc01_hu_df61fad6e9685541.png 800w, https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc01.png 1598w" width="1598"&gt;&lt;/p&gt;
&lt;h3 id="vmの作成"&gt;VMの作成
&lt;/h3&gt;&lt;p&gt;VirtualBoxを起動して&amp;quot;New&amp;quot;からVMの作成を行う。&lt;/p&gt;
&lt;p&gt;名前は適当で、メモリのサイズも無理のない範囲で選ぶ。&lt;br&gt;
ストレージは32GB程度確保する。&lt;/p&gt;
&lt;p&gt;&lt;img alt="VMの設定" class="gallery-image" data-flex-basis="301px" data-flex-grow="125" height="951" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc02.png" srcset="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc02_hu_da75db5b0158e4e.png 800w, https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc02.png 1196w" width="1196"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="ストレージの設定" class="gallery-image" data-flex-basis="301px" data-flex-grow="125" height="951" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc03.png" srcset="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc03_hu_efd2b66cd2b8a099.png 800w, https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc03.png 1196w" width="1196"&gt;&lt;/p&gt;
&lt;p&gt;作成したVMの情報はこんな感じ。&lt;/p&gt;
&lt;p&gt;&lt;img alt="作成したVMの情報" class="gallery-image" data-flex-basis="301px" data-flex-grow="125" height="951" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc04.png" srcset="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc04_hu_6a08fe904c13b295.png 800w, https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc04.png 1196w" width="1196"&gt;&lt;/p&gt;
&lt;h3 id="centos-stream-8のインストールとセットアップ"&gt;CentOS Stream 8のインストールとセットアップ
&lt;/h3&gt;&lt;p&gt;作成したVMで起動するOSのイメージが必要なので、&lt;br&gt;
&lt;a class="link" href="https://www.centos.org/download/" target="_blank" rel="noopener"
 &gt;https://www.centos.org/download/&lt;/a&gt; から持ってくる。&lt;/p&gt;
&lt;p&gt;今回は&lt;a class="link" href="http://isoredirect.centos.org/centos/8-stream/isos/x86_64/" target="_blank" rel="noopener"
 &gt;x86_64用CentOS Stream 8&lt;/a&gt;を選択。&lt;br&gt;
ミラーはどこでもいいので&lt;code&gt;CentOS-Stream-8-x86_64-YYYYMMDD-dvd1.iso&lt;/code&gt;をダウンロードする。&lt;br&gt;
10GBくらいあってダウンロードには30分程度かかった。&lt;/p&gt;
&lt;p&gt;isoを落とせたら再度VirtualBoxに戻り、&lt;br&gt;
先程作成したVMの設定の&amp;quot;Storage&amp;quot;で&amp;quot;IDE Secondary Device 0&amp;quot;を押して先程ダウンロードしたisoファイルを選択した状態で&amp;quot;Start&amp;quot;する。&lt;/p&gt;
&lt;p&gt;&lt;img alt="isoの指定" class="gallery-image" data-flex-basis="301px" data-flex-grow="125" height="951" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc05.png" srcset="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc05_hu_38a0c15f018df028.png 800w, https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc05.png 1196w" width="1196"&gt;&lt;/p&gt;
&lt;p&gt;別ウインドウが出るので&amp;quot;Install CentOS Stream 8-stream&amp;quot;を押す。&lt;/p&gt;
&lt;p&gt;&lt;img alt="インストーラの画面" class="gallery-image" data-flex-basis="284px" data-flex-grow="118" height="597" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc06.png" width="708"&gt;&lt;/p&gt;
&lt;p&gt;CentOSのインストール画面が開くので適当に言語を選んで進む。&lt;br&gt;
次の画面になったら色が変わっている項目を埋める。&lt;br&gt;
今回は&amp;quot;Installation Destination&amp;quot;, &amp;ldquo;Root Password&amp;rdquo;, &amp;ldquo;User Creation&amp;quot;だけいじった。&lt;br&gt;
&amp;ldquo;Begin Installation&amp;quot;を押してインストールを開始。&lt;/p&gt;
&lt;p&gt;&lt;img alt="この状態になってからインストールを開始する" class="gallery-image" data-flex-basis="287px" data-flex-grow="119" height="761" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc07.png" srcset="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc07_hu_4a533e5982cd4f36.png 800w, https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc07.png 912w" width="912"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Installation Destination" class="gallery-image" data-flex-basis="287px" data-flex-grow="119" height="761" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc08.png" srcset="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc08_hu_b8a0cea95841e4b2.png 800w, https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc08.png 912w" width="912"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Root Password" class="gallery-image" data-flex-basis="287px" data-flex-grow="119" height="761" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc09.png" srcset="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc09_hu_b5dc77dba642f25c.png 800w, https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc09.png 912w" width="912"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="User Creation" class="gallery-image" data-flex-basis="287px" data-flex-grow="119" height="761" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc10.png" srcset="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc10_hu_2aa6fe3a528627c0.png 800w, https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc10.png 912w" width="912"&gt;&lt;/p&gt;
&lt;p&gt;インストールは10分ちょっとかかる。&lt;br&gt;
インストールが終わったら&amp;quot;Reboot System&amp;quot;から再起動する。&lt;/p&gt;
&lt;p&gt;&lt;img alt="インストール完了画面" class="gallery-image" data-flex-basis="287px" data-flex-grow="119" height="761" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc11.png" srcset="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc11_hu_33f5193027ff8bc5.png 800w, https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc11.png 912w" width="912"&gt;&lt;/p&gt;
&lt;p&gt;再起動が成功するとライセンスに同意しろ的な画面が出るので同意した上で&amp;quot;FINISH CONFIGURATION&amp;quot;を押す。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ライセンス承諾画面" class="gallery-image" data-flex-basis="290px" data-flex-grow="121" height="717" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc12.png" srcset="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc12_hu_6ff7371843bc9437.png 800w, https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc12.png 868w" width="868"&gt;&lt;/p&gt;
&lt;p&gt;またまた言語とかの設定画面が出るが適当に選択すればデスクトップ画面にたどり着ける。&lt;/p&gt;
&lt;p&gt;まずはパッケージを更新したいので、左上の&amp;quot;Activities&amp;quot;から端末を開いて&lt;code&gt;yum update&lt;/code&gt;する。&lt;br&gt;
すると名前解決できないぞ的なエラーに。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;uzimihsr@localhost ~&lt;span class="o"&gt;]&lt;/span&gt;$ sudo yum update -y
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;CentOS Stream &lt;span class="m"&gt;8&lt;/span&gt; - AppStream 0.0 B/s &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; B 00:00 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Errors during downloading metadata &lt;span class="k"&gt;for&lt;/span&gt; repository &lt;span class="s1"&gt;&amp;#39;appstream&amp;#39;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - Curl error &lt;span class="o"&gt;(&lt;/span&gt;6&lt;span class="o"&gt;)&lt;/span&gt;: Couldn&lt;span class="s1"&gt;&amp;#39;t resolve host name for http://mirrorlist.centos.org/?release=8-stream&amp;amp;arch=x86_64&amp;amp;repo=AppStream&amp;amp;infra=stock [Could not resolve host: mirrorlist.centos.org]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;Error: Failed to download metadata for repo &amp;#39;&lt;/span&gt;appstream&lt;span class="s1"&gt;&amp;#39;: Cannot prepare internal mirrorlist: Curl error (6): Couldn&amp;#39;&lt;/span&gt;t resolve host name &lt;span class="k"&gt;for&lt;/span&gt; http://mirrorlist.centos.org/?release&lt;span class="o"&gt;=&lt;/span&gt;8-stream&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;arch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;x86_64&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;repo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;AppStream&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;infra&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;stock &lt;span class="o"&gt;[&lt;/span&gt;Could not resolve host: mirrorlist.centos.org&lt;span class="o"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;いろいろ見てると右上のステータスで&amp;quot;Wired Off&amp;quot;になっていて、どうやらネットワークにつながっていないっぽい。&lt;br&gt;
&amp;ldquo;Wired Settings&amp;rdquo;→&amp;quot;⚙️&amp;quot;を開いて&amp;quot;Connect automatically&amp;quot;にチェックを入れて適用する。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ネットワークにつながってない" class="gallery-image" data-flex-basis="287px" data-flex-grow="119" height="761" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc13.png" srcset="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc13_hu_95962751daa49608.png 800w, https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc13.png 912w" width="912"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="自動でつなぐようにする" class="gallery-image" data-flex-basis="287px" data-flex-grow="119" height="761" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc14.png" srcset="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc14_hu_9ddc55f73aeb3dbf.png 800w, https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc14.png 912w" width="912"&gt;&lt;/p&gt;
&lt;p&gt;すると右上に&amp;quot;wired connected&amp;quot;のマークが出るようになるので再度パッケージ更新を試す。&lt;br&gt;
今度はうまく行った。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo yum update -y&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;img alt="yum updateできた" class="gallery-image" data-flex-basis="287px" data-flex-grow="119" height="761" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc15.png" srcset="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc15_hu_bb95d28c28915d07.png 800w, https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc15.png 912w" width="912"&gt;&lt;/p&gt;
&lt;h3 id="guest-additionsの導入"&gt;Guest Additionsの導入
&lt;/h3&gt;&lt;p&gt;VirtualBoxで立てたVMに&lt;code&gt;Guest Additions&lt;/code&gt;っていうのを入れるとホストOSとシームレスにGUI(マウス)操作ができたりして色々便利らしい。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://www.virtualbox.org/manual/ch04.html" target="_blank" rel="noopener"
 &gt;https://www.virtualbox.org/manual/ch04.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ホスト(Mac)側の操作に戻り、&lt;br&gt;
&amp;ldquo;VirtualBox VM&amp;rdquo;→&amp;ldquo;Devices&amp;rdquo;→&amp;ldquo;Insert Guest Additions CD image&amp;hellip;&amp;ldquo;を選択。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Guest Additions CD imageの挿入" class="gallery-image" data-flex-basis="283px" data-flex-grow="118" height="683" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc16.png" srcset="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc16_hu_c6621474ba877ed3.png 800w, https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc16.png 807w" width="807"&gt;&lt;/p&gt;
&lt;p&gt;なんかVMの画面でソフトウェアの警告が出たり管理者権限を要求されるけどガンガン進む。&lt;br&gt;
勝手に新しい端末が開いてスクリプトが動く。&lt;br&gt;
&amp;hellip;が、&amp;ldquo;モジュールのビルドに必要なカーネルヘッダがないよ&amp;quot;的なエラーで失敗する。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Verifying archive integrity... All good.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Uncompressing VirtualBox 6.1.32 Guest Additions &lt;span class="k"&gt;for&lt;/span&gt; Linux........
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions installer
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Copying additional installer modules ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Installing additional modules ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: Starting.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: Building the VirtualBox Guest Additions kernel 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;modules. This may take a &lt;span class="k"&gt;while&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: To build modules &lt;span class="k"&gt;for&lt;/span&gt; other installed kernels, run
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: /sbin/rcvboxadd quicksetup &amp;lt;version&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: or
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: /sbin/rcvboxadd quicksetup all
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: Kernel headers not found &lt;span class="k"&gt;for&lt;/span&gt; target kernel 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;4.18.0-365.el8.x86_64. Please install them and execute
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; /sbin/rcvboxadd setup
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;modprobe vboxguest failed
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;The log file /var/log/vboxadd-setup.log may contain further information.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Press Return to close this window...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;言われたとおり&lt;code&gt;kernel-headers&lt;/code&gt;と&lt;code&gt;kernel-devel&lt;/code&gt;を入れる。&lt;br&gt;
カーネル関連のパッケージを入れたときは再起動。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo yum install -y kernel-headers kernel-devel
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo reboot&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;再起動後、さっきのエラーメッセージでカーネルヘッダのインストール後に実行するよう指定されていたコマンドを打つ。&lt;br&gt;
またエラー。つらい。&lt;br&gt;
今度は&amp;rdquo;&lt;code&gt;gcc&lt;/code&gt;, &lt;code&gt;make&lt;/code&gt;, &lt;code&gt;perl&lt;/code&gt;が無いよ&amp;quot;と言われた。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;uzimihsr@localhost ~&lt;span class="o"&gt;]&lt;/span&gt;$ sudo /sbin/rcvboxadd setup
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: Starting.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: Building the VirtualBox Guest Additions kernel 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;modules. This may take a &lt;span class="k"&gt;while&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: To build modules &lt;span class="k"&gt;for&lt;/span&gt; other installed kernels, run
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: /sbin/rcvboxadd quicksetup &amp;lt;version&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: or
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: /sbin/rcvboxadd quicksetup all
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: Building the modules &lt;span class="k"&gt;for&lt;/span&gt; kernel 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;4.18.0-365.el8.x86_64.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;This system is currently not &lt;span class="nb"&gt;set&lt;/span&gt; up to build kernel modules.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Please install the gcc make perl packages from your distribution.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ValueError: File context &lt;span class="k"&gt;for&lt;/span&gt; /opt/VBoxGuestAdditions-6.1.32/other/mount.vboxsf already defined
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;modprobe vboxguest failed
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;The log file /var/log/vboxadd-setup.log may contain further information.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;言われたとおりに入れる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo yum install -y gcc make perl&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;再度実行。&lt;br&gt;
またまたエラー。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;uzimihsr@localhost ~&lt;span class="o"&gt;]&lt;/span&gt;$ sudo /sbin/rcvboxadd setup
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: Starting.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: Building the VirtualBox Guest Additions kernel 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;modules. This may take a &lt;span class="k"&gt;while&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: To build modules &lt;span class="k"&gt;for&lt;/span&gt; other installed kernels, run
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: /sbin/rcvboxadd quicksetup &amp;lt;version&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: or
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: /sbin/rcvboxadd quicksetup all
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: Building the modules &lt;span class="k"&gt;for&lt;/span&gt; kernel 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;4.18.0-365.el8.x86_64.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: Look at /var/log/vboxadd-setup.log to find out what 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;went wrong
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ValueError: File context &lt;span class="k"&gt;for&lt;/span&gt; /opt/VBoxGuestAdditions-6.1.32/other/mount.vboxsf already defined
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;modprobe vboxguest failed
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;The log file /var/log/vboxadd-setup.log may contain further information.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;今度は何もわからないので、指定されたログファイルを確認する。&lt;br&gt;
なんか&lt;code&gt;libelf-dev&lt;/code&gt;がないよ的なことを言われている。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;uzimihsr@localhost ~&lt;span class="o"&gt;]&lt;/span&gt;$ cat /var/log/vboxadd-setup.log
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Building the main Guest Additions 6.1.32 module &lt;span class="k"&gt;for&lt;/span&gt; kernel 4.18.0-365.el8.x86_64.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Error building the module. Build output follows.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;make &lt;span class="nv"&gt;V&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="nv"&gt;CONFIG_MODULE_SIG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;CONFIG_MODULE_SIG_ALL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; -C /lib/modules/4.18.0-365.el8.x86_64/build &lt;span class="nv"&gt;M&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/tmp/vbox.0 &lt;span class="nv"&gt;SRCROOT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/tmp/vbox.0 -j1 modules
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Makefile:985: *** &lt;span class="s2"&gt;&amp;#34;Cannot generate ORC metadata for CONFIG_UNWINDER_ORC=y, please install libelf-dev, libelf-devel or elfutils-libelf-devel&amp;#34;&lt;/span&gt;. Stop.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;make: *** &lt;span class="o"&gt;[&lt;/span&gt;/tmp/vbox.0/Makefile-footer.gmk:117: vboxguest&lt;span class="o"&gt;]&lt;/span&gt; Error &lt;span class="m"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;modprobe vboxguest failed&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;libelf-devel&lt;/code&gt;はELFバイナリファイルをいじるためのユーティリティらしい(あんまり知らない)。&lt;br&gt;
&lt;a class="link" href="https://sourceware.org/elfutils/" target="_blank" rel="noopener"
 &gt;https://sourceware.org/elfutils/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;yum search&lt;/code&gt;かけた感じだと&lt;code&gt;elfutils-libelf-devel&lt;/code&gt;しか見つからなかったのでこれを入れる。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo yum install -y elfutils-libelf-devel
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;再度実行。&lt;br&gt;
今度は行けたっぽい？&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;uzimihsr@localhost ~&lt;span class="o"&gt;]&lt;/span&gt;$ sudo /sbin/rcvboxadd setup
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: Starting.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: Building the VirtualBox Guest Additions kernel 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;modules. This may take a &lt;span class="k"&gt;while&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: To build modules &lt;span class="k"&gt;for&lt;/span&gt; other installed kernels, run
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: /sbin/rcvboxadd quicksetup &amp;lt;version&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: or
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: /sbin/rcvboxadd quicksetup all
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: Building the modules &lt;span class="k"&gt;for&lt;/span&gt; kernel 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;4.18.0-365.el8.x86_64.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: Look at /var/log/vboxadd-setup.log to find out what 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;went wrong
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ValueError: File context &lt;span class="k"&gt;for&lt;/span&gt; /opt/VBoxGuestAdditions-6.1.32/other/mount.vboxsf already defined
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VirtualBox Guest Additions: Running kernel modules will not be replaced &lt;span class="k"&gt;until&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;the system is restarted
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;uzimihsr@localhost ~&lt;span class="o"&gt;]&lt;/span&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;さっきと同じログファイルにはヘッダファイルが見つからない的なエラーが出てるんだけど、&lt;br&gt;
終了コードが0だしモジュールを読み込むために再起動するよう言われてるのでそれに従う。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;uzimihsr@localhost ~&lt;span class="o"&gt;]&lt;/span&gt;$ cat /var/log/vboxadd-setup.log
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Building the main Guest Additions 6.1.32 module &lt;span class="k"&gt;for&lt;/span&gt; kernel 4.18.0-365.el8.x86_64.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Building the shared folder support module.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Building the graphics driver module.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Error building the module. Build output follows.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;make &lt;span class="nv"&gt;V&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="nv"&gt;CONFIG_MODULE_SIG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;CONFIG_MODULE_SIG_ALL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; -C /lib/modules/4.18.0-365.el8.x86_64/build &lt;span class="nv"&gt;M&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/tmp/vbox.0 &lt;span class="nv"&gt;SRCROOT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/tmp/vbox.0 -j1 modules
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;test&lt;/span&gt; -e include/generated/autoconf.h -a -e include/config/auto.conf &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;	&lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;2&lt;span class="p"&gt;;&lt;/span&gt;							&lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; ERROR: Kernel configuration is invalid.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;		&lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; include/generated/autoconf.h or include/config/auto.conf are missing.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; Run &amp;#39;make oldconfig &amp;amp;&amp;amp; make prepare&amp;#39; on kernel src to fix it.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;	&lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;							&lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/bin/false&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mkdir -p /tmp/vbox.0/.tmp_versions &lt;span class="p"&gt;;&lt;/span&gt; rm -f /tmp/vbox.0/.tmp_versions/*
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;make -f ./scripts/Makefile.build &lt;span class="nv"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/tmp/vbox.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;(&lt;/span&gt;cat /dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; kernel//tmp/vbox.0/vboxvideo.ko&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &amp;gt; /tmp/vbox.0/modules.order
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; gcc -Wp,-MD,/tmp/vbox.0/.hgsmi_base.o.d -nostdinc -isystem /usr/lib/gcc/x86_64-redhat-linux/8/include -I./arch/x86/include -I./arch/x86/include/generated -I./include/drm-backport -I./include -I./arch/x86/include/uapi -I./arch/x86/include/generated/uapi -I./include/uapi -I./include/generated/uapi -include ./include/linux/kconfig.h -include ./include/linux/compiler_types.h -D__KERNEL__ -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -fshort-wchar -Werror-implicit-function-declaration -Wno-format-security -std&lt;span class="o"&gt;=&lt;/span&gt;gnu89 -fno-PIE -DCC_HAVE_ASM_GOTO -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -m64 -falign-jumps&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; -falign-loops&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; -mno-80387 -mno-fp-ret-in-387 -mpreferred-stack-boundary&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt; -mskip-rax-setup -mtune&lt;span class="o"&gt;=&lt;/span&gt;generic -mno-red-zone -mcmodel&lt;span class="o"&gt;=&lt;/span&gt;kernel -funit-at-a-time -DCONFIG_AS_CFI&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; -DCONFIG_AS_CFI_SIGNAL_FRAME&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; -DCONFIG_AS_CFI_SECTIONS&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; -DCONFIG_AS_SSSE3&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; -DCONFIG_AS_CRC32&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; -DCONFIG_AS_AVX&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; -DCONFIG_AS_AVX2&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; -DCONFIG_AS_AVX512&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; -DCONFIG_AS_SHA1_NI&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; -DCONFIG_AS_SHA256_NI&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; -DCONFIG_TPAUSE&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; -pipe -Wno-sign-compare -fno-asynchronous-unwind-tables -mindirect-branch&lt;span class="o"&gt;=&lt;/span&gt;thunk-extern -mindirect-branch-register -fno-jump-tables -fno-delete-null-pointer-checks -Wno-frame-address -Wno-format-truncation -Wno-format-overflow -Wno-int-in-bool-context -O2 --param&lt;span class="o"&gt;=&lt;/span&gt;allow-store-data-races&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; -Wframe-larger-than&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2048&lt;/span&gt; -fstack-protector-strong -Wno-unused-but-set-variable -Wno-unused-const-variable -g -gdwarf-4 -pg -mrecord-mcount -mfentry -DCC_USING_FENTRY -fno-inline-functions-called-once -Wdeclaration-after-statement -Wno-pointer-sign -Wno-stringop-truncation -Wno-maybe-uninitialized -fno-strict-overflow -fno-merge-all-constants -fmerge-constants -fno-stack-check -fconserve-stack -Werror&lt;span class="o"&gt;=&lt;/span&gt;implicit-int -Werror&lt;span class="o"&gt;=&lt;/span&gt;strict-prototypes -Werror&lt;span class="o"&gt;=&lt;/span&gt;date-time -Werror&lt;span class="o"&gt;=&lt;/span&gt;incompatible-pointer-types -Werror&lt;span class="o"&gt;=&lt;/span&gt;designated-init -fmacro-prefix-map&lt;span class="o"&gt;=&lt;/span&gt;./&lt;span class="o"&gt;=&lt;/span&gt; -Wno-packed-not-aligned -I./include -I/tmp/vbox.0/ -I./include/drm -D__KERNEL__ -DMODULE -DRT_WITHOUT_PRAGMA_ONCE -DRT_ARCH_AMD64 -DMODULE -DKBUILD_BASENAME&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#34;hgsmi_base&amp;#34;&amp;#39;&lt;/span&gt; -DKBUILD_MODNAME&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#34;vboxvideo&amp;#34;&amp;#39;&lt;/span&gt; -c -o /tmp/vbox.0/.tmp_hgsmi_base.o /tmp/vbox.0/hgsmi_base.c
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;In file included from /tmp/vbox.0/hgsmi_base.c:27:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/tmp/vbox.0/vbox_drv.h:175:11: fatal error: drm/ttm/ttm_memory.h: No such file or directory
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# include &amp;lt;drm/ttm/ttm_memory.h&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ^~~~~~~~~~~~~~~~~~~~~~
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;compilation terminated.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;make&lt;span class="o"&gt;[&lt;/span&gt;2&lt;span class="o"&gt;]&lt;/span&gt;: *** &lt;span class="o"&gt;[&lt;/span&gt;scripts/Makefile.build:316: /tmp/vbox.0/hgsmi_base.o&lt;span class="o"&gt;]&lt;/span&gt; Error &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;make&lt;span class="o"&gt;[&lt;/span&gt;1&lt;span class="o"&gt;]&lt;/span&gt;: *** &lt;span class="o"&gt;[&lt;/span&gt;Makefile:1577: _module_/tmp/vbox.0&lt;span class="o"&gt;]&lt;/span&gt; Error &lt;span class="m"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;make: *** &lt;span class="o"&gt;[&lt;/span&gt;/tmp/vbox.0/Makefile-footer.gmk:117: vboxvideo&lt;span class="o"&gt;]&lt;/span&gt; Error &lt;span class="m"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;uzimihsr@localhost ~&lt;span class="o"&gt;]&lt;/span&gt;$ sudo reboot&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;再起動後はたしかにマウス操作がやりやすくなっている。&lt;/p&gt;
&lt;p&gt;最後にクリップボード共有の設定を入れる。&lt;br&gt;
VirtualBoxの画面で&amp;quot;Settings&amp;rdquo;→&amp;ldquo;General&amp;rdquo;→&amp;ldquo;Advanced&amp;rdquo;→&amp;ldquo;Shared Clipboard&amp;quot;を&amp;quot;Bidirectional&amp;quot;にすると、&lt;br&gt;
ホスト(Mac)とVM(CentOS)をまたいだコピペができるようになって便利。&lt;/p&gt;
&lt;p&gt;&lt;img alt="クリップボード共有設定" class="gallery-image" data-flex-basis="310px" data-flex-grow="129" height="839" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc17.png" srcset="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc17_hu_a4fcdecd954baa75.png 800w, https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sc17.png 1084w" width="1084"&gt;&lt;/p&gt;
&lt;p&gt;疲れたのでとりあえずここまで。&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;こういった地味な環境構築をたまにやるとたのしい。&lt;/p&gt;
&lt;p&gt;VirtualBox使うのが久しぶりでいろいろ詰まったが良い練習になった。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="コンピュータより自分にかまってほしいねこちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sotochan_hu_71688c722dcaee52.jpg 800w, https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sotochan_hu_4b062386be896709.jpg 1600w, https://blog.uzimihsr.com/post/2022-02-24-centos-stream-8-virtualbox-mac/sotochan.jpg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>A queue and multiple workers in golang</title><link>https://blog.uzimihsr.com/post/2022-02-10-queue-and-multiple-workers-golang/</link><pubDate>Thu, 10 Feb 2022 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2022-02-10-queue-and-multiple-workers-golang/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2022-02-10-queue-and-multiple-workers-golang/sotochan.jpeg" alt="Featured image of post A queue and multiple workers in golang" /&gt;&lt;h2 id="summary"&gt;Summary
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;A queue &amp;amp; multiple workers in golang
&lt;ul&gt;
&lt;li&gt;We can use buffered channel as a queue, and goroutines as workers.&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://pkg.go.dev/sync#WaitGroup" target="_blank" rel="noopener"
 &gt;WaitGroup&lt;/a&gt; is useful to wait for goroutines to finish.&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://pkg.go.dev/context" target="_blank" rel="noopener"
 &gt;Context&lt;/a&gt; makes it easy to stop other goroutines from one goroutine.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="prerequisites"&gt;Prerequisites
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;go version go1.17.3 darwin/amd64&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="channel-as-a-queue-goroutines-as-workers"&gt;Channel as a queue, Goroutines as workers
&lt;/h2&gt;&lt;p&gt;I wanted to write the following pattern in golang:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A queue has multiple processing targets&lt;/li&gt;
&lt;li&gt;Each worker gets one target from the queue, processes it, and repeats the procedure until the queue is empty&lt;/li&gt;
&lt;li&gt;All workers run in parallel&lt;/li&gt;
&lt;li&gt;If an error occurs in one worker, all other workers will stop after processing the current target&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="A queue and workers" class="gallery-image" data-flex-basis="766px" data-flex-grow="319" height="458" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-10-queue-and-multiple-workers-golang/fig01.png" srcset="https://blog.uzimihsr.com/post/2022-02-10-queue-and-multiple-workers-golang/fig01_hu_2f72ae45843806c5.png 800w, https://blog.uzimihsr.com/post/2022-02-10-queue-and-multiple-workers-golang/fig01.png 1462w" width="1462"&gt;&lt;/p&gt;
&lt;p&gt;I wrote that pattern using buffered channels and goroutines.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/ab5f24e85c47884386874e4c1fd08e85.js"&gt;&lt;/script&gt;
&lt;p&gt;Here are some notes.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A queue has multiple processing targets&lt;/li&gt;
&lt;li&gt;Each worker gets one target from the queue, processes it, and repeats the procedure until the queue is empty&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this case, we can use &lt;code&gt;buffered channel&lt;/code&gt; as a queue.&lt;br&gt;
A worker tries to get the target from the channel, and processes it if it succeeds, or exits if the channel is closed.&lt;br&gt;
I implemented this pattern with &lt;code&gt;select&lt;/code&gt; statement.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// example&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;queue&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;chan&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;queue&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="nx"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// any task you want to do for v&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;If an error occurs in one worker, all other workers will stop after processing the current target&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a class="link" href="https://pkg.go.dev/context#WithCancel" target="_blank" rel="noopener"
 &gt;context.WithCancel&lt;/a&gt; is suitable for this purpose.&lt;br&gt;
If the process returns an error, the worker will execute &lt;code&gt;cancelFunc&lt;/code&gt;.&lt;br&gt;
&lt;code&gt;cancelFunc&lt;/code&gt; closes &lt;code&gt;ctx&lt;/code&gt;(channel) and the worker will stop when &lt;code&gt;ctx&lt;/code&gt; is closed.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// example&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;cancel&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithCancel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// any task you want&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;All workers run in parallel&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With &lt;a class="link" href="https://pkg.go.dev/sync#WaitGroup" target="_blank" rel="noopener"
 &gt;sync.WaitGroup&lt;/a&gt;, it can wait for multiple goroutines to stop.&lt;br&gt;
When a goroutine starts, call &lt;a class="link" href="https://pkg.go.dev/sync#WaitGroup.Add" target="_blank" rel="noopener"
 &gt;Add&lt;/a&gt; to increase the counter, and when it finishes, call &lt;a class="link" href="https://pkg.go.dev/sync#WaitGroup.Done" target="_blank" rel="noopener"
 &gt;Done&lt;/a&gt; to decrease the counter.&lt;br&gt;
&lt;a class="link" href="https://pkg.go.dev/sync#WaitGroup.Wait" target="_blank" rel="noopener"
 &gt;Wait&lt;/a&gt; waits until the counter reaches zero.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// example&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;wg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WaitGroup&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;workers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;workers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;wg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;wg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// any task you want&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;wg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In order to vary the processing time depending on the target, I created the following process.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;sleep for the specified number of seconds&lt;/li&gt;
&lt;li&gt;if the specified number is 4, raise an error&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Unlucky 4!!!&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then run &lt;strong&gt;main.go&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://go.dev/play/p/ZvO9QVVg5sq" target="_blank" rel="noopener"
 &gt;Go Playground&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;targets: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;7&lt;/span&gt; 6&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;number of workers: &lt;span class="m"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-1: target &lt;span class="m"&gt;1&lt;/span&gt; START
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-0: target &lt;span class="m"&gt;5&lt;/span&gt; START
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-2: target &lt;span class="m"&gt;8&lt;/span&gt; START
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-1: target &lt;span class="m"&gt;1&lt;/span&gt; END
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-1: target &lt;span class="m"&gt;2&lt;/span&gt; START
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-1: target &lt;span class="m"&gt;2&lt;/span&gt; END
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-1: target &lt;span class="m"&gt;3&lt;/span&gt; START
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-0: target &lt;span class="m"&gt;5&lt;/span&gt; END
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-0: target &lt;span class="m"&gt;7&lt;/span&gt; START
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-1: target &lt;span class="m"&gt;3&lt;/span&gt; END
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-1: target &lt;span class="m"&gt;6&lt;/span&gt; START
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-2: target &lt;span class="m"&gt;8&lt;/span&gt; END
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-2: no target...finish
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-0: target &lt;span class="m"&gt;7&lt;/span&gt; END
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-0: no target...finish
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-1: target &lt;span class="m"&gt;6&lt;/span&gt; END
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-1: no target...finish
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;All workers finished.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;All targets were processed.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It is hard to understand how it worked in text, so I made a diagram below.&lt;br&gt;
All workers work in parallel and each worker gets the target from the queue.&lt;br&gt;
&lt;strong&gt;Worker 1&lt;/strong&gt; drew a small number and immediately went for the next target.&lt;br&gt;
In contrast, &lt;strong&gt;Worker 2&lt;/strong&gt; drew a large number, and the queue had been already empty when the worker finished its first target.&lt;/p&gt;
&lt;p&gt;&lt;img alt="how it worked" class="gallery-image" data-flex-basis="763px" data-flex-grow="318" height="633" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-10-queue-and-multiple-workers-golang/fig02.png" srcset="https://blog.uzimihsr.com/post/2022-02-10-queue-and-multiple-workers-golang/fig02_hu_82d270f0c02edb3f.png 800w, https://blog.uzimihsr.com/post/2022-02-10-queue-and-multiple-workers-golang/fig02_hu_2415401482d11d0c.png 1600w, https://blog.uzimihsr.com/post/2022-02-10-queue-and-multiple-workers-golang/fig02.png 2014w" width="2014"&gt;&lt;/p&gt;
&lt;p&gt;Change the target to cause an error, and run &lt;strong&gt;main.go&lt;/strong&gt; again.&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://go.dev/play/p/bFRyJ5EjeYj" target="_blank" rel="noopener"
 &gt;Go Playground&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;targets: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;7&lt;/span&gt; 6&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;number of workers: &lt;span class="m"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-2: target &lt;span class="m"&gt;1&lt;/span&gt; START
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-0: target &lt;span class="m"&gt;8&lt;/span&gt; START
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-1: target &lt;span class="m"&gt;4&lt;/span&gt; START
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-2: target &lt;span class="m"&gt;1&lt;/span&gt; END
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-2: target &lt;span class="m"&gt;2&lt;/span&gt; START
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-2: target &lt;span class="m"&gt;2&lt;/span&gt; END
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-2: target &lt;span class="m"&gt;3&lt;/span&gt; START
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-1: ERROR! Unlucky 4!!!
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-2: target &lt;span class="m"&gt;3&lt;/span&gt; END
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-2: received ctx.Done&lt;span class="o"&gt;()&lt;/span&gt;...finish
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-0: target &lt;span class="m"&gt;8&lt;/span&gt; END
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-0: received ctx.Done&lt;span class="o"&gt;()&lt;/span&gt;...finish
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;All workers finished.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;7&lt;/span&gt; was not processed...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;6&lt;/span&gt; was not processed...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Worker 1&lt;/strong&gt; drew &amp;ldquo;4&amp;rdquo; and raised an error, then all workers stopped after finishing the target they had.&lt;/p&gt;
&lt;p&gt;&lt;img alt="an error from one worker stopped all workers" class="gallery-image" data-flex-basis="763px" data-flex-grow="318" height="633" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-10-queue-and-multiple-workers-golang/fig03.png" srcset="https://blog.uzimihsr.com/post/2022-02-10-queue-and-multiple-workers-golang/fig03_hu_9e66edf60bede72d.png 800w, https://blog.uzimihsr.com/post/2022-02-10-queue-and-multiple-workers-golang/fig03_hu_bd404f31dcd0a802.png 1600w, https://blog.uzimihsr.com/post/2022-02-10-queue-and-multiple-workers-golang/fig03.png 2014w" width="2014"&gt;&lt;/p&gt;
&lt;p&gt;(The following is the same content in Japanese.)&lt;/p&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Go&lt;/code&gt;で複数の処理対象を1つのキューに詰めて複数のワーカーで並行して処理するやつを書いた
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;channel&lt;/code&gt;をキューとして、&lt;code&gt;goroutine&lt;/code&gt;をワーカーとして使えそう&lt;/li&gt;
&lt;li&gt;複数&lt;code&gt;goroutine&lt;/code&gt;の完了を待つには&lt;code&gt;WaitGroup&lt;/code&gt;を使うのが良さげ&lt;/li&gt;
&lt;li&gt;&lt;code&gt;goroutine&lt;/code&gt;から他の&lt;code&gt;goroutine&lt;/code&gt;を止めたりするのは&lt;code&gt;Context&lt;/code&gt;を使うのが良さげ&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;go version go1.17.3 darwin/amd64&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="キューchannelとワーカーgo-routine"&gt;キュー(channel)とワーカー(go routine)
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Go&lt;/code&gt;でちょっとしたバッチ的なものを書こうとしたときに、&lt;br&gt;
同じような処理を繰り返す部分があったので&lt;code&gt;goroutine&lt;/code&gt;を使っていい感じの並行処理を書きたくなった。&lt;/p&gt;
&lt;p&gt;イメージとしては&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;処理したい対象が1つのキューに詰められている&lt;/li&gt;
&lt;li&gt;1つのワーカーはキューから対象を1つ取り出して処理、をキューが空になるまで繰り返す&lt;/li&gt;
&lt;li&gt;すべてのワーカーは並行して動作する&lt;/li&gt;
&lt;li&gt;どこかのワーカーでエラーが発生したら他の全てのワーカーにも知らせて、それを知った各ワーカーは現在処理している対象までで処理を終了する&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;という感じ。&lt;/p&gt;
&lt;p&gt;&lt;img alt="キューとワーカー" class="gallery-image" data-flex-basis="766px" data-flex-grow="319" height="458" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-10-queue-and-multiple-workers-golang/fig01.png" srcset="https://blog.uzimihsr.com/post/2022-02-10-queue-and-multiple-workers-golang/fig01_hu_2f72ae45843806c5.png 800w, https://blog.uzimihsr.com/post/2022-02-10-queue-and-multiple-workers-golang/fig01.png 1462w" width="1462"&gt;&lt;/p&gt;
&lt;p&gt;今回はかんたんなものの例として&lt;code&gt;Go&lt;/code&gt;の&lt;code&gt;channel&lt;/code&gt;と&lt;code&gt;goroutine&lt;/code&gt;を用いて実現してみた。&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/ab5f24e85c47884386874e4c1fd08e85.js"&gt;&lt;/script&gt;
&lt;p&gt;重要そうなところを(数ヶ月後の自分のために)メモしておく。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;処理したい対象が1つのキューに詰められている&lt;/li&gt;
&lt;li&gt;1つのワーカーはキューから対象を1つ取り出して処理、をキューが空になるまで繰り返す&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;は次のように書いた。&lt;/p&gt;
&lt;p&gt;今回の用途のキューであれば、バッファあり&lt;code&gt;channel&lt;/code&gt;を使って実現できる。&lt;br&gt;
&lt;code&gt;select&lt;/code&gt;を使って、&lt;code&gt;channel&lt;/code&gt;から値が取り出せれば何らかの処理を実行、&lt;code&gt;channel&lt;/code&gt;が閉じられたらそこで止まるようにした。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;queue&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;chan&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;queue&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="nx"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// any task you want to do for the v&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;どこかのワーカーでエラーが発生したら他の全てのワーカーにも知らせて、それを知った各ワーカーは現在処理している対象までで処理を終了する&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;は&lt;a class="link" href="https://pkg.go.dev/context#WithCancel" target="_blank" rel="noopener"
 &gt;context.WithCancel&lt;/a&gt;を使って次のように書いた。&lt;br&gt;
ワーカー(&lt;code&gt;go routine&lt;/code&gt;)でなにかエラーが起こったら&lt;strong&gt;cancelFunc&lt;/strong&gt;を実行して&lt;strong&gt;ctx&lt;/strong&gt;(&lt;code&gt;channel &lt;/code&gt;)を閉じ、&lt;br&gt;
&lt;strong&gt;ctx&lt;/strong&gt;が閉じられたらその時点でワーカーを終了させる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;cancel&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithCancel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// any task you want&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;すべてのワーカーは並行して動作する&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ワーカーを複数並行して動かし、全部のワーカーが止まるまで待つような処理は&lt;a class="link" href="https://pkg.go.dev/sync#WaitGroup" target="_blank" rel="noopener"
 &gt;sync.WaitGroup&lt;/a&gt;をつかって書いた。&lt;br&gt;
&lt;a class="link" href="https://pkg.go.dev/sync#WaitGroup.Wait" target="_blank" rel="noopener"
 &gt;Wait&lt;/a&gt;を呼び出すと待つ対象が0になるまで待ち続けるので、&lt;br&gt;
各&lt;code&gt;goroutine&lt;/code&gt;の開始時に&lt;a class="link" href="https://pkg.go.dev/sync#WaitGroup.Add" target="_blank" rel="noopener"
 &gt;Add&lt;/a&gt;して待つ対象を増やし、&lt;code&gt;goroutine&lt;/code&gt;が終了したら&lt;a class="link" href="https://pkg.go.dev/sync#WaitGroup.Done" target="_blank" rel="noopener"
 &gt;Done&lt;/a&gt;で待つ対象をへらすようにしている。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;wg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WaitGroup&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;workers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;workers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;wg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;wg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// any task you want&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;wg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;あとはこれらをいい感じに組み合わせた。&lt;/p&gt;
&lt;p&gt;また、今回は処理対象ごとに処理時間をバラバラにしたかったので、ワーカーの処理として次のようなものを用意した。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;引数の秒数ぶん待機する&lt;/li&gt;
&lt;li&gt;引数が4ならエラーを返す&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Unlucky 4!!!&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;main.go&lt;/strong&gt;を実際に動かしてみる。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://go.dev/play/p/ZvO9QVVg5sq" target="_blank" rel="noopener"
 &gt;Go Playground&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;targets: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;7&lt;/span&gt; 6&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;number of workers: &lt;span class="m"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-1: target &lt;span class="m"&gt;1&lt;/span&gt; START
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-0: target &lt;span class="m"&gt;5&lt;/span&gt; START
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-2: target &lt;span class="m"&gt;8&lt;/span&gt; START
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-1: target &lt;span class="m"&gt;1&lt;/span&gt; END
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-1: target &lt;span class="m"&gt;2&lt;/span&gt; START
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-1: target &lt;span class="m"&gt;2&lt;/span&gt; END
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-1: target &lt;span class="m"&gt;3&lt;/span&gt; START
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-0: target &lt;span class="m"&gt;5&lt;/span&gt; END
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-0: target &lt;span class="m"&gt;7&lt;/span&gt; START
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-1: target &lt;span class="m"&gt;3&lt;/span&gt; END
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-1: target &lt;span class="m"&gt;6&lt;/span&gt; START
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-2: target &lt;span class="m"&gt;8&lt;/span&gt; END
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-2: no target...finish
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-0: target &lt;span class="m"&gt;7&lt;/span&gt; END
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-0: no target...finish
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-1: target &lt;span class="m"&gt;6&lt;/span&gt; END
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-1: no target...finish
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;All workers finished.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;All targets were processed.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;狙い通りに動いたのだが、文字だけ追っても見づらいので図にしてみた。&lt;br&gt;
各ワーカーが1つずつ対象をキューから取り出してその秒数ぶん待機、を繰り返しており、&lt;br&gt;
&lt;strong&gt;Worker 1&lt;/strong&gt;のように小さい数字(=処理が軽い)を引くとその分次の対象を取りに行くのが早くなっていて、&lt;br&gt;
逆に&lt;strong&gt;Worker 2&lt;/strong&gt;のように最初に大きい数字(=処理が重い)を引くとその間に他のワーカーが働くので対象がなくなっている。&lt;/p&gt;
&lt;p&gt;&lt;img alt="処理はこんな感じ" class="gallery-image" data-flex-basis="763px" data-flex-grow="318" height="633" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-10-queue-and-multiple-workers-golang/fig02.png" srcset="https://blog.uzimihsr.com/post/2022-02-10-queue-and-multiple-workers-golang/fig02_hu_82d270f0c02edb3f.png 800w, https://blog.uzimihsr.com/post/2022-02-10-queue-and-multiple-workers-golang/fig02_hu_2415401482d11d0c.png 1600w, https://blog.uzimihsr.com/post/2022-02-10-queue-and-multiple-workers-golang/fig02.png 2014w" width="2014"&gt;&lt;/p&gt;
&lt;p&gt;最後にワーカーがエラーを吐くような処理対象をキューに仕込んで動かしてみる。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://go.dev/play/p/bFRyJ5EjeYj" target="_blank" rel="noopener"
 &gt;Go Playground&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;targets: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;7&lt;/span&gt; 6&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;number of workers: &lt;span class="m"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-2: target &lt;span class="m"&gt;1&lt;/span&gt; START
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-0: target &lt;span class="m"&gt;8&lt;/span&gt; START
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-1: target &lt;span class="m"&gt;4&lt;/span&gt; START
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-2: target &lt;span class="m"&gt;1&lt;/span&gt; END
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-2: target &lt;span class="m"&gt;2&lt;/span&gt; START
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-2: target &lt;span class="m"&gt;2&lt;/span&gt; END
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-2: target &lt;span class="m"&gt;3&lt;/span&gt; START
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-1: ERROR! Unlucky 4!!!
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-2: target &lt;span class="m"&gt;3&lt;/span&gt; END
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-2: received ctx.Done&lt;span class="o"&gt;()&lt;/span&gt;...finish
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-0: target &lt;span class="m"&gt;8&lt;/span&gt; END
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Worker-0: received ctx.Done&lt;span class="o"&gt;()&lt;/span&gt;...finish
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;All workers finished.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;7&lt;/span&gt; was not processed...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;6&lt;/span&gt; was not processed...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;こちらも狙い通り動いていて、&lt;br&gt;
この場合は4を引いた&lt;strong&gt;Worker 1&lt;/strong&gt;の処理でエラーが発生し、&lt;br&gt;
他のワーカーもそのタイミングで持っている対象を最後に以降の処理を行わないようになっている。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ワーカーでエラーが起きると他のワーカーも止まる" class="gallery-image" data-flex-basis="763px" data-flex-grow="318" height="633" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-10-queue-and-multiple-workers-golang/fig03.png" srcset="https://blog.uzimihsr.com/post/2022-02-10-queue-and-multiple-workers-golang/fig03_hu_9e66edf60bede72d.png 800w, https://blog.uzimihsr.com/post/2022-02-10-queue-and-multiple-workers-golang/fig03_hu_bd404f31dcd0a802.png 1600w, https://blog.uzimihsr.com/post/2022-02-10-queue-and-multiple-workers-golang/fig03.png 2014w" width="2014"&gt;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;久しぶりにGoにガッツリ触った。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;go routine&lt;/code&gt;とか&lt;code&gt;channel&lt;/code&gt;とか適当な理解で済ませていたもののおさらいができてよかった。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="キーボードを枕にするそとちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-10-queue-and-multiple-workers-golang/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2022-02-10-queue-and-multiple-workers-golang/sotochan_hu_778a0f9e9c4357f0.jpeg 800w, https://blog.uzimihsr.com/post/2022-02-10-queue-and-multiple-workers-golang/sotochan_hu_87a7ea67e8715381.jpeg 1600w, https://blog.uzimihsr.com/post/2022-02-10-queue-and-multiple-workers-golang/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>1月のそとちゃん(2022)</title><link>https://blog.uzimihsr.com/post/2022-02-01-sotochan/</link><pubDate>Tue, 01 Feb 2022 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2022-02-01-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2022-02-01-sotochan/sotochan.jpeg" alt="Featured image of post 1月のそとちゃん(2022)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%82%e3%81%be%e3%81%88%e3%82%93%e3%81%bc" &gt;あまえんぼ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%82%e3%81%b0%e3%82%8c%e3%82%93%e3%81%bc" &gt;あばれんぼ&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="あまえんぼ"&gt;あまえんぼ
&lt;/h3&gt;&lt;p&gt;またもあまえんぼ期が再来！&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ねこはあったかいねぇ &lt;a href="https://t.co/UtkGEckq0O"&gt;pic.twitter.com/UtkGEckq0O&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1478365038159499266?ref_src=twsrc%5Etfw"&gt;January 4, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;ソファで座ってると高確率で膝に乗ってくる上に、&lt;br&gt;
一度乗っちゃうと全然降りなくてこまっちゃう(たすかる)。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;降りない &lt;a href="https://t.co/7r9sWkOUGX"&gt;pic.twitter.com/7r9sWkOUGX&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1480501792727515136?ref_src=twsrc%5Etfw"&gt;January 10, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;人の膝の上に乗ってきて勝手に暴れたりひっくり返ったり(?)やりたい放題。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;自由 &lt;a href="https://t.co/Gz2gO7BHCs"&gt;pic.twitter.com/Gz2gO7BHCs&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1479639076731256835?ref_src=twsrc%5Etfw"&gt;January 8, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;自由 &lt;a href="https://t.co/UJmr2WYKGK"&gt;pic.twitter.com/UJmr2WYKGK&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1477562071076470786?ref_src=twsrc%5Etfw"&gt;January 2, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;たまたまねこがおしりをこっちに向けたときになんとなくぽんぽん叩いたらそれ以降ハマったらしく、&lt;br&gt;
最近はちゃんとぽんぽんしないと文句を言われる。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;この体勢になったらねこのおしりをぽんぽんしなくてはならない &lt;a href="https://t.co/a5q8jw1A0h"&gt;pic.twitter.com/a5q8jw1A0h&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1486625584738611200?ref_src=twsrc%5Etfw"&gt;January 27, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;膝に乗ってないときもぽんぽんしてほしいらしい。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;おしりぽんぽん要求ちゃん &lt;a href="https://t.co/dk5iVzAbq0"&gt;pic.twitter.com/dk5iVzAbq0&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1485264414857375746?ref_src=twsrc%5Etfw"&gt;January 23, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;&lt;img alt="ぽんぽんされている間はなぜか険しい顔をする" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-01-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2022-02-01-sotochan/sotochan01_hu_a78f58433ceaa603.jpeg 800w, https://blog.uzimihsr.com/post/2022-02-01-sotochan/sotochan01_hu_6c99f31cf0a90b28.jpeg 1600w, https://blog.uzimihsr.com/post/2022-02-01-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;あまえんぼすぎてちょっと心配になるくらいだけど、&lt;br&gt;
甘えてる最中のねこちゃんがアホみたいにかわいいのでOKです。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;あまえんぼガチ勢 &lt;a href="https://t.co/CtFjYfP6TV"&gt;pic.twitter.com/CtFjYfP6TV&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1486997447704739841?ref_src=twsrc%5Etfw"&gt;January 28, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;h3 id="あばれんぼ"&gt;あばれんぼ
&lt;/h3&gt;&lt;p&gt;昨年末の手術後に動けなかった時期がなにかのきっかけになってしまったのか、&lt;br&gt;
そとちゃんは未だに家の中を暴れまわっている。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;暴れ毛玉 &lt;a href="https://t.co/K6Gede8pTy"&gt;pic.twitter.com/K6Gede8pTy&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1481067027632914433?ref_src=twsrc%5Etfw"&gt;January 12, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;特に早朝のテンションが最高潮で、毎朝鳴くわ跳ぶわ壊すわでとてもにぎやか。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;今朝は大暴れで家壊れると思った &lt;a href="https://t.co/oLiWUdgIAe"&gt;pic.twitter.com/oLiWUdgIAe&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1486520951747805184?ref_src=twsrc%5Etfw"&gt;January 27, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;破壊 &lt;a href="https://t.co/LDHDq1c9YH"&gt;pic.twitter.com/LDHDq1c9YH&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1486891431050739713?ref_src=twsrc%5Etfw"&gt;January 28, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;前の日の夜に多めに遊ぶとか、そんな程度で朝のそとちゃんは止められない。&lt;/p&gt;
&lt;p&gt;日が昇れば窓際で外にいかせろと叫び、&lt;/p&gt;
&lt;p&gt;カリカリマシンから朝ごはんが出ればドカ食いしてすぐトイレ。&lt;/p&gt;
&lt;p&gt;うんちをもりもり出したらちゃんと大声で報告した後(重要らしい)、俺が寝ている布団の上を走り回る。&lt;/p&gt;
&lt;p&gt;俺はその衝撃で一瞬だけ起きて仕方なくおもちゃを廊下に投げ、ねこはそれを追いかけてしばき続ける。&lt;/p&gt;
&lt;p&gt;あとはだいたい1hくらいキャットタワーと台所で暴れまわったらようやくちょっと眠くなって、&lt;br&gt;
寝ている俺のお腹の上でおしりをこっちに向けて寝始める。&lt;/p&gt;
&lt;p&gt;これが我が家のモーニングルーティーン。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;起きられない &lt;a href="https://t.co/AXnYCvPTYx"&gt;pic.twitter.com/AXnYCvPTYx&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1485771568840339459?ref_src=twsrc%5Etfw"&gt;January 25, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;起床封じ &lt;a href="https://t.co/abKAgMqR2O"&gt;pic.twitter.com/abKAgMqR2O&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1487606243103752192?ref_src=twsrc%5Etfw"&gt;January 30, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;一度この体勢になるとねこが自分で起きてどこかにいくまで動くことは許されない。&lt;/p&gt;
&lt;p&gt;おかげで朝は高確率で二度寝してしまう身体になってしまった。&lt;/p&gt;
&lt;p&gt;でもねこちゃんが元気なのでOKです。&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;年末の手術を頑張ったそとちゃんを甘やかしまくっていたら、とんでもない甘え暴れん坊になってしまった&amp;hellip;&lt;/p&gt;
&lt;p&gt;が、ねこは幸せになるほどふてぶてしくなるとどこかで聞いた気がするので、これでいいかなとも思っている。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="やりたい放題のねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-02-01-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2022-02-01-sotochan/sotochan_hu_1eadae8cacc1bae7.jpeg 800w, https://blog.uzimihsr.com/post/2022-02-01-sotochan/sotochan_hu_2762d7966a87137.jpeg 1600w, https://blog.uzimihsr.com/post/2022-02-01-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>Specify the API Group of the resource with kubectl</title><link>https://blog.uzimihsr.com/post/2022-01-20-kubectl-specify-api-group/</link><pubDate>Thu, 20 Jan 2022 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2022-01-20-kubectl-specify-api-group/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2022-01-20-kubectl-specify-api-group/sotochan.jpg" alt="Featured image of post Specify the API Group of the resource with kubectl" /&gt;&lt;h2 id="summary"&gt;Summary
&lt;/h2&gt;&lt;p&gt;We can use the expression &lt;code&gt;&amp;lt;Resource&amp;gt;.&amp;lt;API Group&amp;gt;&lt;/code&gt; to specify the API Group with kubectl.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Example: the expressions of &amp;#34;Event v1 core&amp;#34; and &amp;#34;Event v1 events.k8s.io&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl auth can-i get events
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl auth can-i get events.events.k8s.io&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="prerequisites"&gt;Prerequisites
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;Kubernetes API v1.21.1&lt;/li&gt;
&lt;li&gt;kubectl v1.21.5&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="same-resource-different-api-groups"&gt;Same resource, different API Groups
&lt;/h3&gt;&lt;p&gt;In Kubernetes API 1.21, there are some different API Groups for the same kind of resource.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Event
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#event-v1-events-k8s-io" target="_blank" rel="noopener"
 &gt;Event v1 events.k8s.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#event-v1-core" target="_blank" rel="noopener"
 &gt;Event v1 core&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#-strong-old-api-versions-strong-" target="_blank" rel="noopener"
 &gt;OLD API VERSIONS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# in Kubernetes 1.21, there are two different API Groups for Events resource&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl api-resources &lt;span class="p"&gt;|&lt;/span&gt; grep event
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;events ev v1 &lt;span class="nb"&gt;true&lt;/span&gt; Event
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;events ev events.k8s.io/v1 &lt;span class="nb"&gt;true&lt;/span&gt; Event&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But if we specify &amp;ldquo;events&amp;rdquo; resource with kubectl 1.21, it will be treated as &amp;ldquo;Event v1 core&amp;rdquo;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# create a serviceaccount with permissions to view only &amp;#34;Event v1 core&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n default create serviceaccount user01
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n default create role event-corev1-reader --verb&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;get,list&amp;#34;&lt;/span&gt; --resource&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;events&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n default create rolebinding event-corev1-reader --role&lt;span class="o"&gt;=&lt;/span&gt;event-corev1-reader --serviceaccount&lt;span class="o"&gt;=&lt;/span&gt;default:user01
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Check the permissions of the serviceaccount&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# https://kubernetes.io/docs/tasks/run-application/access-api-from-pod/#without-using-a-proxy &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n default run nginx --image&lt;span class="o"&gt;=&lt;/span&gt;nginx --restart&lt;span class="o"&gt;=&lt;/span&gt;Never --rm -it --overrides&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;{ &amp;#34;spec&amp;#34;: { &amp;#34;serviceAccountName&amp;#34; : &amp;#34;user01&amp;#34; } }&amp;#39;&lt;/span&gt; -- /bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# The serviceaccount can list &amp;#34;Event v1 core&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;(&lt;/span&gt;root@nginx&lt;span class="o"&gt;)&lt;/span&gt;$ curl -I -X GET -k https://kubernetes.default.svc/api/v1/namespaces/default/events -H &lt;span class="s2"&gt;&amp;#34;Authorization: Bearer &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;cat /var/run/secrets/kubernetes.io/serviceaccount/token&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;HTTP/2 &lt;span class="m"&gt;200&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# The serviceaccount is not allowed to list &amp;#34;Event v1 events.k8s.io&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;(&lt;/span&gt;root@nginx&lt;span class="o"&gt;)&lt;/span&gt;$ curl -I -X GET -k https://kubernetes.default.svc/apis/events.k8s.io/v1/namespaces/default/events -H &lt;span class="s2"&gt;&amp;#34;Authorization: Bearer &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;cat /var/run/secrets/kubernetes.io/serviceaccount/token&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;HTTP/2 &lt;span class="m"&gt;403&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So, how can we specify the API Group &amp;ldquo;events.k8s.io&amp;rdquo; with kubectl?&lt;/p&gt;
&lt;p&gt;According to the help, we can use the expression &lt;code&gt;&amp;lt;Resource&amp;gt;.&amp;lt;API Group&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create role --help
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Usage:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubectl create role NAME --verb&lt;span class="o"&gt;=&lt;/span&gt;verb --resource&lt;span class="o"&gt;=&lt;/span&gt;resource.group/subresource
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;--resource-name&lt;span class="o"&gt;=&lt;/span&gt;resourcename&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;--dry-run&lt;span class="o"&gt;=&lt;/span&gt;server&lt;span class="p"&gt;|&lt;/span&gt;client&lt;span class="p"&gt;|&lt;/span&gt;none&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;options&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This expression can be used with other kubectl subcommands such as &lt;code&gt;kubectl auth can-i&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# create a serviceaccount with permissions to view only &amp;#34;Event v1 events.k8s.io&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n default create serviceaccount user02
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n default create role event-eventsk8siov1-reader --verb&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;get,list&amp;#34;&lt;/span&gt; --resource&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;events.events.k8s.io&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n default create rolebinding event-eventsk8siov1-reader --role&lt;span class="o"&gt;=&lt;/span&gt;event-eventsk8siov1-reader --serviceaccount&lt;span class="o"&gt;=&lt;/span&gt;default:user02
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# user01 can view only &amp;#34;Event v1 core&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n default auth can-i get events --as system:serviceaccount:default:user01
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;yes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n default auth can-i get events.events.k8s.io --as system:serviceaccount:default:user01
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;no
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# user02 can view only &amp;#34;Event v1 events.k8s.io&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n default auth can-i get events --as system:serviceaccount:default:user02
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;no
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n default auth can-i get events.events.k8s.io --as system:serviceaccount:default:user02
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;yes&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;(The following is the same content in Japanese.)&lt;/p&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;リソースが同じでもAPI Groupが異なるものを&lt;code&gt;kubectl&lt;/code&gt;で指定したいときは&lt;code&gt;&amp;lt;Resource&amp;gt;.&amp;lt;API Group&amp;gt;&lt;/code&gt;とすれば良い。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# &amp;#34;Event v1 core&amp;#34;と&amp;#34;Event v1 events.k8s.io&amp;#34;をそれぞれ指定して権限を確認する例&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl auth can-i get events
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl auth can-i get events.events.k8s.io&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="環境"&gt;環境
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;Kubernetes API v1.21.1&lt;/li&gt;
&lt;li&gt;kubectl v1.21.5&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="同じリソース名でapi-versionが複数あるとき"&gt;同じリソース名でAPI versionが複数あるとき
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Kubernetes API&lt;/code&gt;ではv1.21時点で&lt;code&gt;Event&lt;/code&gt;の&lt;code&gt;API Group&lt;/code&gt;が&lt;a class="link" href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#event-v1-events-k8s-io" target="_blank" rel="noopener"
 &gt;events.k8s.io&lt;/a&gt;になっていて、&lt;br&gt;
それまであった&lt;a class="link" href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#event-v1-core" target="_blank" rel="noopener"
 &gt;core&lt;/a&gt;版の&lt;code&gt;Event&lt;/code&gt;は&lt;a class="link" href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#-strong-old-api-versions-strong-" target="_blank" rel="noopener"
 &gt;OLD API VERSIONS&lt;/a&gt;という扱い。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1.22時点では2種類のAPI Groupが存在する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl api-resources &lt;span class="p"&gt;|&lt;/span&gt; grep event
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;events ev v1 &lt;span class="nb"&gt;true&lt;/span&gt; Event
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;events ev events.k8s.io/v1 &lt;span class="nb"&gt;true&lt;/span&gt; Event&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;しかし、v1.22の&lt;code&gt;kubectl&lt;/code&gt;で普通に&lt;code&gt;events&lt;/code&gt;に対する&lt;code&gt;Role&lt;/code&gt;を作成すると&lt;code&gt;API Group&lt;/code&gt;が&lt;code&gt;core&lt;/code&gt;で指定されてしまう。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# &amp;#34;event&amp;#34;を指定してRoleを作成する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n default create serviceaccount user01
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n default create role event-corev1-reader --verb&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;get,list&amp;#34;&lt;/span&gt; --resource&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;events&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n default create rolebinding event-corev1-reader --role&lt;span class="o"&gt;=&lt;/span&gt;event-corev1-reader --serviceaccount&lt;span class="o"&gt;=&lt;/span&gt;default:user01
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podを立てて確認してみる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# https://kubernetes.io/docs/tasks/run-application/access-api-from-pod/#without-using-a-proxy &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n default run nginx --image&lt;span class="o"&gt;=&lt;/span&gt;nginx --restart&lt;span class="o"&gt;=&lt;/span&gt;Never --rm -it --overrides&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;{ &amp;#34;spec&amp;#34;: { &amp;#34;serviceAccountName&amp;#34; : &amp;#34;user01&amp;#34; } }&amp;#39;&lt;/span&gt; -- /bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# coreのAPIは利用可能&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;(&lt;/span&gt;root@nginx&lt;span class="o"&gt;)&lt;/span&gt;$ curl -I -X GET -k https://kubernetes.default.svc/api/v1/namespaces/default/events -H &lt;span class="s2"&gt;&amp;#34;Authorization: Bearer &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;cat /var/run/secrets/kubernetes.io/serviceaccount/token&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;HTTP/2 &lt;span class="m"&gt;200&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# events.k8s.ioのAPIは認可エラーで利用不可&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;(&lt;/span&gt;root@nginx&lt;span class="o"&gt;)&lt;/span&gt;$ curl -I -X GET -k https://kubernetes.default.svc/apis/events.k8s.io/v1/namespaces/default/events -H &lt;span class="s2"&gt;&amp;#34;Authorization: Bearer &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;cat /var/run/secrets/kubernetes.io/serviceaccount/token&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;HTTP/2 &lt;span class="m"&gt;403&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;じゃあ&lt;code&gt;k8s.events.io&lt;/code&gt;版への権限はどうやって付与するんだろう?と試行錯誤していたら、helpにちゃんと書いてあった&amp;hellip;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create role --help
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Usage:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubectl create role NAME --verb&lt;span class="o"&gt;=&lt;/span&gt;verb --resource&lt;span class="o"&gt;=&lt;/span&gt;resource.group/subresource
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;--resource-name&lt;span class="o"&gt;=&lt;/span&gt;resourcename&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;--dry-run&lt;span class="o"&gt;=&lt;/span&gt;server&lt;span class="p"&gt;|&lt;/span&gt;client&lt;span class="p"&gt;|&lt;/span&gt;none&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;options&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;リソースの後に続いて&lt;code&gt;.&amp;lt;API Group&amp;gt;&lt;/code&gt;を指定すればいいらしい。&lt;br&gt;
(何も指定しない場合はcoreになるっぽい?)&lt;/p&gt;
&lt;p&gt;この方法で再度&lt;code&gt;Role&lt;/code&gt;を指定しなおす。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n default create serviceaccount user02
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n default create role event-eventsk8siov1-reader --verb&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;get,list&amp;#34;&lt;/span&gt; --resource&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;events.events.k8s.io&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n default create rolebinding event-eventsk8siov1-reader --role&lt;span class="o"&gt;=&lt;/span&gt;event-eventsk8siov1-reader --serviceaccount&lt;span class="o"&gt;=&lt;/span&gt;default:user02&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;他のコマンドでリソースを指定するときも同様にできるらしいので、今度は&lt;code&gt;Pod&lt;/code&gt;を建てずに&lt;code&gt;kubectl auth&lt;/code&gt;で確認してみる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# user01: core版のみの閲覧権限&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n default auth can-i get events --as system:serviceaccount:default:user01
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;yes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n default auth can-i get events.events.k8s.io --as system:serviceaccount:default:user01
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;no
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# user02: events.k8s.io版のみの閲覧権限&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n default auth can-i get events --as system:serviceaccount:default:user02
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;no
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n default auth can-i get events.events.k8s.io --as system:serviceaccount:default:user02
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;yes&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;やったぜ。&lt;/p&gt;
&lt;p&gt;異なる&lt;code&gt;API Group&lt;/code&gt;を&lt;code&gt;kubectl&lt;/code&gt;で指定できた。&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;ちゃんとヘルプを読んでいればなんてことない話だったんだけど、&lt;br&gt;
自分は数時間ムダにしてしまったのでメモにした。&lt;/p&gt;
&lt;p&gt;やっぱり公式ドキュメントやヘルプを読むのは大事。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="ごろごろするねこ" class="gallery-image" data-flex-basis="456px" data-flex-grow="190" height="2119" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2022-01-20-kubectl-specify-api-group/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2022-01-20-kubectl-specify-api-group/sotochan_hu_a271e5c4eda2374a.jpg 800w, https://blog.uzimihsr.com/post/2022-01-20-kubectl-specify-api-group/sotochan_hu_54f2badf5b6f68fc.jpg 1600w, https://blog.uzimihsr.com/post/2022-01-20-kubectl-specify-api-group/sotochan_hu_cb57ffa045977032.jpg 2400w, https://blog.uzimihsr.com/post/2022-01-20-kubectl-specify-api-group/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>12月のそとちゃん(2021)</title><link>https://blog.uzimihsr.com/post/2021-12-31-sotochan/</link><pubDate>Thu, 30 Dec 2021 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2021-12-31-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan.jpeg" alt="Featured image of post 12月のそとちゃん(2021)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e6%89%8b%e8%a1%93" &gt;手術&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e8%a1%93%e5%be%8c" &gt;術後&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%8c%e3%81%be%e3%82%93" &gt;がまん&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e6%8a%9c%e7%b3%b8" &gt;抜糸&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="手術"&gt;手術
&lt;/h3&gt;&lt;p&gt;今月は&lt;a class="link" href="https://uzimihsr.github.io/post/2021-12-06-sotochan/#%e7%97%85%e9%99%a2" target="_blank" rel="noopener"
 &gt;首にできた腫瘤&lt;/a&gt;の手術があった。&lt;/p&gt;
&lt;p&gt;手術当日のそとちゃんはいつもどおり余裕ぶっこき状態。&lt;br&gt;
それまで毎日そとちゃんと手術について(日本語で)話してはいたけど、&lt;br&gt;
結局自分がなにをされるのかは最後まで理解していないようだった。&lt;br&gt;
(それはそう😭)&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;御守りを食べるねこ &lt;a href="https://t.co/Bhp7rYojVW"&gt;pic.twitter.com/Bhp7rYojVW&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1471470971727261696?ref_src=twsrc%5Etfw"&gt;December 16, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;余裕ぶっこいてる &lt;a href="https://t.co/JZpgtiQZoN"&gt;pic.twitter.com/JZpgtiQZoN&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1471640352822280192?ref_src=twsrc%5Etfw"&gt;December 17, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;今回は日帰り手術ということで、&lt;br&gt;
朝に診察を行い、昼は検査と手術、術後の様子を診て夕方に引き取りという流れ。&lt;/p&gt;
&lt;p&gt;まずは診察。&lt;/p&gt;
&lt;p&gt;これはそとちゃんというより俺のための時間という感じだった。&lt;br&gt;
当日のそとちゃんの健康状態(食欲や遊ぶ元気)について軽く聞かれた後、&lt;br&gt;
全身麻酔に関する説明と手術についての詳細、術後に気をつけるべきことなどについてもう一度丁寧に説明してもらい、&lt;br&gt;
最後に承諾書のサインと押印を確認した。&lt;/p&gt;
&lt;p&gt;一通りの説明を受けた後、最後にそとちゃんを少し抱きしめてから先生に預けた。&lt;br&gt;
万が一のことがあればこれが最後の別れになるかもしれないと思って、恥ずかしながらこのとき少し泣いてしまった。😢&lt;/p&gt;
&lt;p&gt;(ここからは手術前後に先生から説明を受けた内容)&lt;/p&gt;
&lt;p&gt;次に検査。&lt;/p&gt;
&lt;p&gt;全身麻酔には当然ながらリスクがあるので、&lt;br&gt;
事故の可能性を最低限に抑えるために必ず術前に血液検査とX線検査が行われる。&lt;br&gt;
先生によるとそとちゃんは注射は平気だったものの、X線検査で仰向けにされたときにめちゃくちゃ暴れたらしい。&lt;br&gt;
(普段ひたすらごろごろしてるくせに、強制されるのは嫌😓)&lt;/p&gt;
&lt;p&gt;検査結果に問題がなかったので麻酔をかけて施術が行われた。&lt;br&gt;
切開から縫合までは十数分で終了し、その後そとちゃんはゆっくり目を醒ました。&lt;/p&gt;
&lt;p&gt;&lt;img alt="マンガみたいな手術痕" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan01_hu_7d65b38f1a47760c.jpeg 800w, https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan01_hu_fe6da9a7fd33bcb9.jpeg 1600w, https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="切除した腫瘤" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan02_hu_aef122b92094e8f1.jpeg 800w, https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan02_hu_3ba3e9c126a9659e.jpeg 1600w, https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan02.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;手術の間はずっと心配でソワソワしていたので、術後に電話で連絡が来たときは本当に安心した。😭&lt;/p&gt;
&lt;h3 id="術後"&gt;術後
&lt;/h3&gt;&lt;p&gt;電話をもらった後も念のために病院で少し様子を診てもらい、&lt;br&gt;
夕方ごろにそとちゃんを引き取りに行った。&lt;/p&gt;
&lt;p&gt;診察室で5時間ぶりに対面したそとちゃんは少し不機嫌だった。😡&lt;br&gt;
引き取りの直前におしっこを漏らしてしまったようで、&lt;br&gt;
看護師さんにおしりを拭かれたのが気にいらなかったらしい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="自分のおしりは自分できれいにしたい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan03_hu_f3235b42ebc062e6.jpeg 800w, https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan03_hu_c68ada07ab408c20.jpeg 1600w, https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan03.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;その場で先生から血液検査とX線検査の結果を説明してもらった。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;血液検査の数値はおおむね問題なしだが、クレアチニンとグロブリンの値が少し高め
&lt;ul&gt;
&lt;li&gt;グロブリンは免疫が活発なときに高い数値になるもので、おそらく猫風邪の後遺症(右目の目ヤニができやすい原因)によるものだろうから仕方ない&lt;/li&gt;
&lt;li&gt;クレアチニンは腎臓の機能が低下したときに高くなる値なので、3ヶ月後を目安に再検査が必要😱&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;X線検査では肺や内臓に問題なく、その他の腫瘤などもない&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="血液検査の結果" class="gallery-image" data-flex-basis="354px" data-flex-grow="147" height="1343" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan04_hu_653d021ff22fbb05.jpeg 800w, https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan04_hu_658a18a2c782995e.jpeg 1600w, https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan04.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;切除した腫瘤は病理検査に送って1週間後に結果が返ってくるとのことで、&lt;br&gt;
順調にいけばそのタイミングで抜糸できるかも?とのことだった。&lt;/p&gt;
&lt;p&gt;ちなみに手術代の見積もりで病理検査の費用が漏れていたらしく、実際の請求額はかなり高くついてしまった&amp;hellip;😭&lt;/p&gt;
&lt;p&gt;&lt;img alt="金が飛んでいく" class="gallery-image" data-flex-basis="396px" data-flex-grow="165" height="1202" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan06_hu_8b5ec14b257b6e43.jpeg 800w, https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan06_hu_fad68505dfc4dc28.jpeg 1600w, https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan06.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;病院から家に帰った後のそとちゃんは流石に少しぐったりしていたものの、ちょっとしてすぐにわんわん騒ぎ出した。&lt;br&gt;
手術のタイミングで胃を空っぽにする都合で前日の夜から何も食べさせていなかったので、ほぼ丸一日ぶんお腹を空かせていたのだった。😭&lt;/p&gt;
&lt;p&gt;手術痕から感染症にかからないための抗生剤(かなり苦い)をすりつぶしてちゅーるに混ぜてあげたところ、ものすごい勢いで完食。&lt;br&gt;
術後は弱っていると思っていたが食欲があるようで安心した。🙏&lt;/p&gt;
&lt;p&gt;&lt;img alt="お薬" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan05_hu_92e3452ed3876d12.jpeg 800w, https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan05_hu_e58f35b1fa147e90.jpeg 1600w, https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan05.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ちゅーる(抗生物質入り)&lt;br&gt;爆速 &lt;a href="https://t.co/B32HKTD6IA"&gt;pic.twitter.com/B32HKTD6IA&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1471797473756987394?ref_src=twsrc%5Etfw"&gt;December 17, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;h3 id="がまん"&gt;がまん
&lt;/h3&gt;&lt;p&gt;手術後は我慢の1週間だった。&lt;/p&gt;
&lt;p&gt;そとちゃんは元気なのに、手術痕を守るためのカラーが邪魔でうまく遊べない。😢&lt;br&gt;
カラーをつけた状態でできる遊びにもだんだん飽きてしまって、結局ほとんど寝て過ごしていた。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;いっぱい寝ててえらい &lt;a href="https://t.co/9yw10506Wr"&gt;pic.twitter.com/9yw10506Wr&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1472428879130558464?ref_src=twsrc%5Etfw"&gt;December 19, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;あとはトイレが大変だった。&lt;br&gt;
いつもはトイレの後自分でおしりをなめてきれいにできるのに、カラーのせいで舌が届かず汚れたままになっていることが何度かあった。&lt;br&gt;
ウエットタオルで拭くようにしていたが、そとちゃんはやっぱりおしりを拭かれるのが嫌いなのでちょっとかわいそうだった。😭&lt;/p&gt;
&lt;p&gt;&lt;img alt="カラーが邪魔だと思って用意したフタなしトイレは結局ほとんど使わなかった" class="gallery-image" data-flex-basis="308px" data-flex-grow="128" height="1544" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan07_hu_9406a456cbb3a282.jpeg 800w, https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan07_hu_2d92bc43f51ca753.jpeg 1600w, https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan07.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;一番大変だったのはかゆみとの戦い。&lt;br&gt;
手術痕がカラーに微妙に当たる位置で、かゆいのに舌で舐められない様子は見ていてつらそうだった。&lt;br&gt;
後ろ脚の爪をカラーの隙間から無理やり入れて手術痕を掻こうとすることもあったので、なかなか目が話せなかった&amp;hellip;&lt;/p&gt;
&lt;p&gt;そとちゃんがずっと苦しい思いをしていたので、俺もこの1週間はほぼ家から出ずにつきっきりでみていた。&lt;br&gt;
つくづく在宅勤務でよかった。&lt;/p&gt;
&lt;h3 id="抜糸"&gt;抜糸
&lt;/h3&gt;&lt;p&gt;1週間耐え抜いた後、腫瘤の検査結果が届いたとのことで再度病院へ。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;抜糸できるか診てもらいにいく&lt;br&gt;いつもよりビビってる &lt;a href="https://t.co/SPE3hkiZLG"&gt;pic.twitter.com/SPE3hkiZLG&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1474543422552047616?ref_src=twsrc%5Etfw"&gt;December 25, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;病理検査の結果、今回切除した腫瘤は&lt;a class="link" href="http://www.idexxjp.com/manual/skin03/" target="_blank" rel="noopener"
 &gt;毛包嚢胞&lt;/a&gt;ということで、&lt;br&gt;
人間で言えばニキビとか粉瘤に近いもの?らしかった。&lt;/p&gt;
&lt;p&gt;悪性腫瘍でなくて本当によかった&amp;hellip;😌&lt;br&gt;
完全に切除されていて再発のおそれも低いということなので、これで一安心。&lt;/p&gt;
&lt;p&gt;&lt;img alt="病理検査の結果" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan09.jpeg" srcset="https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan09_hu_3b989e884003a8fd.jpeg 800w, https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan09_hu_a90a5a3c614c3601.jpeg 1600w, https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan09.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;手術痕もきれいにふさがっていたので、その場で抜糸してもらった。&lt;br&gt;
手術と検査で病院が嫌になっちゃったのか、そとちゃんは珍しく暴れたけどなんとか無事に糸を全部外すことができた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="きれいにふさがった" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan08_hu_7d13ac6c8e189bce.jpeg 800w, https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan08_hu_84b0dcd956da2aab.jpeg 1600w, https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan08.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;帰宅後、カラーが外れて7日ぶりの自由を取り戻したそとちゃんはやりたい放題。😂&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;抜糸成功 &lt;a href="https://t.co/qm0q0U2PbS"&gt;pic.twitter.com/qm0q0U2PbS&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1474559477529858048?ref_src=twsrc%5Etfw"&gt;December 25, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;カラーが邪魔でなかなか登れなかったキャットタワーや本棚の上に昇って降りてを繰り返し、&lt;br&gt;
部屋中をものすごい勢いで走り回って手がつけられなかった。🌪&lt;/p&gt;
&lt;p&gt;ちなみにカラーがなくなって手術痕(ふさがってはいるが&amp;hellip;)を思いっきり掻こうとしたので、&lt;br&gt;
この後カラーをつけて外してを何回か繰り返した。😅&lt;/p&gt;
&lt;p&gt;&lt;img alt="わるいねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan10.jpeg" srcset="https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan10_hu_920222bcb4a3972.jpeg 800w, https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan10_hu_1d83b5293ecd12f2.jpeg 1600w, https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan10.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;なにはともあれそとちゃんが無事で本当によかった。&lt;br&gt;
手術前はごはんをもらえず、手術後はカラーをつけられてかわいそうだったがよく耐えてとてもえらかった。👏&lt;/p&gt;
&lt;p&gt;術後の生活が大変すぎて、気がついたらクリスマスが終わっていた&amp;hellip;&lt;br&gt;
去年と違う衣装も用意していたが、手術後に着せるわけにもいかないので来年まで残しておくことにする。&lt;/p&gt;
&lt;p&gt;今年もそとちゃんはずっと元気だったけど、最後に手術があって大変だった。&lt;br&gt;
2022年はそとちゃんの健康により一層気をつけて、幸せに過ごせるようにしたい。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="おしりをガン舐めするそとちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan_hu_8e59ee2abd228393.jpeg 800w, https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan_hu_1c489b2dc37f856b.jpeg 1600w, https://blog.uzimihsr.com/post/2021-12-31-sotochan/sotochan.jpeg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>Add a cronjob-name label to Kubernetes Jobs with Mutating Admission Webhook</title><link>https://blog.uzimihsr.com/post/2021-12-18-kubernetes-mutating-admission-webhook-add-label-to-job/</link><pubDate>Sat, 18 Dec 2021 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2021-12-18-kubernetes-mutating-admission-webhook-add-label-to-job/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2021-12-18-kubernetes-mutating-admission-webhook-add-label-to-job/sotochan.jpg" alt="Featured image of post Add a cronjob-name label to Kubernetes Jobs with Mutating Admission Webhook" /&gt;&lt;p&gt;(最後に日本語版があります)&lt;/p&gt;
&lt;h2 id="cronjob-name-labels-admission-webhook"&gt;cronjob-name labels admission webhook
&lt;/h2&gt;&lt;p&gt;Kubernetes Pods owned by Job have a &lt;strong&gt;job-name&lt;/strong&gt; label, so you can easily filter Pods by the name of the owner Job with label selector.&lt;br&gt;
Meanwhile, Jobs owned by CronJob don&amp;rsquo;t have such one.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# filter Pods by Job with labelSelector&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pod -l job-name&lt;span class="o"&gt;=&lt;/span&gt;my-job
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-job-zm4p4 0/1 Completed &lt;span class="m"&gt;0&lt;/span&gt; 25h
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Jobs do not have any labels related to the owner CronJob&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get job --show-labels
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME COMPLETIONS DURATION AGE LABELS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-cronjob-27322002 1/1 2s 2m26s controller-uid&lt;span class="o"&gt;=&lt;/span&gt;43e62299-838b-4f9a-96b7-e35cfc82a2ec,job-name&lt;span class="o"&gt;=&lt;/span&gt;my-cronjob-27322002
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-cronjob-27322003 1/1 2s 86s controller-uid&lt;span class="o"&gt;=&lt;/span&gt;56130637-ae62-42f4-b8f5-f5248c929ec0,job-name&lt;span class="o"&gt;=&lt;/span&gt;my-cronjob-27322003
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-cronjob-27322004 1/1 3s 26s controller-uid&lt;span class="o"&gt;=&lt;/span&gt;308090e7-2bdb-4960-bd38-ff88b3c0aaf0,job-name&lt;span class="o"&gt;=&lt;/span&gt;my-cronjob-27322004
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-job 1/1 3s 25h controller-uid&lt;span class="o"&gt;=&lt;/span&gt;3369540c-552b-438c-8767-8808d9c42fe6,job-name&lt;span class="o"&gt;=&lt;/span&gt;my-job&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Of course, Jobs also have a field called &lt;code&gt;OwnerReferences&lt;/code&gt; which has the name of the owner CronJob, but it can&amp;rsquo;t be used for filtering Jobs.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# metadata.ownerReferences have the name of the owner CronJob&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get job my-cronjob-27322004 -o &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;{.metadata.ownerReferences[0].name}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-cronjob
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ownerReferences cannot be used to filter Job&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get job --field-selector &lt;span class="s2"&gt;&amp;#34;.metadata.ownerReferences[0].name=my-cronjob&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Error from server &lt;span class="o"&gt;(&lt;/span&gt;BadRequest&lt;span class="o"&gt;)&lt;/span&gt;: Unable to find &lt;span class="s2"&gt;&amp;#34;batch/v1, Resource=jobs&amp;#34;&lt;/span&gt; that match label selector &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;, field selector &lt;span class="s2"&gt;&amp;#34;.metadata.ownerReferences[0].name=my-cronjob&amp;#34;&lt;/span&gt;: field label &lt;span class="s2"&gt;&amp;#34;.metadata.ownerReferences[0].name&amp;#34;&lt;/span&gt; not supported &lt;span class="k"&gt;for&lt;/span&gt; Job&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Therefore, when there are many Jobs in the Cluster, it is difficult to find the Jobs by the name of the owner CronJob.&lt;br&gt;
Of course you can use &lt;code&gt;grep&lt;/code&gt; or &lt;code&gt;jq&lt;/code&gt; with &lt;code&gt;kubectl&lt;/code&gt;, but it is sometimes not fast :(&lt;/p&gt;
&lt;p&gt;To solve this problem, I created my own &lt;a class="link" href="https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/" target="_blank" rel="noopener"
 &gt;Mutating Admission Webhook&lt;/a&gt; for the first time.&lt;br&gt;
&lt;a class="link" href="https://github.com/uzimihsr/cronjob-name-labels-admission-webhook" target="_blank" rel="noopener"
 &gt;https://github.com/uzimihsr/cronjob-name-labels-admission-webhook&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Jobs have a cronjob-name label and it can be used for filtering&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get job -l uzimihsr.github.io/cronjob-name&lt;span class="o"&gt;=&lt;/span&gt;my-cronjob --show-labels
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME COMPLETIONS DURATION AGE LABELS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-cronjob-27322012 1/1 2s 2m26s uzimihsr.github.io/cronjob-name&lt;span class="o"&gt;=&lt;/span&gt;my-cronjob
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-cronjob-27322013 1/1 2s 86s uzimihsr.github.io/cronjob-name&lt;span class="o"&gt;=&lt;/span&gt;my-cronjob
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-cronjob-27322014 1/1 2s 26s uzimihsr.github.io/cronjob-name&lt;span class="o"&gt;=&lt;/span&gt;my-cronjob&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="prerequisites"&gt;Prerequisites
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Kubernetes v1.21.1&lt;/li&gt;
&lt;li&gt;kind v0.11.1&lt;/li&gt;
&lt;li&gt;Go 1.17.3&lt;/li&gt;
&lt;li&gt;OpenSSL 3.0.0&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="how-it-works"&gt;How it works
&lt;/h2&gt;&lt;p&gt;&lt;img alt="composition" class="gallery-image" data-flex-basis="515px" data-flex-grow="214" height="794" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-12-18-kubernetes-mutating-admission-webhook-add-label-to-job/fig01.png" srcset="https://blog.uzimihsr.com/post/2021-12-18-kubernetes-mutating-admission-webhook-add-label-to-job/fig01_hu_419a84f4add0a16c.png 800w, https://blog.uzimihsr.com/post/2021-12-18-kubernetes-mutating-admission-webhook-add-label-to-job/fig01_hu_70ef17b2fc44b1f.png 1600w, https://blog.uzimihsr.com/post/2021-12-18-kubernetes-mutating-admission-webhook-add-label-to-job/fig01.png 1705w" width="1705"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/" target="_blank" rel="noopener"
 &gt;Mutating Admission Webhook&lt;/a&gt; works as an HTTP server that returns &lt;a class="link" href="https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#response" target="_blank" rel="noopener"
 &gt;responses&lt;/a&gt; to &lt;a class="link" href="https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#request" target="_blank" rel="noopener"
 &gt;admission requests&lt;/a&gt; and we can make it with any language.&lt;br&gt;
In this case, I used the &lt;a class="link" href="https://github.com/kubernetes/kubernetes/blob/v1.21.1/test/images/agnhost/webhook/addlabel.go" target="_blank" rel="noopener"
 &gt;webhook example&lt;/a&gt; written in Go.&lt;/p&gt;
&lt;p&gt;This HTTP server works as follows;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Convert the request body to &lt;a class="link" href="https://pkg.go.dev/k8s.io/api/admission/v1#AdmissionReview" target="_blank" rel="noopener"
 &gt;admission.k8s.io/v1.AdmissionReview&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;If the requested resource(Job) is owned by any CronJob, create a &lt;a class="link" href="http://jsonpatch.com/" target="_blank" rel="noopener"
 &gt;JSON Patch&lt;/a&gt; to add the label &lt;strong&gt;&amp;ldquo;uzimihsr.github.io/cronjob-name={Job.metadata.ownerReferences[0].name}&amp;rdquo;&lt;/strong&gt;.
&lt;ul&gt;
&lt;li&gt;You must &lt;a class="link" href="http://jsonpatch.com/#json-pointer" target="_blank" rel="noopener"
 &gt;escape&lt;/a&gt; &lt;code&gt;/&lt;/code&gt; in a JSON key.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Convert the JSON Patch to &lt;a class="link" href="https://pkg.go.dev/k8s.io/api/admission/v1#AdmissionReview" target="_blank" rel="noopener"
 &gt;admission.k8s.io/v1.AdmissionReview&lt;/a&gt; and return it.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The HTTP server can be located anywhere as long as it is reachable from the Kubernetes API, but I preferred to run it as &lt;code&gt;Deployment&lt;/code&gt; in the cluster.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;TLS Secret&lt;/code&gt; is needed because the admission webhook requires a TLS connection between the Kubernetes API and the HTTP server.&lt;br&gt;
If the HTTP server runs in the cluster, self-signed certificate is sufficient.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;ClusterIP Service&lt;/code&gt; exposes the &lt;code&gt;Pod&lt;/code&gt; to the cluster.&lt;br&gt;
It is referenced as &lt;strong&gt;&amp;quot;(service-name).(service-namespace).svc”&lt;/strong&gt; from within the cluster, so the certificate of the &lt;code&gt;TLS Secret&lt;/code&gt; must have that name as SANs.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;MutatingWebhookConfiguration&lt;/code&gt; allows the Kubernetes API to send admission requests to the HTTP server.&lt;br&gt;
It contains the conditions to send webhooks and &lt;a class="link" href="https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#service-reference" target="_blank" rel="noopener"
 &gt;base64-encoded CA certificate&lt;/a&gt; of the self-signed certificate.&lt;/p&gt;
&lt;h2 id="how-to-install"&gt;How to install
&lt;/h2&gt;&lt;p&gt;The container image and manifest files are available on GitHub.&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/uzimihsr/cronjob-name-labels-admission-webhook#install" target="_blank" rel="noopener"
 &gt;https://github.com/uzimihsr/cronjob-name-labels-admission-webhook#install&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# generate a private key&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;openssl genrsa -out tls.key
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# create a self-signed certificate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Common Name (e.g. server FQDN or YOUR name) []:cronjob-name-labels-admission-webhook.default.svc (if you run Pod in the default namespace)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;openssl req -x509 -key tls.key -out tls.crt -days &lt;span class="m"&gt;3650&lt;/span&gt; -addext &lt;span class="s1"&gt;&amp;#39;subjectAltName = DNS:cronjob-name-labels-admission-webhook.default.svc&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# create a TLS Secret&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create secret tls cronjob-name-labels-admission-webhook-tls-secret --cert&lt;span class="o"&gt;=&lt;/span&gt;tls.crt --key&lt;span class="o"&gt;=&lt;/span&gt;tls.key
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# create Deployment, Service, and MutatingWebhookConfiguration&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# replace &amp;#34;CA_BUNDLE&amp;#34; in MutatingWebhookConfiguration by base64-encoded tls.crt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl https://raw.githubusercontent.com/uzimihsr/cronjob-name-labels-admission-webhook/main/manifests/manifest.yaml &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;|&lt;/span&gt; sed &lt;span class="s2"&gt;&amp;#34;s/CA_BUNDLE/&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;kubectl get secret cronjob-name-labels-admission-webhook-tls-secret -o &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;{.data.tls\.crt}&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/g&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;|&lt;/span&gt; kubectl apply -f -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Once all the resources have been successfully created and the &lt;code&gt;Pod&lt;/code&gt; is running, create some &lt;code&gt;CronJobs&lt;/code&gt; to verify the operation.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# create some CronJobs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create cronjob cronjob-a --image&lt;span class="o"&gt;=&lt;/span&gt;busybox --schedule&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;*/1 * * * *&amp;#34;&lt;/span&gt; -- date
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create cronjob cronjob-b --image&lt;span class="o"&gt;=&lt;/span&gt;busybox --schedule&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;*/1 * * * *&amp;#34;&lt;/span&gt; -- date
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create cronjob cronjob-c --image&lt;span class="o"&gt;=&lt;/span&gt;busybox --schedule&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;*/1 * * * *&amp;#34;&lt;/span&gt; -- date
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# create a &amp;#34;normal&amp;#34; Job (not owned by CronJob)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create job my-job --image&lt;span class="o"&gt;=&lt;/span&gt;busybox -- date&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Wait for while and check the &lt;code&gt;Jobs&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Jobs owned by CronJob have a cronjob-name label&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# The &amp;#34;normal&amp;#34; Job does not have the label&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get job --show-labels
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME COMPLETIONS DURATION AGE LABELS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-a-27322073 1/1 6s 2m23s uzimihsr.github.io/cronjob-name&lt;span class="o"&gt;=&lt;/span&gt;cronjob-a
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-a-27322074 1/1 5s 83s uzimihsr.github.io/cronjob-name&lt;span class="o"&gt;=&lt;/span&gt;cronjob-a
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-a-27322075 1/1 5s 23s uzimihsr.github.io/cronjob-name&lt;span class="o"&gt;=&lt;/span&gt;cronjob-a
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-b-27322073 1/1 2s 2m23s uzimihsr.github.io/cronjob-name&lt;span class="o"&gt;=&lt;/span&gt;cronjob-b
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-b-27322074 1/1 4s 83s uzimihsr.github.io/cronjob-name&lt;span class="o"&gt;=&lt;/span&gt;cronjob-b
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-b-27322075 1/1 3s 23s uzimihsr.github.io/cronjob-name&lt;span class="o"&gt;=&lt;/span&gt;cronjob-b
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-c-27322073 1/1 4s 2m23s uzimihsr.github.io/cronjob-name&lt;span class="o"&gt;=&lt;/span&gt;cronjob-c
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-c-27322074 1/1 2s 83s uzimihsr.github.io/cronjob-name&lt;span class="o"&gt;=&lt;/span&gt;cronjob-c
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-c-27322075 1/1 6s 23s uzimihsr.github.io/cronjob-name&lt;span class="o"&gt;=&lt;/span&gt;cronjob-c
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-job 1/1 8s 23s controller-uid&lt;span class="o"&gt;=&lt;/span&gt;27160b7f-65e0-4e48-aa6b-9319e162f422,job-name&lt;span class="o"&gt;=&lt;/span&gt;my-job
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Wow you can filter Jobs by CronJob :)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get job -l uzimihsr.github.io/cronjob-name&lt;span class="o"&gt;=&lt;/span&gt;cronjob-b
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME COMPLETIONS DURATION AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-b-27322073 1/1 2s 2m39s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-b-27322074 1/1 4s 99s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-b-27322075 1/1 3s 39s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I did it. It&amp;rsquo;s working!&lt;/p&gt;
&lt;p&gt;Finally, let&amp;rsquo;s compare the speed of filtering &lt;code&gt;Jobs&lt;/code&gt; by the name of the &lt;code&gt;CronJob&lt;/code&gt; with other methods.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# create 100 CronJobs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; i in &lt;span class="k"&gt;$(&lt;/span&gt;seq -w 100&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubectl create cronjob cronjob-&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; --image&lt;span class="o"&gt;=&lt;/span&gt;busybox --schedule&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;*/1 * * * *&amp;#34;&lt;/span&gt; -- date
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;## look for Jobs owned by the CronJob &amp;#34;cronjob-099&amp;#34; in different ways&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# kubectl + grep: 0.277(kubectl) + 0.276(grep) ≃ 0.5 sec.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;time&lt;/span&gt; kubectl get job &lt;span class="p"&gt;|&lt;/span&gt; grep cronjob-099
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-099-27322103 1/1 2m29s 6m33s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-099-27322104 1/1 5m35s 5m41s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-099-27322105 0/1 4m39s 4m39s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-099-27322106 0/1 3m55s 3m55s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-099-27322107 0/1 2m39s 2m39s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-099-27322108 0/1 109s 109s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-099-27322109 0/1 41s 42s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get job 0.25s user 0.04s system 105% cpu 0.277 total
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grep --color&lt;span class="o"&gt;=&lt;/span&gt;auto cronjob-099 0.00s user 0.00s system 2% cpu 0.276 total
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# kubectl + jq: 0.642(kubectl) + 0.648(jq) ≃ 1.2 sec.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;time&lt;/span&gt; kubectl get job -o json &lt;span class="p"&gt;|&lt;/span&gt; jq &lt;span class="s1"&gt;&amp;#39;.items[] | select(.metadata.ownerReferences[]?.name==&amp;#34;cronjob-099&amp;#34;) | .metadata.name&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;cronjob-099-27322103&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;cronjob-099-27322104&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;cronjob-099-27322105&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;cronjob-099-27322106&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;cronjob-099-27322107&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;cronjob-099-27322108&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;cronjob-099-27322109&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get job -o json 0.70s user 0.06s system 117% cpu 0.642 total
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;jq 0.08s user 0.01s system 13% cpu 0.648 total
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Label Selector &amp;#34;uzimihsr.github.io/cronjob-name&amp;#34; : ≃ 0.1 sec.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;time&lt;/span&gt; kubectl get job -l uzimihsr.github.io/cronjob-name&lt;span class="o"&gt;=&lt;/span&gt;cronjob-099
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME COMPLETIONS DURATION AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-099-27322103 1/1 2m29s 6m40s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-099-27322104 1/1 5m35s 5m48s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-099-27322105 0/1 4m46s 4m46s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-099-27322106 0/1 4m2s 4m2s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-099-27322107 0/1 2m46s 2m46s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-099-27322108 0/1 116s 116s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-099-27322109 0/1 48s 49s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-099-27322110 0/1 1s 1s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get job -l uzimihsr.github.io/cronjob-name&lt;span class="o"&gt;=&lt;/span&gt;cronjob-099 0.08s user 0.03s system 113% cpu 0.094 total&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Wow the label added by Mutating Admission Webhook makes it so fast to filter Jobs by the name of owner CronJob!&lt;/p&gt;
&lt;p&gt;Thank you for reading :)&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;(the following is the Japanese version.)&lt;/p&gt;
&lt;h2 id="つくったもの"&gt;つくったもの
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Kubernetes&lt;/code&gt;の&lt;code&gt;Job&lt;/code&gt;で起動した&lt;code&gt;Pod&lt;/code&gt;には&lt;strong&gt;job-name&lt;/strong&gt;というラベルがついている。&lt;br&gt;
これにより、&amp;ldquo;hogehogeというJobで起動されているPodの一覧が欲しい&amp;quot;といったときは&lt;code&gt;Kubernetes API&lt;/code&gt;へのリクエスト時に&lt;code&gt;labelSelector&lt;/code&gt;を指定することで絞り込みができる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# job-nameラベルを用いたPodの絞り込み&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pod -l job-name&lt;span class="o"&gt;=&lt;/span&gt;my-job
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-job-zm4p4 0/1 Completed &lt;span class="m"&gt;0&lt;/span&gt; 25h&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;しかし、&lt;code&gt;CronJob&lt;/code&gt;によって起動された&lt;code&gt;Job&lt;/code&gt;にはそのようなラベルがなく、&lt;br&gt;
&amp;ldquo;fugafugaというCronJobで起動されているJobの一覧が欲しい&amp;quot;というときに不便。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# JobにはCronJob名のラベルがない&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get job --show-labels
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME COMPLETIONS DURATION AGE LABELS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-cronjob-27322002 1/1 2s 2m26s controller-uid&lt;span class="o"&gt;=&lt;/span&gt;43e62299-838b-4f9a-96b7-e35cfc82a2ec,job-name&lt;span class="o"&gt;=&lt;/span&gt;my-cronjob-27322002
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-cronjob-27322003 1/1 2s 86s controller-uid&lt;span class="o"&gt;=&lt;/span&gt;56130637-ae62-42f4-b8f5-f5248c929ec0,job-name&lt;span class="o"&gt;=&lt;/span&gt;my-cronjob-27322003
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-cronjob-27322004 1/1 3s 26s controller-uid&lt;span class="o"&gt;=&lt;/span&gt;308090e7-2bdb-4960-bd38-ff88b3c0aaf0,job-name&lt;span class="o"&gt;=&lt;/span&gt;my-cronjob-27322004
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-job 1/1 3s 25h controller-uid&lt;span class="o"&gt;=&lt;/span&gt;3369540c-552b-438c-8767-8808d9c42fe6,job-name&lt;span class="o"&gt;=&lt;/span&gt;my-job&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;一応Jobは&lt;code&gt;metadata.ownerReferences&lt;/code&gt;というフィールドにどの&lt;code&gt;CronJob&lt;/code&gt;によって作成されたかの情報を持っているのだが、&lt;br&gt;
このフィールドは&lt;code&gt;fieldSelector&lt;/code&gt;に対応していないので少し使いづらい。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# metadata.ownerReferencesには一応CronJobの情報がある&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get job my-cronjob-27322004 -o &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;{.metadata.ownerReferences[0].name}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-cronjob
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# fieldSelectorで指定しようとするとエラーになる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get job --field-selector &lt;span class="s2"&gt;&amp;#34;.metadata.ownerReferences[0].name=my-cronjob&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Error from server &lt;span class="o"&gt;(&lt;/span&gt;BadRequest&lt;span class="o"&gt;)&lt;/span&gt;: Unable to find &lt;span class="s2"&gt;&amp;#34;batch/v1, Resource=jobs&amp;#34;&lt;/span&gt; that match label selector &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;, field selector &lt;span class="s2"&gt;&amp;#34;.metadata.ownerReferences[0].name=my-cronjob&amp;#34;&lt;/span&gt;: field label &lt;span class="s2"&gt;&amp;#34;.metadata.ownerReferences[0].name&amp;#34;&lt;/span&gt; not supported &lt;span class="k"&gt;for&lt;/span&gt; Job&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;このため、&lt;code&gt;CronJob&lt;/code&gt;を大量に使っているときに調べたい対象の&lt;code&gt;Job&lt;/code&gt;を絞るのが面倒で困っていた。&lt;br&gt;
&amp;hellip;だったら自分で&lt;strong&gt;cronjob-name&lt;/strong&gt;的なラベルをつけちゃえば良いのでは? と思い、&lt;br&gt;
最近勉強している&lt;a class="link" href="https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/" target="_blank" rel="noopener"
 &gt;admission webhook&lt;/a&gt;を使って実現してみた。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/uzimihsr/cronjob-name-labels-admission-webhook" target="_blank" rel="noopener"
 &gt;https://github.com/uzimihsr/cronjob-name-labels-admission-webhook&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# JobにCronJob名のラベルがついたのでlabelSelectorで絞り込める&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get job -l uzimihsr.github.io/cronjob-name&lt;span class="o"&gt;=&lt;/span&gt;my-cronjob --show-labels
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME COMPLETIONS DURATION AGE LABELS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-cronjob-27322012 1/1 2s 2m26s uzimihsr.github.io/cronjob-name&lt;span class="o"&gt;=&lt;/span&gt;my-cronjob
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-cronjob-27322013 1/1 2s 86s uzimihsr.github.io/cronjob-name&lt;span class="o"&gt;=&lt;/span&gt;my-cronjob 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-cronjob-27322014 1/1 2s 26s uzimihsr.github.io/cronjob-name&lt;span class="o"&gt;=&lt;/span&gt;my-cronjob&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Kubernetes v1.21.1&lt;/li&gt;
&lt;li&gt;kind v0.11.1&lt;/li&gt;
&lt;li&gt;Go 1.17.3&lt;/li&gt;
&lt;li&gt;OpenSSL 3.0.0&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="しくみ"&gt;しくみ
&lt;/h2&gt;&lt;p&gt;今回は下記のような構成でつくってみた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="こんなかんじ" class="gallery-image" data-flex-basis="515px" data-flex-grow="214" height="794" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-12-18-kubernetes-mutating-admission-webhook-add-label-to-job/fig01.png" srcset="https://blog.uzimihsr.com/post/2021-12-18-kubernetes-mutating-admission-webhook-add-label-to-job/fig01_hu_419a84f4add0a16c.png 800w, https://blog.uzimihsr.com/post/2021-12-18-kubernetes-mutating-admission-webhook-add-label-to-job/fig01_hu_70ef17b2fc44b1f.png 1600w, https://blog.uzimihsr.com/post/2021-12-18-kubernetes-mutating-admission-webhook-add-label-to-job/fig01.png 1705w" width="1705"&gt;&lt;/p&gt;
&lt;p&gt;まずは決められた形式の&lt;a class="link" href="https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#request" target="_blank" rel="noopener"
 &gt;リクエスト&lt;/a&gt;に対して&lt;a class="link" href="https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#response" target="_blank" rel="noopener"
 &gt;レスポンス&lt;/a&gt;を返すHTTPサーバーを&lt;code&gt;Deployment&lt;/code&gt;として立てる。&lt;br&gt;
Mutating Admission Webhookでラベルを付与する処理はGoで書かれた&lt;a class="link" href="https://github.com/kubernetes/kubernetes/blob/v1.21.1/test/images/agnhost/webhook/addlabel.go" target="_blank" rel="noopener"
 &gt;公式の例&lt;/a&gt;を参考にした。&lt;/p&gt;
&lt;p&gt;このサーバーの処理の流れとしては&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;リクエストボディを&lt;a class="link" href="https://pkg.go.dev/k8s.io/api/admission/v1#AdmissionReview" target="_blank" rel="noopener"
 &gt;admission.k8s.io/v1.AdmissionReview&lt;/a&gt;にパース&lt;/li&gt;
&lt;li&gt;リクエストされているリソース(&lt;code&gt;Job&lt;/code&gt;)のObjectをチェックし、対象のリソースがCronJobによって作成されている場合のみ &lt;strong&gt;&amp;ldquo;uzimihsr.github.io/cronjob-name=(CronJob名)&amp;rdquo;&lt;/strong&gt; のラベルを付与する&lt;a class="link" href="http://jsonpatch.com/" target="_blank" rel="noopener"
 &gt;JSON Patch&lt;/a&gt;を作成
&lt;ul&gt;
&lt;li&gt;今回はラベルのキーに&lt;code&gt;/&lt;/code&gt;が含まれるので、&lt;a class="link" href="http://jsonpatch.com/#json-pointer" target="_blank" rel="noopener"
 &gt;keyの指定方法&lt;/a&gt;に気をつけた&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;作成したJSONパッチを&lt;a class="link" href="https://pkg.go.dev/k8s.io/api/admission/v1#AdmissionReview" target="_blank" rel="noopener"
 &gt;admission.k8s.io/v1.AdmissionReview&lt;/a&gt;に詰めて返す&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;といった感じ。&lt;/p&gt;
&lt;p&gt;また、admission webhookでは対象のエンドポイントとの通信がTLS化されている必要があるので、&lt;br&gt;
オレオレ証明書の&lt;code&gt;TLS Secret&lt;/code&gt;を用意して&lt;code&gt;Pod&lt;/code&gt;にマウントして使用する。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Deployment&lt;/code&gt;が作成できたら、その&lt;code&gt;Pod&lt;/code&gt;を&lt;code&gt;ClusterIP Service&lt;/code&gt;でクラスタ内に公開する。&lt;br&gt;
このときクラスタ内から参照するホスト名が &lt;strong&gt;&amp;quot;(service-name).(service-namespace).svc&amp;rdquo;&lt;/strong&gt; となるので、前述の&lt;code&gt;TLS Secret&lt;/code&gt;のTLS証明書のSANsがこの名前を含む必要がある。&lt;/p&gt;
&lt;p&gt;最後に&lt;code&gt;MutatingWebhookConfiguration&lt;/code&gt;を作成すると、&lt;br&gt;
&lt;code&gt;Kubernetes API&lt;/code&gt;が指定されたAPIオブジェクトを操作するときに指定された&lt;code&gt;Service&lt;/code&gt;宛にwebhookするようになる。&lt;br&gt;
今回はオレオレ証明書を使用しているので、信頼するCA証明書(すなわちオレオレ証明書そのもの)をbase64エンコードしたものを&lt;code&gt;webhooks.clientConfig.caBundle&lt;/code&gt;に指定する。&lt;/p&gt;
&lt;h2 id="つかいかた"&gt;つかいかた
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Deployment&lt;/code&gt;用のimageと各種yamlファイルは&lt;code&gt;GitHub&lt;/code&gt;に用意しているので、&lt;br&gt;
あとはTLS証明書用の&lt;code&gt;Secret&lt;/code&gt;さえ用意すれば動くはず。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/uzimihsr/cronjob-name-labels-admission-webhook#install" target="_blank" rel="noopener"
 &gt;https://github.com/uzimihsr/cronjob-name-labels-admission-webhook#install&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 秘密鍵の作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;openssl genrsa -out tls.key
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# オレオレ証明書の作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Common Name (e.g. server FQDN or YOUR name) []:cronjob-name-labels-admission-webhook.default.svc とする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;openssl req -x509 -key tls.key -out tls.crt -days &lt;span class="m"&gt;3650&lt;/span&gt; -addext &lt;span class="s1"&gt;&amp;#39;subjectAltName = DNS:cronjob-name-labels-admission-webhook.default.svc&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# TLS Secretの作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create secret tls cronjob-name-labels-admission-webhook-tls-secret --cert&lt;span class="o"&gt;=&lt;/span&gt;tls.crt --key&lt;span class="o"&gt;=&lt;/span&gt;tls.key
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Deployment, Service, MutatingWebhookConfigurationの作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# MutatingWebhookConfigurationのcaBundlerはbase64化したtls.crtを指定する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl https://raw.githubusercontent.com/uzimihsr/cronjob-name-labels-admission-webhook/main/manifests/manifest.yaml &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;|&lt;/span&gt; sed &lt;span class="s2"&gt;&amp;#34;s/CA_BUNDLE/&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;kubectl get secret cronjob-name-labels-admission-webhook-tls-secret -o &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;{.data.tls\.crt}&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/g&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;|&lt;/span&gt; kubectl apply -f -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;すべてのリソースが作成できたら、動作確認用のCronJobを作成する。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# CronJobの作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create cronjob cronjob-a --image&lt;span class="o"&gt;=&lt;/span&gt;busybox --schedule&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;*/1 * * * *&amp;#34;&lt;/span&gt; -- date
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create cronjob cronjob-b --image&lt;span class="o"&gt;=&lt;/span&gt;busybox --schedule&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;*/1 * * * *&amp;#34;&lt;/span&gt; -- date
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create cronjob cronjob-c --image&lt;span class="o"&gt;=&lt;/span&gt;busybox --schedule&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;*/1 * * * *&amp;#34;&lt;/span&gt; -- date
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# CronじゃないJobの作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create job my-job --image&lt;span class="o"&gt;=&lt;/span&gt;busybox -- date&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;すこし放置して、&lt;code&gt;Job&lt;/code&gt;が起動したら結果を確認する。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# JobにCronJob名のラベルがついている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 手動で作ったJobのラベルはデフォルトのまま&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get job --show-labels
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME COMPLETIONS DURATION AGE LABELS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-a-27322073 1/1 6s 2m23s uzimihsr.github.io/cronjob-name&lt;span class="o"&gt;=&lt;/span&gt;cronjob-a
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-a-27322074 1/1 5s 83s uzimihsr.github.io/cronjob-name&lt;span class="o"&gt;=&lt;/span&gt;cronjob-a
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-a-27322075 1/1 5s 23s uzimihsr.github.io/cronjob-name&lt;span class="o"&gt;=&lt;/span&gt;cronjob-a
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-b-27322073 1/1 2s 2m23s uzimihsr.github.io/cronjob-name&lt;span class="o"&gt;=&lt;/span&gt;cronjob-b
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-b-27322074 1/1 4s 83s uzimihsr.github.io/cronjob-name&lt;span class="o"&gt;=&lt;/span&gt;cronjob-b
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-b-27322075 1/1 3s 23s uzimihsr.github.io/cronjob-name&lt;span class="o"&gt;=&lt;/span&gt;cronjob-b
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-c-27322073 1/1 4s 2m23s uzimihsr.github.io/cronjob-name&lt;span class="o"&gt;=&lt;/span&gt;cronjob-c
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-c-27322074 1/1 2s 83s uzimihsr.github.io/cronjob-name&lt;span class="o"&gt;=&lt;/span&gt;cronjob-c
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-c-27322075 1/1 6s 23s uzimihsr.github.io/cronjob-name&lt;span class="o"&gt;=&lt;/span&gt;cronjob-c
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-job 1/1 8s 23s controller-uid&lt;span class="o"&gt;=&lt;/span&gt;27160b7f-65e0-4e48-aa6b-9319e162f422,job-name&lt;span class="o"&gt;=&lt;/span&gt;my-job
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# labelSelectorを使った絞り込みができる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get job -l uzimihsr.github.io/cronjob-name&lt;span class="o"&gt;=&lt;/span&gt;cronjob-b
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME COMPLETIONS DURATION AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-b-27322073 1/1 2s 2m39s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-b-27322074 1/1 4s 99s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-b-27322075 1/1 3s 39s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;CronJob&lt;/code&gt;から作成された&lt;code&gt;Job&lt;/code&gt;に所望のラベルが追加されていて、ラベルを用いた絞り込みができることを確認できた。&lt;/p&gt;
&lt;p&gt;最後に、&lt;code&gt;CronJob&lt;/code&gt;から作られた&lt;code&gt;Job&lt;/code&gt;を絞り込む際の速度を他の方法と比較してみる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# CronJobが100個稼働している状態&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; i in &lt;span class="k"&gt;$(&lt;/span&gt;seq -w 100&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubectl create cronjob cronjob-&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; --image&lt;span class="o"&gt;=&lt;/span&gt;busybox --schedule&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;*/1 * * * *&amp;#34;&lt;/span&gt; -- date
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;## 色んな方法でcronjob-099のJobを探してみる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 愚直にgrepするとkubectlで0.277+grepで0.276==約0.5秒かかる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;time&lt;/span&gt; kubectl get job &lt;span class="p"&gt;|&lt;/span&gt; grep cronjob-099
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-099-27322103 1/1 2m29s 6m33s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-099-27322104 1/1 5m35s 5m41s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-099-27322105 0/1 4m39s 4m39s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-099-27322106 0/1 3m55s 3m55s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-099-27322107 0/1 2m39s 2m39s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-099-27322108 0/1 109s 109s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-099-27322109 0/1 41s 42s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get job 0.25s user 0.04s system 105% cpu 0.277 total
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grep --color&lt;span class="o"&gt;=&lt;/span&gt;auto cronjob-099 0.00s user 0.00s system 2% cpu 0.276 total
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# jqとの組み合わせ技だとkubectlで0.642+jqで0.648=約1.2秒...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;time&lt;/span&gt; kubectl get job -o json &lt;span class="p"&gt;|&lt;/span&gt; jq &lt;span class="s1"&gt;&amp;#39;.items[] | select(.metadata.ownerReferences[]?.name==&amp;#34;cronjob-099&amp;#34;) | .metadata.name&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;cronjob-099-27322103&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;cronjob-099-27322104&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;cronjob-099-27322105&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;cronjob-099-27322106&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;cronjob-099-27322107&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;cronjob-099-27322108&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;cronjob-099-27322109&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get job -o json 0.70s user 0.06s system 117% cpu 0.642 total
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;jq 0.08s user 0.01s system 13% cpu 0.648 total
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# webhookで付与したラベルを使うと約0.1秒で済む&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;time&lt;/span&gt; kubectl get job -l uzimihsr.github.io/cronjob-name&lt;span class="o"&gt;=&lt;/span&gt;cronjob-099
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME COMPLETIONS DURATION AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-099-27322103 1/1 2m29s 6m40s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-099-27322104 1/1 5m35s 5m48s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-099-27322105 0/1 4m46s 4m46s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-099-27322106 0/1 4m2s 4m2s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-099-27322107 0/1 2m46s 2m46s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-099-27322108 0/1 116s 116s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-099-27322109 0/1 48s 49s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob-099-27322110 0/1 1s 1s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get job -l uzimihsr.github.io/cronjob-name&lt;span class="o"&gt;=&lt;/span&gt;cronjob-099 0.08s user 0.03s system 113% cpu 0.094 total&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;ラベルをつけたおかげで&lt;code&gt;CronJob&lt;/code&gt;の&lt;code&gt;Job&lt;/code&gt;がそこそこ速く絞り込めるようになった。&lt;br&gt;
やったぜ。&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;admission webhookを自分で作って動かしてみた。&lt;br&gt;
いい勉強になったし、自分で使う上でもそこそこ便利なものができたと思っている。&lt;/p&gt;
&lt;p&gt;カッコつけてそれっぽくリポジトリをつくったものの、まだテストが書けてなかったりするので暇なときにちょくちょく修正していきたい。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="キャリーバッグに入るそとちゃん" class="gallery-image" data-flex-basis="350px" data-flex-grow="145" height="1360" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-12-18-kubernetes-mutating-admission-webhook-add-label-to-job/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2021-12-18-kubernetes-mutating-admission-webhook-add-label-to-job/sotochan_hu_11a11c667071cf8.jpg 800w, https://blog.uzimihsr.com/post/2021-12-18-kubernetes-mutating-admission-webhook-add-label-to-job/sotochan_hu_ad58222e8b32c05c.jpg 1600w, https://blog.uzimihsr.com/post/2021-12-18-kubernetes-mutating-admission-webhook-add-label-to-job/sotochan.jpg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>11月のそとちゃん(2021)</title><link>https://blog.uzimihsr.com/post/2021-12-06-sotochan/</link><pubDate>Mon, 06 Dec 2021 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2021-12-06-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2021-12-06-sotochan/sotochan.jpeg" alt="Featured image of post 11月のそとちゃん(2021)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%b2%e3%81%96%e4%b8%8a%e5%8d%a0%e6%8b%a0%e3%81%a1%e3%82%83%e3%82%93" &gt;ひざ上占拠ちゃん&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e7%ae%b1%e3%81%8c%e3%82%a2%e3%83%84%e3%81%84" &gt;箱がアツい&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e7%97%85%e9%99%a2" &gt;病院&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="ひざ上占拠ちゃん"&gt;ひざ上占拠ちゃん
&lt;/h3&gt;&lt;p&gt;通算n度目のひざブームがきた。&lt;/p&gt;
&lt;p&gt;俺がソファでだらだらしてるとだいたい乗っかってくる。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;乗り &lt;a href="https://t.co/Zozm0vMcf1"&gt;pic.twitter.com/Zozm0vMcf1&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1459836935183028225?ref_src=twsrc%5Etfw"&gt;November 14, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;そとちゃんに乗られるとねこを撫でる/スマホをいじる以外の行動が封じられてとても幸せ。&lt;/p&gt;
&lt;p&gt;ただし少しでも脚が動けば機嫌を損ねてしまう&amp;hellip;&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;勝手に乗ってきてイカ耳されるの納得いかない &lt;a href="https://t.co/lvRsdEwgpl"&gt;pic.twitter.com/lvRsdEwgpl&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1464400796636778506?ref_src=twsrc%5Etfw"&gt;November 27, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;乗ってきたからと言って必ずしも撫でられたいわけでもないらしい。&lt;/p&gt;
&lt;p&gt;むずかしい&amp;hellip;&lt;br&gt;
(ひざの上で寝返りされるとめっちゃ嬉しい)&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ねこ撫でたら反撃された &lt;a href="https://t.co/0LP3CEd008"&gt;pic.twitter.com/0LP3CEd008&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1464928769806782464?ref_src=twsrc%5Etfw"&gt;November 28, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;ソファにこだわりがある訳でもないらしく、仕事用のイスに座ってるときでも乗ってくる。&lt;/p&gt;
&lt;p&gt;イスの場合はちょっと高さがあるので万が一落ちたら怖いが、&lt;br&gt;
そとちゃんはそんなのお構いなしで自由に動いてしまう。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ヒトの膝の安定感を信用しすぎている(毛づくろい中) &lt;a href="https://t.co/ZvyIcN0NCC"&gt;pic.twitter.com/ZvyIcN0NCC&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1460614392739893253?ref_src=twsrc%5Etfw"&gt;November 16, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;&lt;img alt="落ちそうというかおしりと頭がはみ出てる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-12-06-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2021-12-06-sotochan/sotochan01_hu_6284d00d47022211.jpeg 800w, https://blog.uzimihsr.com/post/2021-12-06-sotochan/sotochan01_hu_aa2555f3a5dc67.jpeg 1600w, https://blog.uzimihsr.com/post/2021-12-06-sotochan/sotochan01.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;自由すぎて寝ちゃうときもある。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;寝た &lt;a href="https://t.co/Q4rheVsyQr"&gt;pic.twitter.com/Q4rheVsyQr&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1456483017392750592?ref_src=twsrc%5Etfw"&gt;November 5, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;超かわいい。&lt;/p&gt;
&lt;p&gt;(なお、長いときは1時間くらいそのまま動かないので脚が死ぬ😇)&lt;/p&gt;
&lt;h3 id="箱がアツい"&gt;箱がアツい
&lt;/h3&gt;&lt;p&gt;箱より袋派のそとちゃん。&lt;/p&gt;
&lt;p&gt;最近しもべがお高いものを買わないせいで紙袋の供給が減ってピンチ!&lt;/p&gt;
&lt;p&gt;とはならず、袋がないときは箱でも十分楽しめるみたい。&lt;/p&gt;
&lt;p&gt;横向きの箱に入って待ち構えたところに俺がねずみのおもちゃを投げてそれをしばくのが流行っている。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;これ5回くらいやってる &lt;a href="https://t.co/f6hfKLFsLP"&gt;pic.twitter.com/f6hfKLFsLP&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1456494765285933058?ref_src=twsrc%5Etfw"&gt;November 5, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;ねずみをしばく、箱に隠れる、ねずみをしばく、をエンドレスに繰り返す。&lt;/p&gt;
&lt;p&gt;野良だったころの狩りの動きに近くて楽しいのかも？&lt;/p&gt;
&lt;p&gt;横着して箱から出ずにねずみをしばくだけのパターンもある。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ゴールキーパー &lt;a href="https://t.co/NuNUXIlcQT"&gt;pic.twitter.com/NuNUXIlcQT&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1460195480139284483?ref_src=twsrc%5Etfw"&gt;November 15, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;逆に箱に入っていくねずみを追いかけてしばくときもある。&lt;/p&gt;
&lt;p&gt;結局横向きの箱とねずみがあれば何でも楽しいらしい。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;箱めっちゃたのしい &lt;a href="https://t.co/tsy2BTjJES"&gt;pic.twitter.com/tsy2BTjJES&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1461293670586482691?ref_src=twsrc%5Etfw"&gt;November 18, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;今まで使ってた引っ越しダンボールはそとちゃんにはちょっと大きくて、&lt;/p&gt;
&lt;p&gt;最近しもべが食べ始めた&lt;a class="link" href="https://nosh.jp/share/friend-202110/YCnWL" target="_blank" rel="noopener"
 &gt;nosh&lt;/a&gt;の宅配ダンボールがちょうどそとちゃんサイズにフィットしていてかわいい。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;横向きの箱は入る率高い &lt;a href="https://t.co/5h0KAFRbVv"&gt;pic.twitter.com/5h0KAFRbVv&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1460089494128893957?ref_src=twsrc%5Etfw"&gt;November 15, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;そとちゃんも広すぎるダンボールよりはちょっと狭い方が好きみたい。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;たのしそう &lt;a href="https://t.co/QI1FYWBvx4"&gt;pic.twitter.com/QI1FYWBvx4&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1464088759142477827?ref_src=twsrc%5Etfw"&gt;November 26, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;新しいダンボールにお熱なうちに古い引っ越しダンボールはこっそり捨ててしまいたい&amp;hellip;&lt;br&gt;
(たぶん無理)&lt;/p&gt;
&lt;h3 id="病院"&gt;病院
&lt;/h3&gt;&lt;p&gt;そとちゃんがやたらとお出かけしたがっていたのと、&lt;br&gt;
&lt;a class="link" href="https://uzimihsr.github.io/post/2021-09-30-sotochan/#%e7%97%85%e9%99%a2" target="_blank" rel="noopener"
 &gt;前回見つかった首のしこり&lt;/a&gt;がちょっと大きくなってきた気がしたので9月以来の病院に行ってきた。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;病院いく &lt;a href="https://t.co/SlS3EaY6IG"&gt;pic.twitter.com/SlS3EaY6IG&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1462948181570777088?ref_src=twsrc%5Etfw"&gt;November 23, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;触診の結果やはりしこりが大きくなっていて、&lt;br&gt;
前回はヒトの小指の先くらいのサイズだったのが今回は人差し指くらいの太さになっていた。&lt;/p&gt;
&lt;p&gt;その場で超音波検査をしてもらい、&lt;br&gt;
(検査のために先生に両手両足をガッツリ掴まれてブーブー文句言ってる姿がちょっとかわいそうだけど面白かった)&lt;/p&gt;
&lt;p&gt;エコーを診たところ水が溜まっているとかではなく固形の腫瘤ができていた。😱&lt;/p&gt;
&lt;p&gt;超音波検査だけではこの腫瘤が良性か悪性かは判定できないとのことで、&lt;br&gt;
先生から2つの対応を提案してもらった。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;注射針を入れて腫瘤の一部を吸い取って化学検査&lt;/li&gt;
&lt;li&gt;外科手術での切除&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;前者はある程度様子見、後者は全身麻酔のリスクがある方法。&lt;/p&gt;
&lt;p&gt;今の所は腫瘤を触っても痛そうにする素振りがないので問題なさそうだが、&lt;br&gt;
これが良性にしろ悪性にしろこのまま大きくなり続けると血管を圧迫する恐れがあるということで今回は腫瘤を切除してもらうことになった。&lt;/p&gt;
&lt;p&gt;スケジュールの都合で手術は少し先の12/17に行うことが決まり、
見積もりも出してもらった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="お高い" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-12-06-sotochan/sotochan02.jpg" srcset="https://blog.uzimihsr.com/post/2021-12-06-sotochan/sotochan02_hu_73f34b641b78b7fd.jpg 800w, https://blog.uzimihsr.com/post/2021-12-06-sotochan/sotochan02_hu_6318bab15b780152.jpg 1600w, https://blog.uzimihsr.com/post/2021-12-06-sotochan/sotochan02_hu_4e7ed743b14a1c81.jpg 2400w, https://blog.uzimihsr.com/post/2021-12-06-sotochan/sotochan02.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;自分が外科手術をしてもらったことがないので全身麻酔についてよくわかっていないのと、&lt;br&gt;
さらにそれが小さいそとちゃんのこととなると正直不安でしょうがない。&lt;/p&gt;
&lt;p&gt;めちゃめちゃ怖いけど、&lt;br&gt;
手術の内容について繰り返し質問しても優しく答えてくれた先生の人柄と、&lt;br&gt;
避妊手術で一度お腹を切っているそとちゃんの強さを信じることにした。&lt;/p&gt;
&lt;p&gt;&lt;img alt="すげえ怖いこと書いてある" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1536" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-12-06-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2021-12-06-sotochan/sotochan03_hu_1f22457253f4e0f1.jpeg 800w, https://blog.uzimihsr.com/post/2021-12-06-sotochan/sotochan03_hu_50da964ccda44323.jpeg 1600w, https://blog.uzimihsr.com/post/2021-12-06-sotochan/sotochan03.jpeg 2048w" width="2048"&gt;&lt;/p&gt;
&lt;p&gt;腫瘤以外の話だと、&lt;br&gt;
下痢対策で引っ越す前の病院に勧めてもらった&lt;a class="link" href="https://www.royalcanin.com/jp/cats/products/vet-products/feline-gastrointestinal-high-energy-dry-cat-food" target="_blank" rel="noopener"
 &gt;療法食のカリカリ&lt;/a&gt;を食べ続けても問題ないか聞いたところ、&lt;br&gt;
この療法食の場合は必要な栄養素が充分含まれていて、問題になる成分がないので食べ続けて問題ないとのことだった。&lt;br&gt;
手術のことで混乱していて、歯肉炎の状態を診てもらうのは忘れてしまった。&lt;/p&gt;
&lt;p&gt;病院大好きなそとちゃんも今回の超音波検査は嫌だったみたいで、&lt;br&gt;
帰るときはちょっと元気がなくておとなしかった。&lt;/p&gt;
&lt;p&gt;がんばってえらかったので家に帰ってすぐおやつをあげた。&lt;br&gt;
爪が刺さってめちゃ痛かった。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;病院がんばった &lt;a href="https://t.co/jyouQMh30d"&gt;pic.twitter.com/jyouQMh30d&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1462968634830061573?ref_src=twsrc%5Etfw"&gt;November 23, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;最近は手術が心配で毎晩寝る前にそとちゃんに大丈夫か聞いてるけど「にゃん」しか言わない。&lt;br&gt;
たぶんなにもわかってなさそう&amp;hellip;&lt;/p&gt;
&lt;p&gt;とりあえず無事を祈ってお守りを買ってこようと思う。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="なんも考えてなさそうなときの顔" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-12-06-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2021-12-06-sotochan/sotochan_hu_e0ab075bb2cde0c4.jpeg 800w, https://blog.uzimihsr.com/post/2021-12-06-sotochan/sotochan_hu_4c0799f65a0050d0.jpeg 1600w, https://blog.uzimihsr.com/post/2021-12-06-sotochan/sotochan_hu_86fa0e1e6152b888.jpeg 2400w, https://blog.uzimihsr.com/post/2021-12-06-sotochan/sotochan.jpeg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>Kubernetes Podが生きている間にNamespaceとかServiceAccountを消すとどうなるの?</title><link>https://blog.uzimihsr.com/post/2021-11-28-delete-serviceaccount/</link><pubDate>Sun, 28 Nov 2021 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2021-11-28-delete-serviceaccount/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2021-11-28-delete-serviceaccount/sotochan.jpg" alt="Featured image of post Kubernetes Podが生きている間にNamespaceとかServiceAccountを消すとどうなるの?" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;あんまりやる機会はないだろうけど、&lt;br&gt;
&lt;code&gt;Pod&lt;/code&gt;が生きている間にそれに紐づく&lt;code&gt;Namespace&lt;/code&gt;と&lt;code&gt;ServiceAccount&lt;/code&gt;を削除したときの挙動は次のようになる。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Pod&lt;/code&gt;が生きている間に&lt;code&gt;metadata.namespace&lt;/code&gt;の&lt;code&gt;Namespace&lt;/code&gt;を削除した場合
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Pod&lt;/code&gt;が削除される&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Pod&lt;/code&gt;が生きている間に&lt;code&gt;spec.serviceAccountName&lt;/code&gt;の&lt;code&gt;ServiceAccount&lt;/code&gt;を削除した場合
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Pod&lt;/code&gt;は削除されない&lt;/li&gt;
&lt;li&gt;自動マウントされた&lt;code&gt;ServiceAccount Token&lt;/code&gt;はそのまま残る
&lt;ul&gt;
&lt;li&gt;ただし&lt;code&gt;ServiceAccount&lt;/code&gt;が削除された時点で&lt;code&gt;Kubenretes API&lt;/code&gt;の認証が通らなくなる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/kubernetes-sigs/kind/" target="_blank" rel="noopener"
 &gt;kind&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;v0.11.1 go1.17.3 darwin/amd64&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/kubernetes/kubernetes" target="_blank" rel="noopener"
 &gt;Kubernetes&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;v1.21.1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="もくじ"&gt;もくじ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#namespace%e6%b6%88%e3%81%99" &gt;Namespace消す&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#serviceaccount%e6%b6%88%e3%81%99" &gt;Serviceaccount消す&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="namespace消す"&gt;Namespace消す
&lt;/h3&gt;&lt;p&gt;とある&lt;code&gt;Namespace&lt;/code&gt;で&lt;code&gt;Pod&lt;/code&gt;が生きているときに、&lt;code&gt;kubectl delete namespace&lt;/code&gt;したらどうなるんだろう&amp;hellip;?&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# じゅんび&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create namespace space-1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n space-1 create serviceaccount user-1 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n space-1 run nginx --image&lt;span class="o"&gt;=&lt;/span&gt;nginx --overrides&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;{ &amp;#34;spec&amp;#34;: { &amp;#34;serviceAccountName&amp;#34; : &amp;#34;user-1&amp;#34; } }&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Namespace: space-1でspec.serviceAccountName: user-1のPodが動いている状態&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n space-1 get pod nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nginx 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 15s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n space-1 get pod nginx -o &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;{.spec.serviceAccountName}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;user-1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podが動いてるNamespace消す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl delete namespace space-1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;namespace &lt;span class="s2"&gt;&amp;#34;space-1&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# どこにもPodが残ってない&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pod -A &lt;span class="p"&gt;|&lt;/span&gt; grep -c nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;Namespace&lt;/code&gt;を削除すると、動いている&lt;code&gt;Pod&lt;/code&gt;があっても一緒に削除されるらしい。&lt;/p&gt;
&lt;h3 id="serviceaccount消す"&gt;ServiceAccount消す
&lt;/h3&gt;&lt;p&gt;今度は&lt;code&gt;Pod&lt;/code&gt;の&lt;code&gt;spec.serviceAccountName&lt;/code&gt;に指定された&lt;code&gt;ServiceAccount&lt;/code&gt;を&lt;code&gt;Pod&lt;/code&gt;が生きている間に消してみる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# さっきと同じ状態&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n space-1 get pod nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nginx 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 15s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n space-1 get pod nginx -o &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;{.spec.serviceAccountName}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;user-1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n space-1 get serviceaccount user-1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME SECRETS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;user-1 &lt;span class="m"&gt;1&lt;/span&gt; 75s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podに紐付いてるServiceAccount消す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n space-1 delete serviceaccount user-1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;serviceaccount &lt;span class="s2"&gt;&amp;#34;user-1&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podは生きてる上にserviceAccountNameもそのまま&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n space-1 get pod nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nginx 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 2m46s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n space-1 get pod nginx -o &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;{.spec.serviceAccountName}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;user-1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# PodにマウントされているServiceAccount Tokenは削除したServiceAccountのものが残っている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n space-1 get pod nginx -o &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;{.spec.volumes}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;kube-api-access-fdd7d&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;projected&amp;#34;&lt;/span&gt;:&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;defaultMode&amp;#34;&lt;/span&gt;:420,&lt;span class="s2"&gt;&amp;#34;sources&amp;#34;&lt;/span&gt;:&lt;span class="o"&gt;[{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;serviceAccountToken&amp;#34;&lt;/span&gt;:&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;expirationSeconds&amp;#34;&lt;/span&gt;:3607,&lt;span class="s2"&gt;&amp;#34;path&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;token&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}}&lt;/span&gt;,&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;configMap&amp;#34;&lt;/span&gt;:&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;items&amp;#34;&lt;/span&gt;:&lt;span class="o"&gt;[{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;ca.crt&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;path&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;ca.crt&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}]&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;kube-root-ca.crt&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}}&lt;/span&gt;,&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;downwardAPI&amp;#34;&lt;/span&gt;:&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;items&amp;#34;&lt;/span&gt;:&lt;span class="o"&gt;[{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;fieldRef&amp;#34;&lt;/span&gt;:&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;apiVersion&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;v1&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;fieldPath&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;metadata.namespace&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;path&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;namespace&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}]}}]}}]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n space-1 &lt;span class="nb"&gt;exec&lt;/span&gt; nginx -it -- cat /var/run/secrets/kubernetes.io/serviceaccount/token &lt;span class="p"&gt;|&lt;/span&gt; jq -R &lt;span class="s1"&gt;&amp;#39;split(&amp;#34;.&amp;#34;) | .[1] | @base64d | fromjson | .&amp;#34;kubernetes.io&amp;#34;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;namespace&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;space-1&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;pod&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;nginx&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;uid&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;c1595cec-699d-41dd-bb51-6f648b23e832&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;serviceaccount&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;user-1&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;uid&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;e1d20d3d-5f9f-4ab0-b8e0-d021a42d189c&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;warnafter&amp;#34;&lt;/span&gt;: &lt;span class="m"&gt;1637856366&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;なるほど&amp;hellip;?&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Pod&lt;/code&gt;の&lt;code&gt;spec.serviceAccountName&lt;/code&gt;に指定された&lt;code&gt;ServiceAccount&lt;/code&gt;が削除されても&lt;code&gt;Pod&lt;/code&gt;は消されることはなく、&lt;br&gt;
&lt;code&gt;volume&lt;/code&gt;としてコンテナにマウントされた&lt;code&gt;ServiceAccount Token&lt;/code&gt;もそのままの状態で残るらしい。&lt;/p&gt;
&lt;p&gt;じゃあその&lt;code&gt;Token&lt;/code&gt;を使った&lt;code&gt;Kubernetes API&lt;/code&gt;の認証/認可はどうなるんだろう?&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# またまたさっきと同じ状態&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n space-1 get pod nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nginx 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 15s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n space-1 get pod nginx -o &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;{.spec.serviceAccountName}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;user-1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n space-1 get serviceaccount user-1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME SECRETS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;user-1 &lt;span class="m"&gt;1&lt;/span&gt; 75s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# user-1にspace-1のPod操作権限を付与&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n space-1 create role pod-owner --verb&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;*&amp;#34;&lt;/span&gt; --resource&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;pods&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n space-1 create rolebinding pod-owner-bind --role&lt;span class="o"&gt;=&lt;/span&gt;pod-owner --serviceaccount&lt;span class="o"&gt;=&lt;/span&gt;space-1:user-1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# この状態でServiceAccount Tokenを用いてKubernetes APIをたたくと成功(200 OK)する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n space-1 &lt;span class="nb"&gt;exec&lt;/span&gt; nginx -it -- bash -c &lt;span class="s1"&gt;&amp;#39;curl --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt --header &amp;#34;Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)&amp;#34; -I -X GET https://kubernetes.default.svc/api/v1/namespaces/space-1/pods&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;HTTP/2 &lt;span class="m"&gt;200&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ServiceAccountを削除&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n space-1 delete serviceaccount user-1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podに残ったServiceAccount Tokenを用いてKubernetes APIをたたくと失敗(401 Unauthorized)する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n space-1 &lt;span class="nb"&gt;exec&lt;/span&gt; nginx -it -- bash -c &lt;span class="s1"&gt;&amp;#39;curl --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt --header &amp;#34;Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)&amp;#34; -I -X GET https://kubernetes.default.svc/api/v1/namespaces/space-1/pods&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;HTTP/2 &lt;span class="m"&gt;401&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 同名のServiceAccountを再作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n space-1 create serviceaccount user-1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# しかし結果は変わらず&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n space-1 &lt;span class="nb"&gt;exec&lt;/span&gt; nginx -it -- bash -c &lt;span class="s1"&gt;&amp;#39;curl --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt --header &amp;#34;Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)&amp;#34; -I -X GET https://kubernetes.default.svc/api/v1/namespaces/space-1/pods&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;HTTP/2 &lt;span class="m"&gt;401&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;はえ〜&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ServiceAccount&lt;/code&gt;が削除された時点で&lt;code&gt;Token&lt;/code&gt;での認証ができなくなるみたい。&lt;br&gt;
後から同名の&lt;code&gt;ServiceAccount&lt;/code&gt;を作ってもたぶん&lt;code&gt;Token&lt;/code&gt;の&lt;code&gt;uid&lt;/code&gt;が新しい&lt;code&gt;ServiceAccount&lt;/code&gt;と合わないから認証ができないんじゃないかな&amp;hellip;?&lt;/p&gt;
&lt;p&gt;ちなみに&lt;code&gt;kubectl edit pod&lt;/code&gt;で&lt;code&gt;spec.serviceAccountName&lt;/code&gt;をいじろうとすると&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Forbidden: pod updates may not change fields other than `spec.containers[*].image`, `spec.initContainers[*].image`, `spec.activeDeadlineSeconds` or `spec.tolerations` (only additions to existing tolerations)`
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;って怒られちゃうので、&lt;br&gt;
&lt;code&gt;Pod&lt;/code&gt;が生きてる間に&lt;code&gt;ServiceAccount&lt;/code&gt;を消してしまった場合はその&lt;code&gt;Token&lt;/code&gt;でのAPI認証は諦めて&lt;code&gt;Pod&lt;/code&gt;を作り直すのがよさそう。&lt;br&gt;
(というか&lt;code&gt;Pod&lt;/code&gt;が生きているうちはあまり消さないほうがいい)&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;こんなことは普段仕事で&lt;code&gt;Kubernetes&lt;/code&gt;を運用しているときは絶対やらないとは思うけど、すこし気になったので試してみた。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Namespace&lt;/code&gt;も&lt;code&gt;ServiceAccount&lt;/code&gt;も&lt;code&gt;Pod&lt;/code&gt;を巻き添えにして削除されるものだと思いこんでいたので、&lt;br&gt;
&lt;code&gt;ServiceAccount&lt;/code&gt;が消えても&lt;code&gt;Pod&lt;/code&gt;とマウントされた&lt;code&gt;Token&lt;/code&gt;が残るのは勉強になった。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="こたつでごろごろするそとちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-11-28-delete-serviceaccount/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2021-11-28-delete-serviceaccount/sotochan_hu_7762f65acc193675.jpg 800w, https://blog.uzimihsr.com/post/2021-11-28-delete-serviceaccount/sotochan_hu_e5b147e8a60519d6.jpg 1600w, https://blog.uzimihsr.com/post/2021-11-28-delete-serviceaccount/sotochan.jpg 1984w" width="1984"&gt;&lt;/p&gt;</description></item><item><title>10月のそとちゃん(2021)</title><link>https://blog.uzimihsr.com/post/2021-11-08-sotochan/</link><pubDate>Mon, 08 Nov 2021 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2021-11-08-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan.jpeg" alt="Featured image of post 10月のそとちゃん(2021)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e6%ad%af%e3%81%bf%e3%81%8c%e3%81%8d" &gt;歯みがき&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%be%e3%82%8b%e3%81%84" &gt;まるい?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%8f%e3%83%ad%e3%82%a6%e3%82%a3%e3%83%b3" &gt;ハロウィン&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="歯みがき"&gt;歯みがき
&lt;/h3&gt;&lt;p&gt;やっぱり歯みがきが嫌い。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;この世の全てに絶望して引きこもった(はみがきが嫌) &lt;a href="https://t.co/OKWGazGWnw"&gt;pic.twitter.com/OKWGazGWnw&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1451211545787056132?ref_src=twsrc%5Etfw"&gt;October 21, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;9月に病院で診てもらってからは薬を塗らない日も毎日歯みがきをするようになったんだけど、&lt;br&gt;
歯肉炎になってる右の奥歯に触れられるのがどうしても嫌みたい。&lt;/p&gt;
&lt;p&gt;ふだんはやさしくて滅多に怒らないそとちゃんでもこのときだけは手加減なしで暴れてくるのでひどいときは(俺が)流血沙汰になる。&lt;/p&gt;
&lt;p&gt;&lt;img alt="いたい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1512" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan01.jpeg" srcset="https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan01_hu_8e588450928c1ec8.jpeg 800w, https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan01_hu_ab01ddd41ad36aa9.jpeg 1600w, https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan01.jpeg 2016w" width="2016"&gt;&lt;/p&gt;
&lt;p&gt;それでも最後は抵抗虚しく捕まえられて歯みがきと塗り薬をやられて拗ねちゃう。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;抵抗むなしく歯みがきされて拗ねてる &lt;a href="https://t.co/CPtY0LJqGZ"&gt;pic.twitter.com/CPtY0LJqGZ&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1449772610405896192?ref_src=twsrc%5Etfw"&gt;October 17, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;(あんまり怒り慣れてないからいじけ方もぎこちなくてちょっとかわいい)&lt;/p&gt;
&lt;p&gt;&lt;img alt="いじけてるつもり" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1512" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan02.jpeg" srcset="https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan02_hu_479b4a59d7c00062.jpeg 800w, https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan02_hu_17b992f2ae8d88dc.jpeg 1600w, https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan02.jpeg 2016w" width="2016"&gt;&lt;/p&gt;
&lt;p&gt;歯肉炎の塗り薬は処方されたぶんをしっかり使い終わって、&lt;a class="link" href="https://uzimihsr.github.io/post/2021-09-30-sotochan/#%e7%97%85%e9%99%a2" target="_blank" rel="noopener"
 &gt;9月のはじめ&lt;/a&gt;よりもちょっと赤みが引いたような気もする。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ちょっと良くなった?" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1512" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan11.jpeg" srcset="https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan11_hu_5852f6a7365af465.jpeg 800w, https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan11_hu_118996325d2157e5.jpeg 1600w, https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan11.jpeg 2016w" width="2016"&gt;&lt;/p&gt;
&lt;p&gt;近いうちにまた病院で診てもらいたい。　　&lt;/p&gt;
&lt;h3 id="まるい"&gt;まるい?
&lt;/h3&gt;&lt;p&gt;ちょっと寒くなってきたのか、そとちゃんがまるくなっていることが増えた。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;まるい &lt;a href="https://t.co/kppQydVKzb"&gt;pic.twitter.com/kppQydVKzb&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1443783401496977414?ref_src=twsrc%5Etfw"&gt;October 1, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;まるくなった &lt;a href="https://t.co/tfgERaqHAN"&gt;pic.twitter.com/tfgERaqHAN&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1445646210451210242?ref_src=twsrc%5Etfw"&gt;October 6, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;でもまるくないときもある。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;まるくない &lt;a href="https://t.co/FaIo4SFUkd"&gt;pic.twitter.com/FaIo4SFUkd&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1445615304067801089?ref_src=twsrc%5Etfw"&gt;October 6, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ぴーぴー言いながら寝てる &lt;a href="https://t.co/rCTVPBzljc"&gt;pic.twitter.com/rCTVPBzljc&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1453565906009800707?ref_src=twsrc%5Etfw"&gt;October 28, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;&amp;hellip;というかまるくないことのほうが多いかもしれない。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;最近まるくないことのほうが多い &lt;a href="https://t.co/Z88hN28lPA"&gt;pic.twitter.com/Z88hN28lPA&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1446323874073702406?ref_src=twsrc%5Etfw"&gt;October 8, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;たまに四角いときもある。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;もはやちょっと四角い &lt;a href="https://t.co/Lq1cEji2c8"&gt;pic.twitter.com/Lq1cEji2c8&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1453689119331155976?ref_src=twsrc%5Etfw"&gt;October 28, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;毎日おもしろい寝かたをしているので見ていて飽きない。&lt;br&gt;
かわいい。&lt;/p&gt;
&lt;h3 id="ハロウィン"&gt;ハロウィン
&lt;/h3&gt;&lt;p&gt;今年もそとちゃんにハロウィンの仮装をしてもらった。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ドラキュラマント&lt;a href="https://twitter.com/hashtag/HappyHalloween2021?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#HappyHalloween2021&lt;/a&gt; &lt;a href="https://t.co/DxTVkM6xLI"&gt;pic.twitter.com/DxTVkM6xLI&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1454826344777281545?ref_src=twsrc%5Etfw"&gt;October 31, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;例年(嫌々ながら)着てもらっていたドラキュラマントに加えて、今年はこうもりポンチョもご用意させていただいた。&lt;/p&gt;
&lt;p&gt;これがまたバチクソにかわいい。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;こうもりポンチョ&lt;a href="https://twitter.com/hashtag/HappyHalloween2021?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#HappyHalloween2021&lt;/a&gt; &lt;a href="https://t.co/u3r6HBFzU2"&gt;pic.twitter.com/u3r6HBFzU2&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1454823615652786191?ref_src=twsrc%5Etfw"&gt;October 31, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;&lt;img alt="フードになっててかわいい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1512" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan03.jpeg" srcset="https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan03_hu_f5575a60c7feacd4.jpeg 800w, https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan03_hu_d6d50895fc4b9304.jpeg 1600w, https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan03.jpeg 2016w" width="2016"&gt;&lt;/p&gt;
&lt;p&gt;本当は小型犬用の服なんだけど、頭からかぶってボタンで留めるだけなのでそとちゃんでも着られた。&lt;br&gt;
(手を通すタイプだとめちゃくちゃ嫌がる)&lt;/p&gt;
&lt;p&gt;&lt;img alt="おめめキラキラでかわいい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1512" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan04.jpeg" srcset="https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan04_hu_1e5bbe90dec7db99.jpeg 800w, https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan04_hu_b0f4544670d10297.jpeg 1600w, https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan04.jpeg 2016w" width="2016"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="羽が生えててかわいい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1512" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan05.jpeg" srcset="https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan05_hu_7aaa9f9983b1c597.jpeg 800w, https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan05_hu_6edaa2240ba3ffe2.jpeg 1600w, https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan05.jpeg 2016w" width="2016"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="フードが落ちると前が見えなくなってかわいい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1512" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan06.jpeg" srcset="https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan06_hu_fe3c371c8f15b0e5.jpeg 800w, https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan06_hu_a561c91ffb98423.jpeg 1600w, https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan06.jpeg 2016w" width="2016"&gt;&lt;/p&gt;
&lt;p&gt;でも最後は自分で脱いじゃった。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;脱ぐ &lt;a href="https://t.co/eP6mv2Heuz"&gt;pic.twitter.com/eP6mv2Heuz&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1454972492217401350?ref_src=twsrc%5Etfw"&gt;November 1, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;逆にドラキュラマントはそんなに気にならないみたいで、脱がずにずっとウロウロしていた。&lt;br&gt;
(着たままトイレしようとしたので流石に脱がせた)&lt;/p&gt;
&lt;p&gt;&lt;img alt="マントも結局かわいい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1512" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan07.jpeg" srcset="https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan07_hu_3bb184eb6458fafe.jpeg 800w, https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan07_hu_2818e35b992d3a.jpeg 1600w, https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan07.jpeg 2016w" width="2016"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="かわいい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan08.jpeg" srcset="https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan08_hu_2ee2572483d2dfca.jpeg 800w, https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan08_hu_56016cc2a8fb16d8.jpeg 1600w, https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan08.jpeg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;俺のわがままに付き合ってもらったので、最後はちゃんと報酬を支払った。&lt;br&gt;
(耳がでてくるとこが最高にかわいい)&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;おやつ &lt;a href="https://t.co/x56SDNygRO"&gt;pic.twitter.com/x56SDNygRO&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1455025122801184770?ref_src=twsrc%5Etfw"&gt;November 1, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;クリスマスもまたかわいい服を着てもらいたい。&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;そとちゃんは10月も元気によく遊んでよく寝るいい子だった。&lt;/p&gt;
&lt;p&gt;歯みがきでどれだけ不機嫌になっても絶対に&amp;quot;シャーッ!&amp;ldquo;とか&amp;quot;フーッ!&amp;ldquo;って怒ることがないので(暴れはする)、&lt;br&gt;
そとちゃんが保護されるまで関わってきた周りのねこもみんな優しい性格で、そとちゃんは怒りの表現を知らないまま成猫になったのかな&amp;hellip;と思ったりもした。&lt;/p&gt;
&lt;p&gt;そろそろ本格的に寒くなってくるころなので、暖かくして幸せに過ごせるようにしたい。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="オフショット?" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1512" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan.jpeg" srcset="https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan_hu_e9e37a035ead5237.jpeg 800w, https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan_hu_9d4e6bc36d81d0c5.jpeg 1600w, https://blog.uzimihsr.com/post/2021-11-08-sotochan/sotochan.jpeg 2016w" width="2016"&gt;&lt;/p&gt;</description></item><item><title>kubeadmで作ったクラスタにNGINX Ingress Controllerを入れる</title><link>https://blog.uzimihsr.com/post/2021-10-28-ingress-nginx-bare-metal/</link><pubDate>Thu, 28 Oct 2021 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2021-10-28-ingress-nginx-bare-metal/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2021-10-28-ingress-nginx-bare-metal/sotochan.jpg" alt="Featured image of post kubeadmで作ったクラスタにNGINX Ingress Controllerを入れる" /&gt;&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;p&gt;自分は普段マネージド&lt;code&gt;Kubernetes&lt;/code&gt;ばかり使っていて、当たり前のように&lt;code&gt;Ingress&lt;/code&gt;を使ってアプリをクラスタ外に公開している。&lt;br&gt;
でもよくよく考えると&lt;code&gt;Ingress&lt;/code&gt;が使えるのはクラスタの管理者が&lt;code&gt;Ingress Controller&lt;/code&gt;を用意してくれているからで、&lt;br&gt;
今までそれ自体を自分で設定したことはなかった。&lt;/p&gt;
&lt;p&gt;仕事でこれだけ&lt;code&gt;Kubernetes&lt;/code&gt;触ってるのに&lt;code&gt;Ingress Controller&lt;/code&gt;を設定したことがないのは流石に恥ずかしいと思い、&lt;br&gt;
&lt;a class="link" href="https://uzimihsr.github.io/post/2021-10-15-create-kubernetes-cluster-with-kubeadm-containerd-calico/" target="_blank" rel="noopener"
 &gt;kubeadmで作った自前のクラスタ&lt;/a&gt;に&lt;a class="link" href="https://github.com/kubernetes/ingress-nginx/" target="_blank" rel="noopener"
 &gt;NGINX Ingress Controller&lt;/a&gt;を設定して、サービスがクラスタ外に公開できるところまで試した。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;kubeadm&lt;/code&gt;で作った自前クラスタに&lt;code&gt;ingress-nginx(NGINX Ingress Controller)&lt;/code&gt;を入れて&lt;code&gt;NodePort Service&lt;/code&gt;で動かした&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Ingress Class&lt;/code&gt;の設定をした&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MetalLB&lt;/code&gt;を使って&lt;code&gt;ingress-nginx&lt;/code&gt;を&lt;code&gt;LoadBalancer Service&lt;/code&gt;で動かした&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Ubuntu 20.04.3 LTS (GNU/Linux 5.11.0-1020-gcp x86_64)&lt;/li&gt;
&lt;li&gt;containerd 1.4.11&lt;/li&gt;
&lt;li&gt;Calico v3.20.2&lt;/li&gt;
&lt;li&gt;Kubernetes v1.22.2&lt;/li&gt;
&lt;li&gt;NGINX Ingress controller v1.0.4&lt;/li&gt;
&lt;li&gt;MetalLB 0.10.3&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e8%87%aa%e5%89%8d%e3%82%af%e3%83%a9%e3%82%b9%e3%82%bf%e3%81%ae%e4%bd%9c%e6%88%90" &gt;自前クラスタの作成&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#ingress-nginx%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%abnodeport" &gt;ingress-nginxのインストール(NodePort)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e5%8b%95%e4%bd%9c%e7%a2%ba%e8%aa%8dnodeport" &gt;動作確認(NodePort)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#metallb%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" &gt;MetalLBのインストール&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#ingress-nginx%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%abwith-metallb" &gt;ingress-nginxのインストール(with MetalLB)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e5%8b%95%e4%bd%9c%e7%a2%ba%e8%aa%8dwith-metallb" &gt;動作確認(with MetalLB)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="自前クラスタの作成"&gt;自前クラスタの作成
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2021-10-15-create-kubernetes-cluster-with-kubeadm-containerd-calico/" target="_blank" rel="noopener"
 &gt;前回作ったクラスタ&lt;/a&gt;をそのまま使う。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get nodes -o wide
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-master Ready control-plane,master 5m56s v1.22.2 10.240.0.2 &amp;lt;none&amp;gt; Ubuntu 20.04.3 LTS 5.11.0-1020-gcp containerd://1.4.11
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-worker Ready &amp;lt;none&amp;gt; 3m30s v1.22.2 10.240.0.3 &amp;lt;none&amp;gt; Ubuntu 20.04.3 LTS 5.11.0-1020-gcp containerd://1.4.11
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get deploy -A
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAMESPACE NAME READY UP-TO-DATE AVAILABLE AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;calico-apiserver calico-apiserver 1/1 &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 5m15s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;calico-system calico-kube-controllers 1/1 &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 6m16s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;calico-system calico-typha 2/2 &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; 6m17s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube-system coredns 2/2 &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; 7m27s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tigera-operator tigera-operator 1/1 &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 6m24s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get ds -A
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAMESPACE NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;calico-system calico-node &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; kubernetes.io/os&lt;span class="o"&gt;=&lt;/span&gt;linux 6m36s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube-system kube-proxy &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; kubernetes.io/os&lt;span class="o"&gt;=&lt;/span&gt;linux 7m46s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get service -A
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;calico-apiserver calico-api ClusterIP 10.96.0.75 &amp;lt;none&amp;gt; 443/TCP 6m2s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;calico-system calico-kube-controllers-metrics ClusterIP 10.97.190.112 &amp;lt;none&amp;gt; 9094/TCP 6m27s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;calico-system calico-typha ClusterIP 10.97.47.173 &amp;lt;none&amp;gt; 5473/TCP 7m4s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;default kubernetes ClusterIP 10.96.0.1 &amp;lt;none&amp;gt; 443/TCP 8m16s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube-system kube-dns ClusterIP 10.96.0.10 &amp;lt;none&amp;gt; 53/UDP,53/TCP,9153/TCP 8m14s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get ingress -A
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;No resources found&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="ingress-nginxのインストールnodeport"&gt;ingress-nginxのインストール(NodePort)
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/" target="_blank" rel="noopener"
 &gt;Ingress Controller&lt;/a&gt;にはいくつか種類があるが、&lt;code&gt;Kubernetes&lt;/code&gt;公式でサポートされている中では&lt;a class="link" href="https://github.com/kubernetes/ingress-nginx/" target="_blank" rel="noopener"
 &gt;NGINX Ingress Controller&lt;/a&gt;が自前クラスタに使えそう。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://kubernetes.github.io/ingress-nginx/deploy/#bare-metal" target="_blank" rel="noopener"
 &gt;公式の手順&lt;/a&gt;に従ってインストールしてみる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# https://kubernetes.github.io/ingress-nginx/deploy/#bare-metal&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.0.4/deploy/static/provider/baremetal/deploy.yaml&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a class="link" href="https://kubernetes.github.io/ingress-nginx/deploy/baremetal/#over-a-nodeport-service" target="_blank" rel="noopener"
 &gt;今回の手順だとクラスタ外のロードバランサーを用意していない&lt;/a&gt;ので、&lt;code&gt;Ingress Controller&lt;/code&gt;自体が&lt;code&gt;NodePort Service&lt;/code&gt;でクラスタ外からのリクエストを受けて&lt;code&gt;Ingress&lt;/code&gt;のルールに則ったトラフィックの振り分けを行うらしい。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Ingress ControllerのDeploymentが立っている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n ingress-nginx get deploy
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY UP-TO-DATE AVAILABLE AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ingress-nginx-controller 1/1 &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 7m34s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n ingress-nginx get pods --field-selector&lt;span class="o"&gt;=&lt;/span&gt;status.phase&lt;span class="o"&gt;=&lt;/span&gt;Running -o wide
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ingress-nginx-controller-644555766d-4pwm2 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 7m8s 192.168.231.195 kubernetes-worker &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n ingress-nginx &lt;span class="nb"&gt;exec&lt;/span&gt; -it ingress-nginx-controller-644555766d-4pwm2 -- /nginx-ingress-controller --version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NGINX Ingress controller
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Release: v1.0.4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Build: 9b78b6c197b48116243922170875af4aa752ee59
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Repository: https://github.com/kubernetes/ingress-nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; nginx version: nginx/1.19.9
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Ingress Controller自体がNodePort Serviceで公開されている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n ingress-nginx get service
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ingress-nginx-controller NodePort 10.104.81.185 &amp;lt;none&amp;gt; 80:31862/TCP,443:30703/TCP 8m29s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ingress-nginx-controller-admission ClusterIP 10.98.56.107 &amp;lt;none&amp;gt; 443/TCP 8m29s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl -n ingress-nginx describe service ingress-nginx-controller
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: ingress-nginx-controller
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: ingress-nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: app.kubernetes.io/component&lt;span class="o"&gt;=&lt;/span&gt;controller
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; app.kubernetes.io/instance&lt;span class="o"&gt;=&lt;/span&gt;ingress-nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; app.kubernetes.io/managed-by&lt;span class="o"&gt;=&lt;/span&gt;Helm
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; app.kubernetes.io/name&lt;span class="o"&gt;=&lt;/span&gt;ingress-nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; app.kubernetes.io/version&lt;span class="o"&gt;=&lt;/span&gt;1.0.4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; helm.sh/chart&lt;span class="o"&gt;=&lt;/span&gt;ingress-nginx-4.0.6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Selector: app.kubernetes.io/component&lt;span class="o"&gt;=&lt;/span&gt;controller,app.kubernetes.io/instance&lt;span class="o"&gt;=&lt;/span&gt;ingress-nginx,app.kubernetes.io/name&lt;span class="o"&gt;=&lt;/span&gt;ingress-nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Type: NodePort
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IP Family Policy: SingleStack
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IP Families: IPv4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IP: 10.104.81.185
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IPs: 10.104.81.185
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Port: http 80/TCP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;TargetPort: http/TCP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NodePort: http 31862/TCP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Endpoints: 192.168.231.195:80
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Port: https 443/TCP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;TargetPort: https/TCP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NodePort: https 30703/TCP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Endpoints: 192.168.231.195:443
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Session Affinity: None
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;External Traffic Policy: Cluster
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events: &amp;lt;none&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="動作確認nodeport"&gt;動作確認(NodePort)
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Ingress Controller&lt;/code&gt;が用意できたので、適当な&lt;code&gt;Pod&lt;/code&gt;と&lt;code&gt;Ingress&lt;/code&gt;を用意して動作を確認する。&lt;br&gt;
手順は&lt;a class="link" href="https://kubernetes.io/docs/tasks/access-application-cluster/ingress-minikube/#deploy-a-hello-world-app" target="_blank" rel="noopener"
 &gt;Kubernetes公式のもの&lt;/a&gt;を一部改変して試した。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 動作確認用Deployment, Service, Ingressの作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create deployment web --image&lt;span class="o"&gt;=&lt;/span&gt;gcr.io/google-samples/hello-app:1.0 --port&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl expose deployment web --port&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create ingress example-ingress --rule&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;hello-world.info/*=web:8080&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;作成したリソースはこんな感じ。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;web -o wide
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;web-7c884bf475-tt9g6 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 8m21s 192.168.231.196 kubernetes-worker &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get service web -o wide
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE SELECTOR
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;web ClusterIP 10.99.167.187 &amp;lt;none&amp;gt; 8080/TCP 6m7s &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;web
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ちょっとあやしい...?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl describe ingress example-ingress
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: example-ingress
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Address:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Default backend: default-http-backend:80 &lt;span class="o"&gt;(&lt;/span&gt;&amp;lt;error: endpoints &lt;span class="s2"&gt;&amp;#34;default-http-backend&amp;#34;&lt;/span&gt; not found&amp;gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Rules:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Host Path Backends
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---- ---- --------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; hello-world.info
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; / web:8080 &lt;span class="o"&gt;(&lt;/span&gt;192.168.231.196:8080&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events: &amp;lt;none&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;試しに&lt;code&gt;master node&lt;/code&gt;からクラスタを介さず&lt;code&gt;Ingress&lt;/code&gt;経由で疎通できるか試してみる。&lt;br&gt;
インストール後に確認したように&lt;code&gt;Ingress Controller&lt;/code&gt;自体が&lt;code&gt;NodePort Service&lt;/code&gt;で公開されているので、そこにリクエストを飛ばす。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# &amp;lt;nodeのIP&amp;gt;:&amp;lt;NodePort&amp;gt;にリクエストしたけどダメ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -H &lt;span class="s2"&gt;&amp;#34;Host: hello-world.info&amp;#34;&lt;/span&gt; 10.240.0.3:31862/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;html&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;404 Not Found&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;body&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;center&amp;gt;&amp;lt;h1&amp;gt;404 Not Found&amp;lt;/h1&amp;gt;&amp;lt;/center&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;hr&amp;gt;&amp;lt;center&amp;gt;nginx&amp;lt;/center&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;/body&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;は？失敗したんだが😭&lt;/p&gt;
&lt;p&gt;どうやら作った&lt;code&gt;Ingress&lt;/code&gt;に&lt;a class="link" href="https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class" target="_blank" rel="noopener"
 &gt;Ingress Class&lt;/a&gt;の指定がないので&lt;code&gt;Ingress Controller&lt;/code&gt;に認識されてないっぽい。&lt;br&gt;
(1クラスタに複数の&lt;code&gt;Ingress Controller&lt;/code&gt;が存在することがあるので、&lt;code&gt;Ingress Class&lt;/code&gt;が指定されていないといろいろ問題になる)&lt;/p&gt;
&lt;p&gt;対応方法としては&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Ingress&lt;/code&gt;作成時に&lt;code&gt;spec.ingressClassName&lt;/code&gt;フィールドを指定する&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Ingress Class&lt;/code&gt;にアノテーションをつけてデフォルト設定にする
のどちらかだと思う。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;今回はデフォルト&lt;code&gt;Ingress Class&lt;/code&gt;を設定する方法を試してみる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Ingress Classにアノテーションをつけてデフォルト設定にする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl annotate ingressclass nginx ingressclass.kubernetes.io/is-default-class&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ingressを作り直す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl delete ingress example-ingress
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create ingress example-ingress --rule&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;hello-world.info/*=web:8080&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# (optional)IngressClassのデフォルト設定をしない場合は--classでIngressClassを指定する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create ingress example-ingress --class&lt;span class="o"&gt;=&lt;/span&gt;nginx --rule&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;hello-world.info/*=web:8080&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;Ingress Class&lt;/code&gt;の設定をした上で再度挑戦してみる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# アノテーションがついている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl describe ingressclass nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: app.kubernetes.io/component&lt;span class="o"&gt;=&lt;/span&gt;controller
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; app.kubernetes.io/instance&lt;span class="o"&gt;=&lt;/span&gt;ingress-nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; app.kubernetes.io/managed-by&lt;span class="o"&gt;=&lt;/span&gt;Helm
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; app.kubernetes.io/name&lt;span class="o"&gt;=&lt;/span&gt;ingress-nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; app.kubernetes.io/version&lt;span class="o"&gt;=&lt;/span&gt;1.0.4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; helm.sh/chart&lt;span class="o"&gt;=&lt;/span&gt;ingress-nginx-4.0.6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: ingressclass.kubernetes.io/is-default-class: &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Controller: k8s.io/ingress-nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# さっきと違ってIngress Controllerに認識されてそう&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl describe ingress example-ingress
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: example-ingress
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Address: 10.240.0.3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Default backend: default-http-backend:80 &lt;span class="o"&gt;(&lt;/span&gt;&amp;lt;error: endpoints &lt;span class="s2"&gt;&amp;#34;default-http-backend&amp;#34;&lt;/span&gt; not found&amp;gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Rules:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Host Path Backends
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---- ---- --------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; hello-world.info
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; / web:8080 &lt;span class="o"&gt;(&lt;/span&gt;192.168.231.196:8080&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Reason Age From Message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---- ------ ---- ---- -------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Sync 2m8s &lt;span class="o"&gt;(&lt;/span&gt;x2 over 2m12s&lt;span class="o"&gt;)&lt;/span&gt; nginx-ingress-controller Scheduled &lt;span class="k"&gt;for&lt;/span&gt; sync
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 今度は疎通できる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -H &lt;span class="s2"&gt;&amp;#34;Host: hello-world.info&amp;#34;&lt;/span&gt; 10.240.0.3:31862/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Hello, world!
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Version: 1.0.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Hostname: web-7c884bf475-tt9g6&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;今度はちゃんと&lt;code&gt;Ingress&lt;/code&gt;経由で通信できた。🎉&lt;br&gt;
やったぜ。&lt;/p&gt;
&lt;h3 id="metallbのインストール"&gt;MetalLBのインストール
&lt;/h3&gt;&lt;p&gt;とはいえやっぱりクラスタ外からアクセスするときにデカいポートをいちいち指定するのはしんどい。&lt;br&gt;
次は&lt;code&gt;NodePort Service&lt;/code&gt;ではなく&lt;code&gt;LoadBalancer Service&lt;/code&gt;を使って普通のポートでトラフィックを受けられるようにしてみる。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://kubernetes.github.io/ingress-nginx/deploy/baremetal/#a-pure-software-solution-metallb" target="_blank" rel="noopener"
 &gt;NGINX Ingress Controllerのドキュメント&lt;/a&gt;によると、クラウドプロバイダで管理されていないベアメタルクラスタでも&lt;a class="link" href="https://github.com/metallb/metallb" target="_blank" rel="noopener"
 &gt;MetalLB&lt;/a&gt;を導入すれば&lt;code&gt;LoadBalancer Service&lt;/code&gt;が使えるようになるらしい。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# NodePort版Ingress Controllerの削除&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl delete -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.0.4/deploy/static/provider/baremetal/deploy.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# MetalLBのインストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.10.3/manifests/namespace.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.10.3/manifests/metallb.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# L2 modeの設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# https://metallb.universe.tf/configuration/#layer-2-configuration&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# nodeのネットワークで使われていないIPを使用する(今回は10.240.0.0/24の中でnodeに割り当てられていないIP)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat &lt;span class="s"&gt;&amp;lt;&amp;lt; EOF | kubectl apply -f -
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: v1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: ConfigMap
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; namespace: metallb-system
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; name: config
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;data:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; config: |
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; address-pools:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; - name: default
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; protocol: layer2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; addresses:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; - 10.240.0.10-10.240.0.15
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;EOF&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;MetalLB&lt;/code&gt;のインストールと設定が正常にできていればこんな感じになる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ k -n metallb-system get all
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/controller-77c44876d-wgqzj 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 5m43s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/speaker-fdcrw 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 5m43s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/speaker-kgz2w 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 5m43s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;daemonset.apps/speaker &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; kubernetes.io/os&lt;span class="o"&gt;=&lt;/span&gt;linux 5m43s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY UP-TO-DATE AVAILABLE AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps/controller 1/1 &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 5m43s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME DESIRED CURRENT READY AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;replicaset.apps/controller-77c44876d &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 5m43s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="ingress-nginxのインストールwith-metallb"&gt;ingress-nginxのインストール(with MetalLB)
&lt;/h3&gt;&lt;p&gt;あとは&lt;code&gt;LoadBalancer Service&lt;/code&gt;を使う設定の&lt;code&gt;ingress-nginx&lt;/code&gt;をインストールする。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# LoadBalancerになるはず&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.0.4/deploy/static/provider/cloud/deploy.yaml&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;外部からリクエストを受けてトラフィックを振り分けるための&lt;code&gt;Ingress Controller&lt;/code&gt;が今度は&lt;code&gt;NodePort Service&lt;/code&gt;でなくちゃんと&lt;code&gt;LoadBalancer Service&lt;/code&gt;で公開されていて、しかも&lt;code&gt;ExternalIP&lt;/code&gt;に&lt;code&gt;MetalLB&lt;/code&gt;で指定したIPが設定されている。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ k -n ingress-nginx get all
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/ingress-nginx-admission-create--1-fbqsf 0/1 Completed &lt;span class="m"&gt;0&lt;/span&gt; 28s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/ingress-nginx-admission-patch--1-l2pz5 0/1 Completed &lt;span class="m"&gt;1&lt;/span&gt; 28s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/ingress-nginx-controller-5c8d66c76d-wfbjf 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 29s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/ingress-nginx-controller LoadBalancer 10.111.44.72 10.240.0.10 80:31646/TCP,443:32459/TCP 29s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/ingress-nginx-controller-admission ClusterIP 10.99.244.117 &amp;lt;none&amp;gt; 443/TCP 29s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY UP-TO-DATE AVAILABLE AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps/ingress-nginx-controller 1/1 &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 29s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME DESIRED CURRENT READY AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;replicaset.apps/ingress-nginx-controller-5c8d66c76d &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 29s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME COMPLETIONS DURATION AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;job.batch/ingress-nginx-admission-create 1/1 4s 29s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;job.batch/ingress-nginx-admission-patch 1/1 4s 28s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="動作確認with-metallb"&gt;動作確認(with MetalLB)
&lt;/h3&gt;&lt;p&gt;最後に、同じネットワークの&lt;code&gt;node&lt;/code&gt;から&lt;code&gt;MetalLB&lt;/code&gt;で払い出された&lt;code&gt;LoadBalancer Service&lt;/code&gt;のIP越しに&lt;code&gt;Ingress&lt;/code&gt;経由のリクエストを送ってみる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 払い出したExretnalIPで接続できた!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -H &lt;span class="s2"&gt;&amp;#34;Host: hello-world.info&amp;#34;&lt;/span&gt; 10.240.0.10/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Hello, world!
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Version: 1.0.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Hostname: web-7c884bf475-tt9g6&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;できた〜〜🎉&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;10.240.0.10&lt;/strong&gt;にサーバが立ってないのにリクエストができるのは&lt;a class="link" href="https://metallb.universe.tf/concepts/layer2/" target="_blank" rel="noopener"
 &gt;MetalLB&lt;/a&gt;の&lt;code&gt;speaker&lt;/code&gt;が同じネットワークに送られたARPリクエストに対して応答するおかげらしい(まだちゃんと理解してない)。&lt;/p&gt;
&lt;p&gt;よくわかってないけどとりあえず普通のポートで&lt;code&gt;Ingress&lt;/code&gt;が動いたのでヨシ!&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;自前のクラスタに&lt;code&gt;Ingress Controller&lt;/code&gt;を突っ込む練習をしてみた。&lt;br&gt;
正直なところドキュメント通りにyamlをapplyするだけで簡単に設定できてしまったので本当に身についたかは怪しいが、&lt;br&gt;
&lt;code&gt;Ingress Class&lt;/code&gt;については&lt;code&gt;Ingress Controller&lt;/code&gt;を意識しないと触れる機会が少ないし、実際あまりわかってなかったので勉強になってよかった。&lt;br&gt;
&lt;code&gt;MetalLB&lt;/code&gt;についてはまたどこかでお世話になりそうなのでそのときにちゃんと勉強したい。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="ねこか？" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-10-28-ingress-nginx-bare-metal/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2021-10-28-ingress-nginx-bare-metal/sotochan_hu_b25ca99f414a4416.jpg 800w, https://blog.uzimihsr.com/post/2021-10-28-ingress-nginx-bare-metal/sotochan_hu_f019e85f0e5d5cef.jpg 1600w, https://blog.uzimihsr.com/post/2021-10-28-ingress-nginx-bare-metal/sotochan_hu_8cf6a95093c45490.jpg 2400w, https://blog.uzimihsr.com/post/2021-10-28-ingress-nginx-bare-metal/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>Ubuntu+kubeadm+containerd+CalicoでシングルmasterのKubernetesクラスタをつくる</title><link>https://blog.uzimihsr.com/post/2021-10-15-create-kubernetes-cluster-with-kubeadm-containerd-calico/</link><pubDate>Fri, 15 Oct 2021 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2021-10-15-create-kubernetes-cluster-with-kubeadm-containerd-calico/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2021-10-15-create-kubernetes-cluster-with-kubeadm-containerd-calico/sotochan.jpg" alt="Featured image of post Ubuntu+kubeadm+containerd+CalicoでシングルmasterのKubernetesクラスタをつくる" /&gt;&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;p&gt;クラスタ操作の練習用に&lt;code&gt;GKE&lt;/code&gt;みたいなマネージドではない自前の&lt;code&gt;Kubernetes&lt;/code&gt;クラスタがほしくて、&lt;br&gt;
かつ運用の練習としては&lt;code&gt;kind&lt;/code&gt;や&lt;code&gt;Minikube&lt;/code&gt;みたいなやつだと物足りない。&lt;br&gt;
とはいえ&lt;a class="link" href="https://github.com/kelseyhightower/kubernetes-the-hard-way" target="_blank" rel="noopener"
 &gt;Kubernetes The Hard Way&lt;/a&gt;するほどじゃないんだよな&amp;hellip;みたいな気分になったので、&lt;br&gt;
おさらいも兼ねて&lt;code&gt;kubeadm&lt;/code&gt;でクラスタを立てることにした。&lt;br&gt;
基本的に&lt;a class="link" href="https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/" target="_blank" rel="noopener"
 &gt;Creating a cluster with kubeadm&lt;/a&gt;をなぞっているだけ。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://console.cloud.google.com/" target="_blank" rel="noopener"
 &gt;GCP&lt;/a&gt;でVMとネットワークを作成した&lt;/li&gt;
&lt;li&gt;&lt;code&gt;kubeadm&lt;/code&gt;を使って&lt;code&gt;Kubernetes&lt;/code&gt;クラスタをつくった&lt;/li&gt;
&lt;li&gt;コンテナランタイムには&lt;a class="link" href="https://containerd.io/" target="_blank" rel="noopener"
 &gt;containerd&lt;/a&gt;, ネットワークアドオンは&lt;a class="link" href="https://www.tigera.io/project-calico/" target="_blank" rel="noopener"
 &gt;Calico&lt;/a&gt;を使用した&lt;/li&gt;
&lt;li&gt;あまり長くつかっているとお金がかかるのでおかたづけした&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Big Sur 11.2.3&lt;/li&gt;
&lt;li&gt;Google Cloud SDK 360.0.0
&lt;ul&gt;
&lt;li&gt;GCP操作に使用&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Ubuntu 20.04.3 LTS (GNU/Linux 5.11.0-1020-gcp x86_64)
&lt;ul&gt;
&lt;li&gt;node用のVMとして使用&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;containerd 1.4.11
&lt;ul&gt;
&lt;li&gt;コンテナランタイム&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Calico v3.20.2
&lt;ul&gt;
&lt;li&gt;ネットワークアドオン&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Kubernetes v1.22.2&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%8d%e3%83%83%e3%83%88%e3%83%af%e3%83%bc%e3%82%af%e3%81%a8vm%e3%81%ae%e6%ba%96%e5%82%99gcp" &gt;ネットワークとVMの準備(GCP)&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#vpc%e3%83%8d%e3%83%83%e3%83%88%e3%83%af%e3%83%bc%e3%82%af%e3%81%ae%e4%bd%9c%e6%88%90" &gt;VPCネットワークの作成&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#vm%e3%82%a4%e3%83%b3%e3%82%b9%e3%82%bf%e3%83%b3%e3%82%b9%e3%81%ae%e4%bd%9c%e6%88%90" &gt;VMインスタンスの作成&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#node%e3%81%ae%e6%ba%96%e5%82%99" &gt;nodeの準備&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%b3%e3%83%b3%e3%83%86%e3%83%8a%e3%83%a9%e3%83%b3%e3%82%bf%e3%82%a4%e3%83%a0containerd%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" &gt;コンテナランタイム(containerd)のインストール&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#kubeletkubeadmkubectl%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" &gt;kubelet,kubeadm,kubectlのインストール&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#master%e3%81%ae%e8%b5%b7%e5%8b%95" &gt;masterの起動&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%8d%e3%83%83%e3%83%88%e3%83%af%e3%83%bc%e3%82%af%e3%82%a2%e3%83%89%e3%82%aa%e3%83%b3calico%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" &gt;ネットワークアドオン(Calico)のインストール&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#worker%e3%81%ae%e8%b5%b7%e5%8b%95" &gt;workerの起動&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%8a%e3%81%8b%e3%81%9f%e3%81%a5%e3%81%91" &gt;おかたづけ&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="ネットワークとvmの準備gcp"&gt;ネットワークとVMの準備(GCP)
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;gcloud&lt;/code&gt;のセットアップは&lt;a class="link" href="https://cloud.google.com/sdk/docs/quickstart-macos" target="_blank" rel="noopener"
 &gt;macOS用のクイックスタート&lt;/a&gt;で終わっている前提。&lt;/p&gt;
&lt;h4 id="vpcネットワークの作成"&gt;VPCネットワークの作成
&lt;/h4&gt;&lt;p&gt;まずは&lt;code&gt;node&lt;/code&gt;同士をつなぐためのネットワークを設定する。&lt;br&gt;
&lt;code&gt;GCP&lt;/code&gt;では&lt;a class="link" href="https://cloud.google.com/vpc/docs/using-vpc" target="_blank" rel="noopener"
 &gt;VPCネットワーク&lt;/a&gt;を使う。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Macで実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# VPCネットワークの作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# サブネットのIPレンジは10.240.0.0/24(最大256node使用可能)にする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gcloud compute networks create kubernetes-vpc-network --subnet-mode&lt;span class="o"&gt;=&lt;/span&gt;custom
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gcloud compute networks subnets create kubernetes-vpc-network-subnet --range&lt;span class="o"&gt;=&lt;/span&gt;10.240.0.0/24 --network&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-vpc-network
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ネットワークのIPレンジ内からネットワーク上の任意のnodeへの任意のプロトコルでの接続を許可(kubernetes-vpc-network-allow-internal)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 任意の送信元からネットワーク上の任意のnodeへの特定ポートへの特定プロトコルでの接続を許可(kubernetes-vpc-network-allow-external)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# tcp:22はnodeへのSSHに, tcp:6443はkube-apiserverへのリクエストに, icmpはpingでの監視に使用&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gcloud compute firewall-rules create kubernetes-vpc-network-allow-internal --network&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-vpc-network --allow all --source-ranges&lt;span class="o"&gt;=&lt;/span&gt;10.240.0.0/24
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gcloud compute firewall-rules create kubernetes-vpc-network-allow-external --network kubernetes-vpc-network --allow tcp:22,tcp:6443,icmp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id="vmインスタンスの作成"&gt;VMインスタンスの作成
&lt;/h4&gt;&lt;p&gt;つぎにクラスタの&lt;code&gt;node&lt;/code&gt;として使う&lt;a class="link" href="https://cloud.google.com/compute/docs/instances/create-start-instance" target="_blank" rel="noopener"
 &gt;VMインスタンス&lt;/a&gt;を&lt;code&gt;master&lt;/code&gt;用と&lt;code&gt;worker&lt;/code&gt;用にそれぞれ1台ずつ建てる。&lt;br&gt;
&lt;a class="link" href="https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/" target="_blank" rel="noopener"
 &gt;Creating a cluster with kubeadm&lt;/a&gt;によると&lt;code&gt;master&lt;/code&gt;は最低でも2GiB RAM, 2CPUsがあるといいらしいのでマシンタイプはそれを満たすように気をつける。&lt;br&gt;
OSの起動imageは&lt;code&gt;Ubuntu 20.04 LTS&lt;/code&gt;を使用した。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Macで実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# master(e2-medium),worker(e2-small)用インスタンスの作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gcloud compute instances create kubernetes-master --machine-type&lt;span class="o"&gt;=&lt;/span&gt;e2-medium --image-family&lt;span class="o"&gt;=&lt;/span&gt;ubuntu-2004-lts --image-project&lt;span class="o"&gt;=&lt;/span&gt;ubuntu-os-cloud --subnet&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-vpc-network-subnet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gcloud compute instances create kubernetes-worker --machine-type&lt;span class="o"&gt;=&lt;/span&gt;e2-small --image-family&lt;span class="o"&gt;=&lt;/span&gt;ubuntu-2004-lts --image-project&lt;span class="o"&gt;=&lt;/span&gt;ubuntu-os-cloud --subnet&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-vpc-network-subnet&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;最終的に以下のようになっていればOK。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ gcloud compute networks list --filter&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;name=kubernetes-vpc-network&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME SUBNET_MODE BGP_ROUTING_MODE IPV4_RANGE GATEWAY_IPV4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-vpc-network CUSTOM REGIONAL
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ gcloud compute networks subnets list --filter&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;name=kubernetes-vpc-network-subnet&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME REGION NETWORK RANGE STACK_TYPE IPV6_ACCESS_TYPE IPV6_CIDR_RANGE EXTERNAL_IPV6_CIDR_RANGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-vpc-network-subnet us-central1 kubernetes-vpc-network 10.240.0.0/24 IPV4_ONLY
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ gcloud compute firewall-rules list --filter&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;network=kubernetes-vpc-network&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME NETWORK DIRECTION PRIORITY ALLOW DENY DISABLED
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-vpc-network-allow-external kubernetes-vpc-network INGRESS &lt;span class="m"&gt;1000&lt;/span&gt; tcp:22,tcp:6443,icmp False
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-vpc-network-allow-internal kubernetes-vpc-network INGRESS &lt;span class="m"&gt;1000&lt;/span&gt; all False
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ gcloud compute instances list
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME ZONE MACHINE_TYPE PREEMPTIBLE INTERNAL_IP EXTERNAL_IP STATUS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-master us-central1-a e2-medium 10.240.0.4 xx.xx.xx.xxx RUNNING
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-worker us-central1-a e2-small 10.240.0.5 yy.yyy.yyy.yy RUNNING&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="nodeの準備"&gt;nodeの準備
&lt;/h3&gt;&lt;p&gt;ネットワークと&lt;code&gt;node&lt;/code&gt;用&lt;code&gt;VM&lt;/code&gt;が準備できたので、いよいよクラスタを構築していく。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# SSHするときは以下のコマンドを使う&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gcloud compute ssh kubernetes-master
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gcloud compute ssh kubernetes-worker&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id="コンテナランタイムcontainerdのインストール"&gt;コンテナランタイム(containerd)のインストール
&lt;/h4&gt;&lt;p&gt;&lt;code&gt;master&lt;/code&gt;と&lt;code&gt;worker&lt;/code&gt;で共に&lt;code&gt;Pod&lt;/code&gt;(コンテナ)を動かすために必要な&lt;a class="link" href="https://kubernetes.io/docs/setup/production-environment/container-runtimes/" target="_blank" rel="noopener"
 &gt;コンテナランタイム&lt;/a&gt;をインストールする。&lt;br&gt;
コンテナランタイムにはいくつか候補があるが、今回は&lt;a class="link" href="https://containerd.io/" target="_blank" rel="noopener"
 &gt;containerd&lt;/a&gt;を使う。&lt;br&gt;
&lt;code&gt;Ubuntu&lt;/code&gt;でのインストール手順は&lt;a class="link" href="https://docs.docker.com/engine/install/ubuntu/" target="_blank" rel="noopener"
 &gt;Install Docker Engine on Ubuntu&lt;/a&gt;を参考にする。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# master/worker両方でそれぞれ実行する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# VM起動時にkernelモジュール(overlay, br_netfilter)を読み込むための設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat &lt;span class="s"&gt;&amp;lt;&amp;lt;EOF | sudo tee /etc/modules-load.d/containerd.conf
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;overlay
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;br_netfilter
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# kernelモジュール(overlay, br_netfilter)の手動読み込み&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo modprobe overlay &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo modprobe br_netfilter
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# kernelパラメータを変更(永続化)する設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat &lt;span class="s"&gt;&amp;lt;&amp;lt;EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;net.bridge.bridge-nf-call-iptables = 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;net.ipv4.ip_forward = 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;net.bridge.bridge-nf-call-ip6tables = 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# kernelパラメータの適用&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo sysctl --system
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# (ないと思うが)古いpackageを削除&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt-get remove docker docker-engine docker.io containerd runc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# aptのpackage indexの更新とHTTPSでリポジトリを使うために必要なpackageのインストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo apt-get install -y apt-transport-https ca-certificates curl gnupg lsb-release
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Docker公式のGPG鍵追加 &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl -fsSL https://download.docker.com/linux/ubuntu/gpg &lt;span class="p"&gt;|&lt;/span&gt; sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Dockerのstableリポジトリ追加&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;deb [arch=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;dpkg --print-architecture&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;lsb_release -cs&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; stable&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sudo tee /etc/apt/sources.list.d/docker.list &amp;gt; /dev/null
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# containerdのインストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo apt-get install -y containerd.io
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# containerdの設定ファイル作成(96行目付近にsystemdのcgroupドライバーを使う設定を入れる)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo mkdir -p /etc/containerd
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;containerd config default &lt;span class="p"&gt;|&lt;/span&gt; sudo tee /etc/containerd/config.toml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo vim /etc/containerd/config.toml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# containerdの再起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo systemctl restart containerd&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;containerd&lt;/code&gt;を動かす&lt;code&gt;cgroup&lt;/code&gt;が&lt;code&gt;systemd&lt;/code&gt;になる&lt;code&gt;/etc/containerd/config.toml&lt;/code&gt;の設定は&lt;a class="link" href="https://kubernetes.io/docs/setup/production-environment/container-runtimes/#containerd-systemd" target="_blank" rel="noopener"
 &gt;Using the systemd cgroup driver&lt;/a&gt;に従った。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-toml" data-lang="toml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;io.containerd.grpc.v1.cri&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;containerd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;runtimes&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;io.containerd.grpc.v1.cri&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;containerd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;runtimes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;runc&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;runtime_type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;io.containerd.runc.v2&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;runtime_engine&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;runtime_root&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;privileged_without_host_devices&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;base_runtime_spec&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;io.containerd.grpc.v1.cri&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;containerd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;runtimes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;runc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;SystemdCgroup&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;systemd&lt;/code&gt;で&lt;code&gt;containerd&lt;/code&gt;が動いていることを確認できればOK。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-worker:~$ systemctl is-active containerd
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;active&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id="kubeletkubeadmkubectlのインストール"&gt;kubelet,kubeadm,kubectlのインストール
&lt;/h4&gt;&lt;p&gt;コンテナランタイムがインストールできたら、次は&lt;a class="link" href="https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/#installing-kubeadm-kubelet-and-kubectl" target="_blank" rel="noopener"
 &gt;Installing kubeadm, kubelet and kubectl&lt;/a&gt;に従って&lt;code&gt;Kubernetes&lt;/code&gt;クラスタに必要なコンポーネントを&lt;code&gt;master&lt;/code&gt;と&lt;code&gt;worker&lt;/code&gt;両方にインストールする。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# master/worker両方でそれぞれ実行する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Google CloudのGPG鍵追加&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Kubernetesリポジトリ追加&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sudo tee /etc/apt/sources.list.d/kubernetes.list
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# kubelet,kubeadm,kubectlのインストールとバージョン固定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo apt-get install -y kubelet kubeadm kubectl &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo apt-mark hold kubelet kubeadm kubectl&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="masterの起動"&gt;masterの起動
&lt;/h3&gt;&lt;p&gt;コンテナランタイムと&lt;code&gt;kubeadm&lt;/code&gt;の準備ができたらまずは&lt;code&gt;master node (control-plane)&lt;/code&gt;を作成する。&lt;br&gt;
今回はネットワークアドオンに&lt;a class="link" href="https://docs.projectcalico.org/getting-started/kubernetes/quickstart" target="_blank" rel="noopener"
 &gt;Calico&lt;/a&gt;を使うため、&lt;code&gt;kubeadm init&lt;/code&gt;のオプションを付与する。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# masterでのみ実行する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# master nodeのセットアップ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo kubeadm init --pod-network-cidr&lt;span class="o"&gt;=&lt;/span&gt;192.168.0.0/16
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# kubeconfigの準備&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mkdir -p &lt;span class="nv"&gt;$HOME&lt;/span&gt;/.kube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo cp -i /etc/kubernetes/admin.conf &lt;span class="nv"&gt;$HOME&lt;/span&gt;/.kube/config
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo chown &lt;span class="k"&gt;$(&lt;/span&gt;id -u&lt;span class="k"&gt;)&lt;/span&gt;:&lt;span class="k"&gt;$(&lt;/span&gt;id -g&lt;span class="k"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;$HOME&lt;/span&gt;/.kube/config
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# kubectlの準備&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;source&lt;/span&gt; &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;kubectl completion bash&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nv"&gt;k&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubectl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;complete&lt;/span&gt; -F __start_kubectl k&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;これで&lt;code&gt;master node&lt;/code&gt;が作成できた&amp;hellip;と思いきや、&lt;br&gt;
この時点ではまだネットワークアドオンが入っていないため&lt;code&gt;Pod&lt;/code&gt;間の通信ができず、&lt;code&gt;CoreDNS&lt;/code&gt;が立ち上がらない。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-master:~$ k get pods -A
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAMESPACE NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube-system coredns-78fcd69978-dzwrb 0/1 Pending &lt;span class="m"&gt;0&lt;/span&gt; 3m25s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube-system coredns-78fcd69978-ffpvj 0/1 Pending &lt;span class="m"&gt;0&lt;/span&gt; 3m25s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube-system etcd-kubernetes-master 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 3m33s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube-system kube-apiserver-kubernetes-master 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 3m33s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube-system kube-controller-manager-kubernetes-master 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 3m33s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube-system kube-proxy-zk7mn 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 3m25s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube-system kube-scheduler-kubernetes-master 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 3m33s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="ネットワークアドオンcalicoのインストール"&gt;ネットワークアドオン(Calico)のインストール
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;kubeadm init&lt;/code&gt;が終わったので、&lt;br&gt;
つぎにネットワークアドオンとして&lt;a class="link" href="https://docs.projectcalico.org/getting-started/kubernetes/quickstart" target="_blank" rel="noopener"
 &gt;Calico&lt;/a&gt;をインストールする。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# masterでのみ実行する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Calicoのインストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;k create -f https://docs.projectcalico.org/manifests/tigera-operator.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;k create -f https://docs.projectcalico.org/manifests/custom-resources.yaml&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;Calico&lt;/code&gt;に必要な&lt;code&gt;Pod&lt;/code&gt;の作成には時間がかかるのですこし待つ。&lt;br&gt;
次のようになっていればOK。&lt;br&gt;
&lt;code&gt;CoreDNS&lt;/code&gt;も立ち上がっている。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-master:~$ k get pods -A
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAMESPACE NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;calico-apiserver calico-apiserver-6dd4bc68c6-lslcj 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 12s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;calico-system calico-kube-controllers-767ddd5576-64dj8 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 80s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;calico-system calico-node-2fx6b 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 80s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;calico-system calico-typha-5bf9887dd7-hrtwj 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 80s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube-system coredns-78fcd69978-dzwrb 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 12m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube-system coredns-78fcd69978-ffpvj 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 12m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube-system etcd-kubernetes-master 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 12m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube-system kube-apiserver-kubernetes-master 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 12m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube-system kube-controller-manager-kubernetes-master 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 12m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube-system kube-proxy-zk7mn 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 12m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube-system kube-scheduler-kubernetes-master 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 12m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tigera-operator tigera-operator-59f4845b57-qgq6c 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 111s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="workerの起動"&gt;workerの起動
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;master&lt;/code&gt;1台の&lt;code&gt;Kubernetes&lt;/code&gt;クラスタができたので、&lt;br&gt;
次に&lt;code&gt;worker&lt;/code&gt;をこのクラスタに追加する。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;node&lt;/code&gt;の追加に必要なトークンとCA証明書のハッシュ値は&lt;code&gt;master&lt;/code&gt;側で取得する。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# masterでのみ実行する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 新規tokenの作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-master:~$ kubeadm token create
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;token&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# CA証明書ハッシュの取得&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-master:~$ openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt &lt;span class="p"&gt;|&lt;/span&gt; openssl rsa -pubin -outform der 2&amp;gt;/dev/null &lt;span class="p"&gt;|&lt;/span&gt; openssl dgst -sha256 -hex &lt;span class="p"&gt;|&lt;/span&gt; sed &lt;span class="s1"&gt;&amp;#39;s/^.* //&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;hash&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# master nodeのホストとIPを取得&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-master:~$ k cluster-info &lt;span class="p"&gt;|&lt;/span&gt; grep control
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Kubernetes control plane is running at https://&amp;lt;control-plane-host&amp;gt;:&amp;lt;control-plane-port&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;master&lt;/code&gt;で取得した情報を使って&lt;code&gt;worker&lt;/code&gt;を&lt;code&gt;kubeadm join&lt;/code&gt;してクラスタに追加する。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# workerでのみ実行する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo kubeadm join --token &amp;lt;token&amp;gt; &amp;lt;control-plane-host&amp;gt;:&amp;lt;control-plane-port&amp;gt; --discovery-token-ca-cert-hash sha256:&amp;lt;hash&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;This node has joined the cluster&lt;/code&gt;と表示されれば&lt;code&gt;worker&lt;/code&gt;がクラスタに追加できている。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;master&lt;/code&gt;側で確認すると&lt;code&gt;worker&lt;/code&gt;が認識されていて、各種&lt;code&gt;DaemonSet&lt;/code&gt;の&lt;code&gt;Pod&lt;/code&gt;もちゃんと&lt;code&gt;worker&lt;/code&gt;に配置されている。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-master:~$ k get nodes -o wide
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-master Ready control-plane,master 25m v1.22.2 10.240.0.4 &amp;lt;none&amp;gt; Ubuntu 20.04.3 LTS 5.11.0-1020-gcp containerd://1.4.11
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-worker Ready &amp;lt;none&amp;gt; 91s v1.22.2 10.240.0.5 &amp;lt;none&amp;gt; Ubuntu 20.04.3 LTS 5.11.0-1020-gcp containerd://1.4.11
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-master:~$ k get all -A -o wide
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;calico-apiserver pod/calico-apiserver-6dd4bc68c6-lslcj 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 19m 192.168.237.5 kubernetes-master &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;calico-system pod/calico-kube-controllers-767ddd5576-64dj8 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 20m 192.168.237.2 kubernetes-master &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;calico-system pod/calico-node-2fx6b 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 20m 10.240.0.4 kubernetes-master &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;calico-system pod/calico-node-vkmhc 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 7m7s 10.240.0.5 kubernetes-worker &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;calico-system pod/calico-typha-5bf9887dd7-hrtwj 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 20m 10.240.0.4 kubernetes-master &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;calico-system pod/calico-typha-5bf9887dd7-v8plr 1/1 Running &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;6m33s ago&lt;span class="o"&gt;)&lt;/span&gt; 7m4s 10.240.0.5 kubernetes-worker &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube-system pod/coredns-78fcd69978-dzwrb 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 31m 192.168.237.1 kubernetes-master &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube-system pod/coredns-78fcd69978-ffpvj 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 31m 192.168.237.3 kubernetes-master &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube-system pod/etcd-kubernetes-master 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 31m 10.240.0.4 kubernetes-master &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube-system pod/kube-apiserver-kubernetes-master 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 31m 10.240.0.4 kubernetes-master &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube-system pod/kube-controller-manager-kubernetes-master 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 31m 10.240.0.4 kubernetes-master &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube-system pod/kube-proxy-xj444 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 7m7s 10.240.0.5 kubernetes-worker &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube-system pod/kube-proxy-zk7mn 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 31m 10.240.0.4 kubernetes-master &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube-system pod/kube-scheduler-kubernetes-master 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 31m 10.240.0.4 kubernetes-master &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tigera-operator pod/tigera-operator-59f4845b57-qgq6c 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 20m 10.240.0.4 kubernetes-master &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE SELECTOR
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;calico-apiserver service/calico-api ClusterIP 10.110.66.91 &amp;lt;none&amp;gt; 443/TCP 19m &lt;span class="nv"&gt;apiserver&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;calico-system service/calico-kube-controllers-metrics ClusterIP 10.106.106.192 &amp;lt;none&amp;gt; 9094/TCP 19m k8s-app&lt;span class="o"&gt;=&lt;/span&gt;calico-kube-controllers
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;calico-system service/calico-typha ClusterIP 10.110.34.28 &amp;lt;none&amp;gt; 5473/TCP 20m k8s-app&lt;span class="o"&gt;=&lt;/span&gt;calico-typha
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;default service/kubernetes ClusterIP 10.96.0.1 &amp;lt;none&amp;gt; 443/TCP 31m &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube-system service/kube-dns ClusterIP 10.96.0.10 &amp;lt;none&amp;gt; 53/UDP,53/TCP,9153/TCP 31m k8s-app&lt;span class="o"&gt;=&lt;/span&gt;kube-dns
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAMESPACE NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE CONTAINERS IMAGES SELECTOR
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;calico-system daemonset.apps/calico-node &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; kubernetes.io/os&lt;span class="o"&gt;=&lt;/span&gt;linux 20m calico-node docker.io/calico/node:v3.20.2 k8s-app&lt;span class="o"&gt;=&lt;/span&gt;calico-node
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube-system daemonset.apps/kube-proxy &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; kubernetes.io/os&lt;span class="o"&gt;=&lt;/span&gt;linux 31m kube-proxy k8s.gcr.io/kube-proxy:v1.22.2 k8s-app&lt;span class="o"&gt;=&lt;/span&gt;kube-proxy
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAMESPACE NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;calico-apiserver deployment.apps/calico-apiserver 1/1 &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 19m calico-apiserver docker.io/calico/apiserver:v3.20.2 &lt;span class="nv"&gt;apiserver&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;calico-system deployment.apps/calico-kube-controllers 1/1 &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 20m calico-kube-controllers docker.io/calico/kube-controllers:v3.20.2 k8s-app&lt;span class="o"&gt;=&lt;/span&gt;calico-kube-controllers
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;calico-system deployment.apps/calico-typha 2/2 &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; 20m calico-typha docker.io/calico/typha:v3.20.2 k8s-app&lt;span class="o"&gt;=&lt;/span&gt;calico-typha
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube-system deployment.apps/coredns 2/2 &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; 31m coredns k8s.gcr.io/coredns/coredns:v1.8.4 k8s-app&lt;span class="o"&gt;=&lt;/span&gt;kube-dns
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tigera-operator deployment.apps/tigera-operator 1/1 &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 20m tigera-operator quay.io/tigera/operator:v1.20.4 &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;tigera-operator
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAMESPACE NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;calico-apiserver replicaset.apps/calico-apiserver-6dd4bc68c6 &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 19m calico-apiserver docker.io/calico/apiserver:v3.20.2 &lt;span class="nv"&gt;apiserver&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;true,pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;6dd4bc68c6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;calico-apiserver replicaset.apps/calico-apiserver-788fc95f55 &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; 19m calico-apiserver docker.io/calico/apiserver:v3.20.2 &lt;span class="nv"&gt;apiserver&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;true,pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;788fc95f55
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;calico-system replicaset.apps/calico-kube-controllers-767ddd5576 &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 20m calico-kube-controllers docker.io/calico/kube-controllers:v3.20.2 k8s-app&lt;span class="o"&gt;=&lt;/span&gt;calico-kube-controllers,pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;767ddd5576
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;calico-system replicaset.apps/calico-typha-5bf9887dd7 &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; 20m calico-typha docker.io/calico/typha:v3.20.2 k8s-app&lt;span class="o"&gt;=&lt;/span&gt;calico-typha,pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;5bf9887dd7
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube-system replicaset.apps/coredns-78fcd69978 &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; 31m coredns k8s.gcr.io/coredns/coredns:v1.8.4 k8s-app&lt;span class="o"&gt;=&lt;/span&gt;kube-dns,pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;78fcd69978
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tigera-operator replicaset.apps/tigera-operator-59f4845b57 &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 20m tigera-operator quay.io/tigera/operator:v1.20.4 &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;tigera-operator,pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;59f4845b57&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;これで1&lt;code&gt;master&lt;/code&gt;-1&lt;code&gt;worker&lt;/code&gt;の&lt;code&gt;Kubernetes&lt;/code&gt;クラスタをつくることができた。&lt;/p&gt;
&lt;p&gt;後はVMのリソースが尽きない限り何でも自由にやりたい放題できる。&lt;/p&gt;
&lt;h3 id="おかたづけ"&gt;おかたづけ
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;GCP&lt;/code&gt;で建てた&lt;code&gt;VM&lt;/code&gt;は今回&lt;code&gt;master&lt;/code&gt;に使用した&lt;code&gt;e2-medium&lt;/code&gt;だけでも1ヶ月で約3000円くらいかかってしまう。&lt;/p&gt;
&lt;p&gt;&lt;img alt="おかねなくなる" class="gallery-image" data-flex-basis="422px" data-flex-grow="175" height="531" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-10-15-create-kubernetes-cluster-with-kubeadm-containerd-calico/sc01.png" srcset="https://blog.uzimihsr.com/post/2021-10-15-create-kubernetes-cluster-with-kubeadm-containerd-calico/sc01_hu_d234e8e739e7a6af.png 800w, https://blog.uzimihsr.com/post/2021-10-15-create-kubernetes-cluster-with-kubeadm-containerd-calico/sc01.png 934w" width="934"&gt;&lt;/p&gt;
&lt;p&gt;お金に余裕があればいいんだけど、練習用のクラスタなので使わなくなったらさっさと片付けるべき。&lt;br&gt;
(昔デカめの&lt;code&gt;Kubernetes&lt;/code&gt;クラスタを放置してたら無料枠$300が1ヶ月で吹き飛んた)&lt;/p&gt;
&lt;p&gt;&lt;code&gt;VM&lt;/code&gt;をそのまま吹き飛ばしても良いのだが、練習として&lt;code&gt;kubeadm&lt;/code&gt;を使ったお掃除をしてみる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# masterでのみ実行する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# workerのPodを退去させる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl drain kubernetes-worker --delete-local-data --force --ignore-daemonsets&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# workerでのみ実行する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# kubadm joinによって設定されたものを設定前に戻す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo kubeadm reset
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo rm -rf /etc/cni/net.d&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# masterでのみ実行する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# workerを削除する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl delete node kubernetes-worker
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# kubeadm initによって設定されたものを設定前に戻す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo kubeadm reset
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo rm -rf /etc/cni/net.d&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;あとは粛々と&lt;code&gt;Kubernetes&lt;/code&gt;コンポーネントとコンテナランタイムを削除していく。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# master/worker両方でそれぞれ実行する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Kubernetesコンポーネントの削除&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt-get purge -y --allow-change-held-packages kubelet kubeadm kubectl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt-get purge -y --allow-change-held-packages containerd.io&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;最後に&lt;code&gt;gcloud&lt;/code&gt;で作ったリソースを削除する。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Macで実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# GCPリソースの削除(いきなりこれをやってもOK)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gcloud compute instances delete kubernetes-master kubernetes-worker
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gcloud compute firewall-rules delete kubernetes-vpc-network-allow-internal kubernetes-vpc-network-allow-external
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gcloud compute networks subnets delete kubernetes-vpc-network-subnet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gcloud compute networks delete kubernetes-vpc-network&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;これで綺麗さっぱりおかたづけできたのでお財布のダメージも少ないはず。&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/" target="_blank" rel="noopener"
 &gt;Creating a cluster with kubeadm&lt;/a&gt;をなぞって練習用の&lt;code&gt;Kubernetes&lt;/code&gt;クラスタをつくった。&lt;br&gt;
基本的にはドキュメントさえ見ればできるんだけど、参照するドキュメントが何枚もあったりしてたまに混乱するので具体的な手順を1枚にできてよかった。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="くつろぐねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-10-15-create-kubernetes-cluster-with-kubeadm-containerd-calico/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2021-10-15-create-kubernetes-cluster-with-kubeadm-containerd-calico/sotochan_hu_c959f14d33ffdca7.jpg 800w, https://blog.uzimihsr.com/post/2021-10-15-create-kubernetes-cluster-with-kubeadm-containerd-calico/sotochan_hu_be00fdb17602cf3c.jpg 1600w, https://blog.uzimihsr.com/post/2021-10-15-create-kubernetes-cluster-with-kubeadm-containerd-calico/sotochan_hu_8aa4b3ab75840e83.jpg 2400w, https://blog.uzimihsr.com/post/2021-10-15-create-kubernetes-cluster-with-kubeadm-containerd-calico/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>CKSを受験した</title><link>https://blog.uzimihsr.com/post/2021-10-10-cks/</link><pubDate>Sun, 10 Oct 2021 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2021-10-10-cks/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2021-10-10-cks/sotochan.jpg" alt="Featured image of post CKSを受験した" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;CKSを受験した&lt;/li&gt;
&lt;li&gt;今回も試験シミュレータ(Killer Shell)で十分対策できた&lt;/li&gt;
&lt;li&gt;試験中に参照できるドキュメントはCKAよりも多い&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="もくじ"&gt;もくじ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e8%a9%a6%e9%a8%93%e5%af%be%e7%ad%96" &gt;試験対策&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e8%a9%a6%e9%a8%93%e6%9c%ac%e7%95%aa" &gt;試験本番&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e7%b5%90%e6%9e%9c" &gt;結果&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="試験対策"&gt;試験対策
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2021-09-14-cka/" target="_blank" rel="noopener"
 &gt;CKA&lt;/a&gt;を取ってからモチベーションの高いうちに&lt;a class="link" href="https://training.linuxfoundation.org/certification/certified-kubernetes-security-specialist/" target="_blank" rel="noopener"
 &gt;CKS&lt;/a&gt;を受けることにした。&lt;br&gt;
勉強から先に始めるといつまでたっても終わらないマンなので今回も試験日を先に決めて(CKS合格の約2週後)、それに向けて勉強する方式を取った。&lt;/p&gt;
&lt;p&gt;まずは&lt;code&gt;CKS&lt;/code&gt;にバンドルされた教材(&lt;a class="link" href="https://training.linuxfoundation.org/training/kubernetes-security-essentials-lfs260/" target="_blank" rel="noopener"
 &gt;LFS260&lt;/a&gt;)を1週間で一通り読み込んだ。&lt;br&gt;
今回は初めて触る内容も多かったので割と真面目に読んで、Exerciseもちゃんと手を動かして解いた。&lt;br&gt;
&lt;a class="link" href="https://github.com/aquasecurity/trivy" target="_blank" rel="noopener"
 &gt;trivy&lt;/a&gt;や&lt;a class="link" href="https://github.com/aquasecurity/kube-bench" target="_blank" rel="noopener"
 &gt;kube-bench&lt;/a&gt;などの&lt;code&gt;Kubernetes&lt;/code&gt;にデフォルトで含まれていないツールについての練習もできてよかったと思う。&lt;br&gt;
量的には&lt;code&gt;CKA&lt;/code&gt;用の教材(&lt;a class="link" href="https://training.linuxfoundation.org/training/kubernetes-fundamentals/" target="_blank" rel="noopener"
 &gt;LFS258&lt;/a&gt;)よりすこし少ない程度だったが、連休だったのもあってなんとか終わらせることができた。&lt;/p&gt;
&lt;p&gt;教材を終わらせた後、前回同様に&lt;a class="link" href="https://killer.sh/" target="_blank" rel="noopener"
 &gt;Killer Shell&lt;/a&gt;の試験シミュレータで模擬試験を解いた。&lt;br&gt;
&lt;code&gt;CKA&lt;/code&gt;合格が前提とされている試験だけあり、クラスタの設定に関する問題は普通に出てくるしさらに先述のツール類を使う問題も出るので内容としてはかなり難しかったように思う。&lt;br&gt;
初回はドキュメントを見ないとほぼ0点だった。&lt;/p&gt;
&lt;p&gt;また、&lt;code&gt;CKS&lt;/code&gt;では&lt;code&gt;CKAD&lt;/code&gt;や&lt;code&gt;CKA&lt;/code&gt;と異なり&lt;code&gt;Kubernetes&lt;/code&gt;公式ドキュメント以外にも&lt;a class="link" href="https://github.com/aquasecurity/trivy" target="_blank" rel="noopener"
 &gt;trivy&lt;/a&gt;, &lt;a class="link" href="https://docs.sysdig.com/" target="_blank" rel="noopener"
 &gt;sysdig&lt;/a&gt;, &lt;a class="link" href="https://falco.org/docs" target="_blank" rel="noopener"
 &gt;Falco&lt;/a&gt;, &lt;a class="link" href="https://gitlab.com/apparmor/apparmor/-/wikis/Documentation" target="_blank" rel="noopener"
 &gt;AppArmor&lt;/a&gt;のドキュメントが試験中に参照可能であることをここで初めて知った。&lt;br&gt;
これらのツールも模擬試験では容赦なく出題されていたので、試験で使えそうなページをブックマークしておいた。&lt;/p&gt;
&lt;h3 id="試験本番"&gt;試験本番
&lt;/h3&gt;&lt;p&gt;今回も自宅で試験を受けた。&lt;br&gt;
もちろん&lt;a class="link" href="https://uzimihsr.github.io/post/2021-09-14-cka/" target="_blank" rel="noopener"
 &gt;ねこもいっしょ&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;今回は試験開始時刻になっても試験官が来ない?トラブルがあったため、5分遅れくらいでスタートした。&lt;br&gt;
試験前の試験官とのやりとりはこれまでと全く一緒。&lt;/p&gt;
&lt;p&gt;今回も試験時間は2時間で問題数は17問くらいだった。&lt;br&gt;
やはり&lt;a class="link" href="https://killer.sh/" target="_blank" rel="noopener"
 &gt;Killer Shell&lt;/a&gt;の試験シミュレータでやった内容と似た問題が多く、今回も余裕を持って回答できた(つもり)。&lt;/p&gt;
&lt;p&gt;それぞれの問題の難しさ的には&lt;code&gt;CKA&lt;/code&gt;と同じくらいかそれ以上だと感じたが、&lt;code&gt;CKS&lt;/code&gt;で出る問題の場合は&lt;code&gt;Kubernetes&lt;/code&gt;以外のツールの使い方を問うようなものが多く、&lt;br&gt;
そういった汎用的な手順はだいたい公式ドキュメントに書いてあるのでそれを見れば解けてしまうようなものがいくつかあった。&lt;/p&gt;
&lt;p&gt;ちなみに試験を受けたのが普段ねこにおやつをあげている時間だったので、今回そとちゃんがめちゃくちゃうるさかった。&lt;br&gt;
試験前にその日のぶんのおやつはあげていたのに&amp;hellip;😭&lt;br&gt;
結構ガッツリ鳴いていたが、試験官に怒られることはなかった。&lt;/p&gt;
&lt;h3 id="結果"&gt;結果
&lt;/h3&gt;&lt;p&gt;結果は&amp;hellip;?&lt;/p&gt;
&lt;p&gt;&lt;img alt="やったぜ。" class="gallery-image" data-flex-basis="310px" data-flex-grow="129" height="1916" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-10-10-cks/cks.jpg" srcset="https://blog.uzimihsr.com/post/2021-10-10-cks/cks_hu_86ca02871d183738.jpg 800w, https://blog.uzimihsr.com/post/2021-10-10-cks/cks_hu_a8c724feaa27e37.jpg 1600w, https://blog.uzimihsr.com/post/2021-10-10-cks/cks_hu_f73ff2751e6354f5.jpg 2400w, https://blog.uzimihsr.com/post/2021-10-10-cks/cks.jpg 2478w" width="2478"&gt;&lt;/p&gt;
&lt;p&gt;合格だった。🎉&lt;/p&gt;
&lt;p&gt;&lt;img alt="満点ならず" class="gallery-image" data-flex-basis="1615px" data-flex-grow="673" height="112" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-10-10-cks/score.png" width="754"&gt;&lt;/p&gt;
&lt;p&gt;合格点67点に対して75点とかなりギリギリの結果だった。&lt;br&gt;
今回は配点比率がかなり高めの問題で1つ致命的なミスをした自覚があるので、それが点数に響いたように思う。&lt;br&gt;
&lt;a class="link" href="https://uzimihsr.github.io/post/2020-08-17-ckad/" target="_blank" rel="noopener"
 &gt;CKAD&lt;/a&gt;, &lt;a class="link" href="https://uzimihsr.github.io/post/2021-09-14-cka/" target="_blank" rel="noopener"
 &gt;CKA&lt;/a&gt;はそこそこの点数が取れていたのと比較すると、&lt;br&gt;
やはり実務であまり触れていないモノに対して試験勉強だけでなんとかしようとしたためにまだ本質を理解できていないことがよくわかった。&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;CKSに合格した。&lt;br&gt;
CKAD, CKAと併せてこれでKubernetesの認定資格(2021年10月時点で公開されているもの)をすべて取得できたので、&lt;br&gt;
&lt;strong&gt;†Kubernetes完全に理解した†&lt;/strong&gt; と言って良いのでは？(アカン)&lt;/p&gt;
&lt;p&gt;とはいえCKSだけ点数が低かったあたり、やっぱり実務でさわんないとダメだなという気持ちになった。&lt;br&gt;
今後も慢心せずに頑張りたい。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="おとなしくできなかったそとちゃん" class="gallery-image" data-flex-basis="433px" data-flex-grow="180" height="2040" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-10-10-cks/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2021-10-10-cks/sotochan_hu_120d8946d0595f68.jpg 800w, https://blog.uzimihsr.com/post/2021-10-10-cks/sotochan_hu_ee034925052ebcb0.jpg 1600w, https://blog.uzimihsr.com/post/2021-10-10-cks/sotochan_hu_f25296e71adc2518.jpg 2400w, https://blog.uzimihsr.com/post/2021-10-10-cks/sotochan.jpg 3687w" width="3687"&gt;&lt;/p&gt;</description></item><item><title>9月のそとちゃん(2021)</title><link>https://blog.uzimihsr.com/post/2021-09-30-sotochan/</link><pubDate>Thu, 30 Sep 2021 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2021-09-30-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2021-09-30-sotochan/sotochan.jpg" alt="Featured image of post 9月のそとちゃん(2021)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e8%8d%89" &gt;草&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e7%97%85%e9%99%a2" &gt;病院&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="草"&gt;草
&lt;/h3&gt;&lt;p&gt;約2年ぶりくらいに猫草を買った。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;草 &lt;a href="https://t.co/13K07YSLUy"&gt;pic.twitter.com/13K07YSLUy&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1439926453114523653?ref_src=twsrc%5Etfw"&gt;September 20, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;またたびジャンキーのそとちゃんは猫草も大好きで食いつきがヤバい。&lt;/p&gt;
&lt;p&gt;昔あげたときにごはんそっちのけで食べては吐いてを繰り返し&lt;strong&gt;部屋中GEROまみれにした&lt;/strong&gt;前科があるので、&lt;br&gt;
今回は猫草を部屋の外に出して、特定の時間だけ食べられるようにした。&lt;br&gt;
(部屋の中に置くとずっと食べ続けちゃう😭)&lt;/p&gt;
&lt;div class="video-wrapper"&gt;
 &lt;iframe loading="lazy" 
 src="https://www.youtube.com/embed/OucMh_ZuIOk" 
 allowfullscreen 
 title="YouTube Video"
 &gt;
 &lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;なお&amp;hellip;😭&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;草めっちゃ食べて吐いた &lt;a href="https://t.co/DgfwfqmsNF"&gt;pic.twitter.com/DgfwfqmsNF&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1443127397709062144?ref_src=twsrc%5Etfw"&gt;September 29, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;(なんで吐いた後のねこっていつもどや顔してるの？)&lt;/p&gt;
&lt;h3 id="病院"&gt;病院
&lt;/h3&gt;&lt;p&gt;そとちゃんのワクチンを打ちに病院に行った。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;病院いく &lt;a href="https://t.co/nxuDU9nnZY"&gt;pic.twitter.com/nxuDU9nnZY&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1440473566667894796?ref_src=twsrc%5Etfw"&gt;September 22, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;そとちゃんは病院大好きねこ。&lt;br&gt;
お出かけするとわかったとたんキャリーバッグに自分から入る。&lt;/p&gt;
&lt;p&gt;&lt;img alt="“はやく行くぞ!“って感じ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-09-30-sotochan/sotochan01.jpg" srcset="https://blog.uzimihsr.com/post/2021-09-30-sotochan/sotochan01_hu_fb609d5f20b8c787.jpg 800w, https://blog.uzimihsr.com/post/2021-09-30-sotochan/sotochan01_hu_1d476400d0781985.jpg 1600w, https://blog.uzimihsr.com/post/2021-09-30-sotochan/sotochan01_hu_45fd1a5737fdf84c.jpg 2400w, https://blog.uzimihsr.com/post/2021-09-30-sotochan/sotochan01.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;病院についてからも余裕ぶっこき状態。&lt;br&gt;
待合室で騒ぐ子犬など眼中になく、バッグの中でごろごろして成猫の余裕を見せつける。&lt;br&gt;
(俺は犬が苦手なので怯えまくっていた)&lt;/p&gt;
&lt;p&gt;診察室に入ると今度は診察台の上で寝転んだり先生の机の上を探検してしまう。&lt;br&gt;
あまりの傍若無人ぶりに耐えかねた先生に「気に入ってくれてうれしいけど、ここはおうちじゃないのよ〜🏥」とやんわり(?)怒られる始末。😭&lt;/p&gt;
&lt;p&gt;注射も全然平気で、全く暴れず「にゃん」とも言われなかった。&lt;br&gt;
それよりも体温測定(おしりの*に体温計を入れてはかる)が嫌だったらしい。&lt;br&gt;
体温計を入れるときだけは暴れて「に&amp;quot;ゃ&amp;quot;ん&amp;rdquo;💢」だった。&lt;br&gt;
(ちなみに体温は38.2℃だった。ねこって温かい)&lt;/p&gt;
&lt;p&gt;今回打ったのは3種混合ワクチンというやつ。&lt;br&gt;
そとちゃんはワクチンを最後に打ったのが2018年に保護されたときで、それ以降うちに来てからは打っていなかった。&lt;br&gt;
完全室内飼いかつ1匹だけなので今まで頭から抜けていたんだけど、それでも本当は年に1回の接種がおすすめらしい。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="qme" dir="ltr"&gt;&lt;a href="https://twitter.com/hashtag/Vaccinated?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#Vaccinated&lt;/a&gt; &lt;a href="https://t.co/t0WgPwBO0h"&gt;pic.twitter.com/t0WgPwBO0h&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1440497084663140365?ref_src=twsrc%5Etfw"&gt;September 22, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;ワクチンを打ったついでにいろいろ診てもらった。&lt;/p&gt;
&lt;p&gt;先生によると首にちょっとだけしこりがあるのが気になったらしい。&lt;br&gt;
精密検査とかが必要なレベルではないらしいけど、毎日触ってみてもし肥大するようなら要検査らしいので注意したい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="赤い丸のあたりを触るとたしかに変な感触がある" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-09-30-sotochan/sotochan02.jpg" srcset="https://blog.uzimihsr.com/post/2021-09-30-sotochan/sotochan02_hu_65005544b4ea85e4.jpg 800w, https://blog.uzimihsr.com/post/2021-09-30-sotochan/sotochan02_hu_c75c13432def9a19.jpg 1600w, https://blog.uzimihsr.com/post/2021-09-30-sotochan/sotochan02_hu_386500024cc23f21.jpg 2400w, https://blog.uzimihsr.com/post/2021-09-30-sotochan/sotochan02.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;あと、右の奥歯が歯肉炎になっていて、何かが触れるだけで痛みを感じる状態らしい。😭&lt;br&gt;
歯みがきをやたら嫌がるのはこれが原因だった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="歯肉が赤くなっている" class="gallery-image" data-flex-basis="311px" data-flex-grow="129" height="2376" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-09-30-sotochan/sotochan03.jpg" srcset="https://blog.uzimihsr.com/post/2021-09-30-sotochan/sotochan03_hu_7f1e8af758a2ad7b.jpg 800w, https://blog.uzimihsr.com/post/2021-09-30-sotochan/sotochan03_hu_465e12d654e28c3e.jpg 1600w, https://blog.uzimihsr.com/post/2021-09-30-sotochan/sotochan03_hu_15166412e659e74.jpg 2400w, https://blog.uzimihsr.com/post/2021-09-30-sotochan/sotochan03.jpg 3079w" width="3079"&gt;&lt;/p&gt;
&lt;p&gt;左の奥歯は綺麗なので問題ないけど、歯周病菌がこれ以上増えないよう歯肉に塗る薬を処方してもらうことになった。&lt;br&gt;
&lt;a class="link" href="https://www.ds-vet.jp/product/interberry/index.html" target="_blank" rel="noopener"
 &gt;インターベリーα&lt;/a&gt;&lt;br&gt;
犬用って書いてあるけど猫にも効果があるみたい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="これを塗る" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-09-30-sotochan/sotochan04.jpg" srcset="https://blog.uzimihsr.com/post/2021-09-30-sotochan/sotochan04_hu_72d3cb6096f61b6a.jpg 800w, https://blog.uzimihsr.com/post/2021-09-30-sotochan/sotochan04_hu_14a6827492c902e3.jpg 1600w, https://blog.uzimihsr.com/post/2021-09-30-sotochan/sotochan04_hu_71529954d14c1fbd.jpg 2400w, https://blog.uzimihsr.com/post/2021-09-30-sotochan/sotochan04.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;これを週に2回×5週間、計10回塗る必要がある。&lt;br&gt;
まだ歯肉の痛みがあるそとちゃんはなかなか塗らせてくれないけど、よくなると信じてがんばるしかない。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;歯肉炎の薬塗られるの嫌すぎて立てこもり &lt;a href="https://t.co/Xoq49MCnH6"&gt;pic.twitter.com/Xoq49MCnH6&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1443234461630353418?ref_src=twsrc%5Etfw"&gt;September 29, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;その他はだいたい健康で、体型も普通なので食事は今のままで問題ないとのことだった。&lt;br&gt;
(体重は4.05kgだった)&lt;/p&gt;
&lt;p&gt;ワクチンを打った後は人間と同じく副反応が出ることがあるらしく、&lt;br&gt;
接種後は目を離さないように言われたのでその日はつきっきりで看ていた。&lt;/p&gt;
&lt;p&gt;が、特に何も変化はなくいつもどおりごろごろしていた。&lt;br&gt;
このあたりは俺に似たのかもしれない。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ワクチン接種後2時間くらいは目を離さないよう言われてたけどなんもなかった&lt;br&gt;元気 &lt;a href="https://t.co/ORRLgRletl"&gt;pic.twitter.com/ORRLgRletl&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1440561035228762118?ref_src=twsrc%5Etfw"&gt;September 22, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;(ほとんど遊んでただけだが)そとちゃんは病院をがんばってえらかった。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;病院がんばった &lt;a href="https://t.co/PvxJYKrTGq"&gt;pic.twitter.com/PvxJYKrTGq&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1440493214775971842?ref_src=twsrc%5Etfw"&gt;September 22, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;9月は病院に行ったのがかなり大きなイベントだった。&lt;/p&gt;
&lt;p&gt;最近はそとちゃんがいつも元気にしているのであまり病院に連れて行っていなかったけども、&lt;br&gt;
今回みたいにちょっと怪しい部分(特に歯)を診てもらえたり、何よりそとちゃんが楽しそうなので今後は定期的に連れていくようにしたい。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="塗り薬をやめるよう目で訴えるねこ(かわいそう😭)" class="gallery-image" data-flex-basis="325px" data-flex-grow="135" height="2775" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-09-30-sotochan/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2021-09-30-sotochan/sotochan_hu_3a8d7acb0f048d91.jpg 800w, https://blog.uzimihsr.com/post/2021-09-30-sotochan/sotochan_hu_9496941ad8d49c72.jpg 1600w, https://blog.uzimihsr.com/post/2021-09-30-sotochan/sotochan_hu_5ca58ffae1f0625d.jpg 2400w, https://blog.uzimihsr.com/post/2021-09-30-sotochan/sotochan.jpg 3769w" width="3769"&gt;&lt;/p&gt;</description></item><item><title>kubectl auth can-iでService Accountの権限を確認する</title><link>https://blog.uzimihsr.com/post/2021-09-16-kubectl-auth-can-i-service-account/</link><pubDate>Thu, 16 Sep 2021 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2021-09-16-kubectl-auth-can-i-service-account/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2021-09-16-kubectl-auth-can-i-service-account/sotochan.jpg" alt="Featured image of post kubectl auth can-iでService Accountの権限を確認する" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;kubectl --as&lt;/code&gt;で&lt;code&gt;Service Account&lt;/code&gt;を使いたいときは&lt;code&gt;system:serviceaccount:(NAMESPACE):(SERVICEACCOUNT)&lt;/code&gt;を指定すると良い。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# resourceに対するverbが許可されているかチェック&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl auth can-i &amp;lt;verb&amp;gt; &amp;lt;resource&amp;gt; -n &amp;lt;namespace&amp;gt; --as system:serviceaccount:&amp;lt;namespace&amp;gt;:&amp;lt;serviceAccountName&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ServiceAccountに許可されたresource, verbをリストで表示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl auth can-i --list -n &amp;lt;namespace&amp;gt; --as system:serviceaccount:&amp;lt;namespace&amp;gt;:&amp;lt;serviceAccountName&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/kubernetes-sigs/kind/" target="_blank" rel="noopener"
 &gt;kind&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;v0.11.0 go1.16.4 darwin/amd64&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/kubernetes/kubernetes" target="_blank" rel="noopener"
 &gt;Kubernetes&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;v1.21.1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="もくじ"&gt;もくじ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e9%96%93%e9%81%95%e3%81%88%e3%81%a6%e3%81%84%e3%81%9f" &gt;間違えていた&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e6%ad%a3%e3%81%97%e3%81%84%e3%82%84%e3%82%8a%e6%96%b9" &gt;正しいやり方&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="間違えていた"&gt;間違えていた
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Service Account&lt;/code&gt;にこんな感じの権限を設定していたとする。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# namespace(myhome)のservice account(sotochan)がnamespace: myhomeのpodに対して何でもできる権限を付与&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create namespace myhome
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create serviceaccount sotochan -n myhome
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create role pod-owner --verb&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;*&amp;#34;&lt;/span&gt; --resource&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;pods&amp;#34;&lt;/span&gt; -n myhome
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create rolebinding pod-owner-bind --role&lt;span class="o"&gt;=&lt;/span&gt;pod-owner --serviceaccount&lt;span class="o"&gt;=&lt;/span&gt;myhome:sotochan&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;このとき、&lt;code&gt;kubectl auth can-i&lt;/code&gt;で&lt;code&gt;Service Account&lt;/code&gt;の権限を確認しようとしたらうまくいかなかった。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# どうして...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl auth can-i get pod -n myhome --as sotochan
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;no
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl auth can-i --list -n myhome --as sotochan &lt;span class="p"&gt;|&lt;/span&gt; grep -c pod
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="正しいやり方"&gt;正しいやり方
&lt;/h3&gt;&lt;p&gt;公式ドキュメントをテキトーに探してもよくわからず&amp;quot;わからん！わからん！&amp;ldquo;って騒いでいたら会社の素晴らしい同期が教えてくれた。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;--as&lt;/code&gt;で&lt;code&gt;Service Account&lt;/code&gt;を指定する場合は&lt;code&gt;system:serviceaccount:(NAMESPACE):(SERVICEACCOUNT)&lt;/code&gt;と指定すればいいらしい。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# やったぜ。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl auth can-i get pod -n myhome --as system:serviceaccount:myhome:sotochan
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;yes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl auth can-i --list -n myhome --as system:serviceaccount:myhome:sotochan &lt;span class="p"&gt;|&lt;/span&gt; grep pod
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pods &lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;*&lt;span class="o"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;落ち着いて探したら公式ドキュメントにも一応関連する情報が書いてあった。&lt;br&gt;
&lt;code&gt;Service Account&lt;/code&gt;のユーザー名がそもそも&lt;code&gt;system:serviceaccount:(NAMESPACE):(SERVICEACCOUNT)&lt;/code&gt;として扱われているらしい。&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;知らなかった&amp;hellip;😭&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Service Account&lt;/code&gt;についてちゃんと理解してればこんなところで詰まらないとは思うけど、&lt;br&gt;
公式ドキュメントで&lt;code&gt;kubectl --as&lt;/code&gt;で&lt;code&gt;Service Account&lt;/code&gt;を指定する例が見つけづらかった+自分は30分くらい消耗してしまったので一応メモとして残しておく。&lt;/p&gt;
&lt;p&gt;かなしい&amp;hellip;&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="だらだらするそとちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-09-16-kubectl-auth-can-i-service-account/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2021-09-16-kubectl-auth-can-i-service-account/sotochan_hu_ad57fb07ac807f7a.jpg 800w, https://blog.uzimihsr.com/post/2021-09-16-kubectl-auth-can-i-service-account/sotochan_hu_5720f16e4361eedc.jpg 1600w, https://blog.uzimihsr.com/post/2021-09-16-kubectl-auth-can-i-service-account/sotochan_hu_9741cc6856d30a14.jpg 2400w, https://blog.uzimihsr.com/post/2021-09-16-kubectl-auth-can-i-service-account/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a class="link" href="https://kubernetes.io/docs/reference/access-authn-authz/authentication/#service-account-tokens" target="_blank" rel="noopener"
 &gt;https://kubernetes.io/docs/reference/access-authn-authz/authentication/#service-account-tokens&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>CKAはねこと一緒に受験できる</title><link>https://blog.uzimihsr.com/post/2021-09-14-cka/</link><pubDate>Tue, 14 Sep 2021 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2021-09-14-cka/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2021-09-14-cka/sotochan.jpg" alt="Featured image of post CKAはねこと一緒に受験できる" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;CKAを受験した&lt;/li&gt;
&lt;li&gt;CKA-JPを受ける意味はないと思う&lt;/li&gt;
&lt;li&gt;試験シミュレータの出来が良いのである程度慣れている人なら試験対策はこれだけでよさそう&lt;/li&gt;
&lt;li&gt;ねこちゃんは持ち込み可(重要)&lt;/li&gt;
&lt;li&gt;CKADを先に受けておいてよかった&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="もくじ"&gt;もくじ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e5%8f%97%e9%a8%93%e3%81%be%e3%81%a7" &gt;受験まで&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e8%a9%a6%e9%a8%93%e5%af%be%e7%ad%96" &gt;試験対策&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e8%a9%a6%e9%a8%93%e6%9c%ac%e7%95%aa" &gt;試験本番&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e7%b5%90%e6%9e%9c" &gt;結果&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="受験まで"&gt;受験まで
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2020-08-17-ckad/" target="_blank" rel="noopener"
 &gt;CKAD&lt;/a&gt;に合格してから約1年、Kubernetesにもだいぶ慣れてきたので&lt;a class="link" href="https://training.linuxfoundation.org/certification/certified-kubernetes-administrator-cka/" target="_blank" rel="noopener"
 &gt;CKA&lt;/a&gt;を受験することにした。&lt;/p&gt;
&lt;p&gt;&amp;hellip;本当はだいぶ前に教材(&lt;a class="link" href="https://training.linuxfoundation.org/training/kubernetes-fundamentals/" target="_blank" rel="noopener"
 &gt;LFS258&lt;/a&gt;)付きの受験コースを購入していて、&lt;br&gt;
それを読み終わってから受験しようと思ってだらだらしてたらこの教材が中々のボリュームで時間がかかっていた。&lt;/p&gt;
&lt;p&gt;結局のところ、業務で経験を積んだおかげで教材の内容がほとんどわかる状態だったのと、&lt;br&gt;
いつまで経っても教材が終わらなかったので(主にソシャゲのせい)、&lt;br&gt;
先に試験日を決めてその前の数日で試験対策をして臨むことにした。&lt;/p&gt;
&lt;p&gt;試験の申し込みの流れは&lt;a class="link" href="https://uzimihsr.github.io/post/2020-08-17-ckad/" target="_blank" rel="noopener"
 &gt;CKAD&lt;/a&gt;を受験したときとほとんど同じだったので割愛。&lt;br&gt;
前回は日本語版で受けたが試験官とのやり取りが普通に英語だったりとあまりメリットを感じなかったので、CKA-JPではなく普通のCKAを受けた。&lt;br&gt;
何故かCKAのほうがちょっと安いし(2021年9月時点でCKAが$375, CKA-JPが$410)、やろうと思えば問題文も日本語にできるので普通にCKAを受けたほうが良いと思う。&lt;/p&gt;
&lt;h3 id="試験対策"&gt;試験対策
&lt;/h3&gt;&lt;p&gt;試験対策はほとんど一夜漬け。&lt;br&gt;
&lt;a class="link" href="https://training.linuxfoundation.org/training/kubernetes-fundamentals/" target="_blank" rel="noopener"
 &gt;LFS258&lt;/a&gt;のExerciseも良さそうだったけど、&lt;br&gt;
クラスタ構築のためにパブリッククラウド使うとお片付け忘れてお金無駄にしちゃうマンなので手は動かさずに内容をさらっと読む程度だった。&lt;/p&gt;
&lt;p&gt;前からあったのかもしれないが今はCKAに申し込むと&lt;a class="link" href="https://killer.sh/" target="_blank" rel="noopener"
 &gt;Killer Shell&lt;/a&gt;とかいう試験シミュレータが無料で使えるので(36hx2回まで)、どちらかというとこっちのほうが役に立った。&lt;/p&gt;
&lt;p&gt;&amp;ldquo;本番の試験よりも難しいよ!(意訳)&amp;ldquo;との触れ込み通り、このシミュレータが結構難しい。&lt;br&gt;
練習問題25問+プレビュー問題3問が用意されているのだが、&lt;br&gt;
ドキュメントを見ないと最初は練習問題が半分、プレビュー問題は1つくらいしか解けなかった。&lt;br&gt;
よくわからなかったところを回答と&lt;a class="link" href="https://kubernetes.io/docs/home/" target="_blank" rel="noopener"
 &gt;公式ドキュメント&lt;/a&gt;を見ながら再度解いた。&lt;/p&gt;
&lt;p&gt;特に自分はクラスタ構築を&lt;a class="link" href="https://github.com/kelseyhightower/kubernetes-the-hard-way" target="_blank" rel="noopener"
 &gt;Kubernetes The Hard Way&lt;/a&gt;でしかやったことがなかった(普段はマネージドk8sを使っている)ので、&lt;br&gt;
主に&lt;a class="link" href="https://kubernetes.io/docs/reference/setup-tools/kubeadm/" target="_blank" rel="noopener"
 &gt;kubeadm&lt;/a&gt;のコマンドまわりがわからず急いでドキュメントを読み込んだ。&lt;/p&gt;
&lt;p&gt;公式ドキュメントは本番試験中も参照可能なので、難しいと思った内容に関連するドキュメントはブックマークしておいた。&lt;br&gt;
PersistentVolume(Claim), NetworkPolicyあたりは&lt;code&gt;kubectl create --dry-run -o yaml&lt;/code&gt;できないのでこれらのYAML例があるページも併せてブックマークした。&lt;/p&gt;
&lt;h3 id="試験本番"&gt;試験本番
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2020-08-17-ckad/" target="_blank" rel="noopener"
 &gt;CKAD&lt;/a&gt;と同様、自宅で試験を受けた。&lt;/p&gt;
&lt;p&gt;試験前の指示も前回と全く同じ(カメラを持って部屋を一周しろ、机を片付けろ、などなど)だったので割愛。&lt;/p&gt;
&lt;p&gt;前回そとちゃんを廊下で待たせたら試験中に爆鳴きして大変だったので、そとちゃんをカメラに映しながら試験官に&lt;br&gt;
&lt;strong&gt;&amp;ldquo;ウチにはねこちゃんいるんだけど、この子部屋の外に出さなきゃダメ?&amp;rdquo;&lt;/strong&gt;&lt;br&gt;
と確認したところ&lt;br&gt;
&lt;strong&gt;&amp;ldquo;おとなしくできるなら彼女は部屋に居てもいいよ!&amp;rdquo;&lt;/strong&gt;&lt;br&gt;
とのことだった。&lt;/p&gt;
&lt;p&gt;見た目だけでなんでそとちゃんが女の子(she)だってわかったのかは謎だけど(英語だと猫の代名詞でsheを使うことが多い?)、&lt;br&gt;
OKをもらえたのでよかった。&lt;/p&gt;
&lt;p&gt;また、試験中に開けるタブは2つまで(試験用+ドキュメント用)とされているが、1タブずつで2ウィンドウ開いても良いとのことだった。&lt;br&gt;
自分の場合はディスプレイが横長なのでこれがかなり有利に働いたと思う。&lt;/p&gt;
&lt;p&gt;&lt;img alt="左側の画面はCKAではなくKatacodaのもの" class="gallery-image" data-flex-basis="573px" data-flex-grow="238" height="1440" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-09-14-cka/sc01.png" srcset="https://blog.uzimihsr.com/post/2021-09-14-cka/sc01_hu_49e3271afd81c4f.png 800w, https://blog.uzimihsr.com/post/2021-09-14-cka/sc01_hu_164e70771fcab7aa.png 1600w, https://blog.uzimihsr.com/post/2021-09-14-cka/sc01_hu_c9d2770074f4e10a.png 2400w, https://blog.uzimihsr.com/post/2021-09-14-cka/sc01.png 3440w" width="3440"&gt;&lt;/p&gt;
&lt;p&gt;試験時間は2時間で問題数は17問くらい。&lt;br&gt;
具体的な内容は避けるが問題の傾向は試験シミュレータとかなり似ていて、&lt;br&gt;
たしかに本番のほうが少し簡単なものが多かった。&lt;br&gt;
また、シミュレータと違って「n問目が正解できてないとm問目で詰む」というケースがなかったので、難しい問題は飛ばして後回しにできて良かった。&lt;br&gt;
CKAD(2時間で19問)のときは少し慎重になりすぎて時間が足りなかったので、&lt;br&gt;
今回はスピード重視でやったところ30分くらい時間が余って見直しする余裕もあった。&lt;/p&gt;
&lt;p&gt;ちなみにそとちゃんは試験開始後に1回鳴いただけで、その後はずっとおとなしく寝てくれていた。えらい!&lt;/p&gt;
&lt;p&gt;&lt;img alt="どや顔" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-09-14-cka/sotochan01.jpg" srcset="https://blog.uzimihsr.com/post/2021-09-14-cka/sotochan01_hu_cbcfaefc2cb69531.jpg 800w, https://blog.uzimihsr.com/post/2021-09-14-cka/sotochan01_hu_6d1ab4351f0c68d9.jpg 1600w, https://blog.uzimihsr.com/post/2021-09-14-cka/sotochan01_hu_36e632e7fce54d32.jpg 2400w, https://blog.uzimihsr.com/post/2021-09-14-cka/sotochan01.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;h3 id="結果"&gt;結果
&lt;/h3&gt;&lt;p&gt;結果は&amp;hellip;?&lt;/p&gt;
&lt;p&gt;&lt;img alt="やったぜ。" class="gallery-image" data-flex-basis="310px" data-flex-grow="129" height="1916" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-09-14-cka/cka.jpg" srcset="https://blog.uzimihsr.com/post/2021-09-14-cka/cka_hu_e90b4f3fddf4ec9f.jpg 800w, https://blog.uzimihsr.com/post/2021-09-14-cka/cka_hu_1f75201ab8eb13e3.jpg 1600w, https://blog.uzimihsr.com/post/2021-09-14-cka/cka_hu_3aad0a1119c8325a.jpg 2400w, https://blog.uzimihsr.com/post/2021-09-14-cka/cka.jpg 2475w" width="2475"&gt;&lt;/p&gt;
&lt;p&gt;合格だった。🎉&lt;/p&gt;
&lt;p&gt;&lt;img alt="満点ならず" class="gallery-image" data-flex-basis="1568px" data-flex-grow="653" height="114" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-09-14-cka/score.png" width="745"&gt;&lt;/p&gt;
&lt;p&gt;合格点66点に対して得点はまたも91点だった。&lt;br&gt;
今回は時間にも余裕があって、完答したつもりだったのですこしくやしい。&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;CKAに合格した。&lt;br&gt;
正直これを獲っただけで実用レベルのクラスタ管理者になれるかというとすこし疑問だけど、&lt;br&gt;
少なくともKubernetesの基本を押さえたことの証明にはなると思う。&lt;/p&gt;
&lt;p&gt;個人的にはCKADと比べると問題の内容はすこし難しいものの、制限時間のあるテストとして考えるとCKAのほうが問題数も少なくて簡単だった。&lt;br&gt;
(CKADを受けたおかげで&lt;code&gt;kubectl&lt;/code&gt;の操作がやたら早くなっていたり、もちろん自分の経験値が増えていることもあるが&amp;hellip;)&lt;/p&gt;
&lt;p&gt;CKAD、CKAと来てしまったので次は&lt;a class="link" href="https://training.linuxfoundation.org/certification/certified-kubernetes-security-specialist/" target="_blank" rel="noopener"
 &gt;CKS&lt;/a&gt;を受ける予定(いつ?)。&lt;br&gt;
噂によるとかなり難しいらしいので頑張りたい(ほんまか?)。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="おとなしくできてえらかったそとちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-09-14-cka/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2021-09-14-cka/sotochan_hu_b806804be0163cb0.jpg 800w, https://blog.uzimihsr.com/post/2021-09-14-cka/sotochan_hu_a52b8c5b105e804d.jpg 1600w, https://blog.uzimihsr.com/post/2021-09-14-cka/sotochan_hu_bec925ad46f43482.jpg 2400w, https://blog.uzimihsr.com/post/2021-09-14-cka/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>8月のそとちゃん(2021)</title><link>https://blog.uzimihsr.com/post/2021-09-09-sotochan/</link><pubDate>Thu, 09 Sep 2021 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2021-09-09-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan.jpg" alt="Featured image of post 8月のそとちゃん(2021)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%8a%e3%81%a7%e3%81%8b%e3%81%91" &gt;おでかけ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%ad%e3%81%9a%e3%81%bf%e5%a4%a7%e6%8d%9c%e7%b4%a2" &gt;ねずみ大捜索&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%9c%e3%83%ad%e3%83%9c%e3%83%ad%e3%83%80%e3%83%b3%e3%83%9c%e3%83%bc%e3%83%ab" &gt;ボロボロダンボール&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="おでかけ"&gt;おでかけ
&lt;/h3&gt;&lt;p&gt;そとちゃんがいつもより窓際で鳴いたりして外に出たがってるように見えたので、&lt;br&gt;
ハーネス+抱っこの状態で何回か家の外に出してみた。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;セミを見てきた &lt;a href="https://t.co/Z5sqSvsCqd"&gt;pic.twitter.com/Z5sqSvsCqd&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1430677576138170368?ref_src=twsrc%5Etfw"&gt;August 25, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;元々野良猫だったそとちゃんだけど外に出ても意外とおとなしくできる。えらい。&lt;/p&gt;
&lt;p&gt;というよりはハーネスが嫌いすぎて動く気がないと言ったほうが正しい。&lt;/p&gt;
&lt;p&gt;つけられた時点で石のように動かなくなる(抱っこしやすくて助かる)。&lt;/p&gt;
&lt;p&gt;&lt;img alt="赤いハーネスはめちゃめちゃ嫌い" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan02.jpg" srcset="https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan02_hu_7e59680e0311826c.jpg 800w, https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan02_hu_578d769e909b1bb7.jpg 1600w, https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan02_hu_c2cfa6bcf31872a2.jpg 2400w, https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan02.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;外に出てもあんまり遠くは見ずに、近くに落ちてる死にかけの虫をずっと睨んでいる。&lt;/p&gt;
&lt;p&gt;よくわからないけどこのときはしっぽをぶんぶん振るのでそとちゃん的にはめっちゃ楽しいらしい。&lt;br&gt;
(たまに反撃されてびっくりする)&lt;/p&gt;
&lt;p&gt;一応完全室内飼いなのでそとちゃんだけで外に出すことは絶対にしないけど、&lt;br&gt;
ずっと室内だと退屈そうなのでたまにはこうやってお出かけしてもいいと思った。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ドアを開けろと言っている" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan01.jpg" srcset="https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan01_hu_534d043366ed0bfb.jpg 800w, https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan01_hu_4d317e1e0f23c19b.jpg 1600w, https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan01_hu_fda5b0b677faf495.jpg 2400w, https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan01.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;h3 id="ねずみ大捜索"&gt;ねずみ大捜索
&lt;/h3&gt;&lt;p&gt;実は6月くらいからねずみのおもちゃが全部行方不明になっていた。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;1ヶ月くらい失くしてたねずみが出てきた &lt;a href="https://t.co/cGhpu2NHxS"&gt;pic.twitter.com/cGhpu2NHxS&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1429225338983251969?ref_src=twsrc%5Etfw"&gt;August 21, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;そとちゃんは遊んでるときにおもちゃが取れなくなると一応鳴いて教えてくれるんだけど、&lt;br&gt;
どこで失くしたかまでは教えてくれないのでその場で見つからなかったときはそのまま迷宮入りしてしまう。&lt;/p&gt;
&lt;p&gt;そんな感じでどんどんねずみが消えていって、ついに全部なくなっちゃったので気合をいれて大捜索。&lt;/p&gt;
&lt;p&gt;狭い部屋の中なのに1時間くらいかかってなんとか全部見つけられた。&lt;/p&gt;
&lt;p&gt;&lt;img alt="5個そろった" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan03.jpg" srcset="https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan03_hu_af41435c071efffb.jpg 800w, https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan03_hu_99cc5427c32a7d58.jpg 1600w, https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan03_hu_fa971c5dc00e02b9.jpg 2400w, https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan03.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;猫トイレの裏、洗面台の下、ベッドフレームとマットレスの隙間、冷蔵庫の裏側&amp;hellip;&lt;br&gt;
ねこの手じゃ届かないのにどうやって入れた？ってところにも隠れててびっくりした。&lt;/p&gt;
&lt;p&gt;次は失くさずに上手に遊んでほしい。&lt;br&gt;
(この後すぐ白いのが1つ消えた😭)&lt;/p&gt;
&lt;h3 id="ボロボロダンボール"&gt;ボロボロダンボール
&lt;/h3&gt;&lt;p&gt;そとちゃんお気に入りのダンボールトンネル(元は自動給餌器の空き箱)。&lt;/p&gt;
&lt;p&gt;箱より袋派のそとちゃんだけどこれはほぼ毎日入る。&lt;br&gt;
(この中から飛び出して俺をビビらせるのがすき)&lt;/p&gt;
&lt;p&gt;&lt;img alt="めっちゃ好き" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan04.jpg" srcset="https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan04_hu_363fc3642fc3b8a0.jpg 800w, https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan04_hu_bd3014feb858af14.jpg 1600w, https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan04_hu_1f6c4d992a63b41b.jpg 2400w, https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan04.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;そんなダンボールトンネルも2年使っているのでもうボロボロ。&lt;/p&gt;
&lt;p&gt;そとちゃんが入ったときに興奮して内側をバリバリしちゃうので、ついに大きな穴が空いてしまった。&lt;/p&gt;
&lt;p&gt;&lt;img alt="おしりはみ出てる" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan05.jpg" srcset="https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan05_hu_f1dbbc62c3741c7.jpg 800w, https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan05_hu_67156eda48f36dc9.jpg 1600w, https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan05_hu_56b4e99d8d811f4c.jpg 2400w, https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan05.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;バリバリするたびにダンボールのカスが出るし、流石にもう捨てたいのだけど、なかなか許可が降りない&amp;hellip;😭&lt;/p&gt;
&lt;p&gt;&lt;img alt="絶対出ない" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan06.jpg" srcset="https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan06_hu_b97f0ea6f3d41a19.jpg 800w, https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan06_hu_7becb11f23b429cc.jpg 1600w, https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan06_hu_c5c76a9542663570.jpg 2400w, https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan06.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;8月のそとちゃんは元気いっぱいでよく遊んでいた。&lt;/p&gt;
&lt;p&gt;遊ぶ時間は毎日確保してるので運動不足ではないとおもうけど、この元気はどこからくるのだろうか&amp;hellip;&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="本当はハーネス無しで外に出たいそとちゃん(ダメです)" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan_hu_ebf709953ddf1388.jpg 800w, https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan_hu_49fec8af9f26bb72.jpg 1600w, https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan_hu_feffdfc69c9e69e1.jpg 2400w, https://blog.uzimihsr.com/post/2021-09-09-sotochan/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>mtailでnginxのaccess.logをメトリクス化する</title><link>https://blog.uzimihsr.com/post/2021-08-19-mtail-nginx-access-log-regexp/</link><pubDate>Thu, 19 Aug 2021 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2021-08-19-mtail-nginx-access-log-regexp/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2021-08-19-mtail-nginx-access-log-regexp/sotochan.jpg" alt="Featured image of post mtailでnginxのaccess.logをメトリクス化する" /&gt;&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;ログファイルをtailしてメトリクス化する&lt;code&gt;mtail&lt;/code&gt;を使って&lt;code&gt;nginx&lt;/code&gt;のアクセスログをメトリクス化した
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/uzimihsr/mtail-nginx" target="_blank" rel="noopener"
 &gt;https://github.com/uzimihsr/mtail-nginx&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Big Sur 11.2.3&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/editions/community/docker-ce-desktop-mac" target="_blank" rel="noopener"
 &gt;Docker Desktop for Mac&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Version 3.5.2&lt;/li&gt;
&lt;li&gt;Docker Engine Version 20.10.7&lt;/li&gt;
&lt;li&gt;Docker Compose Version 1.29.2&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/google/mtail" target="_blank" rel="noopener"
 &gt;mtail&lt;/a&gt; version 3.0.0-rc47&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/nginx/nginx" target="_blank" rel="noopener"
 &gt;nginx&lt;/a&gt; 1.21.1&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/prometheus/prometheus" target="_blank" rel="noopener"
 &gt;Prometheus&lt;/a&gt; v2.29.1&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#mtail%e3%81%ae%e3%83%93%e3%83%ab%e3%83%89" &gt;mtailのビルド&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#mtail-program%e3%81%ae%e4%bd%9c%e6%88%90" &gt;mtail programの作成&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e5%8b%95%e4%bd%9c%e7%a2%ba%e8%aa%8d" &gt;動作確認&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mtailのビルド"&gt;mtailのビルド
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;mtail&lt;/code&gt;はアプリケーションのログをメトリクス化するツール。&lt;br&gt;
自身でメトリクスを公開できないアプリの監視なんかに使えそう。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;nginx&lt;/code&gt;のメトリクスを扱うexporterとしては&lt;a class="link" href="https://github.com/nginxinc/nginx-prometheus-exporter" target="_blank" rel="noopener"
 &gt;nginx-prometheus-exporter&lt;/a&gt;があるんだけど、&lt;br&gt;
&lt;a class="link" href="https://nginx.org/en/docs/http/ngx_http_stub_status_module.html#stub_status" target="_blank" rel="noopener"
 &gt;stub_status&lt;/a&gt;の設定が必要だったりOSS版&lt;code&gt;nginx&lt;/code&gt;だとメトリクスの種類が少なかったりするので今回は&lt;code&gt;mtail&lt;/code&gt;を使ってみる。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;mtail&lt;/code&gt;のビルド方法はいくつかある&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;が、今回はかんたんに試したいので&lt;code&gt;GitHub Releases&lt;/code&gt;で配布されているバイナリ&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;を仕込んだ&lt;code&gt;Docker&lt;/code&gt;イメージを作成する。&lt;br&gt;
(自前でビルドしようとしたら自分の環境ではテストのエラーが発生してうまくできなかった&amp;hellip;)&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/5303ae045aa6f95e2ab60898f3d86361.js"&gt;&lt;/script&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Docker imageのビルド&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls Dockerfile
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Dockerfile
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image build -t mtail .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run -it --rm mtail --version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mtail version 3.0.0-rc47 git revision 5e0099f843e4e4f2b7189c21019de18eb49181bf go version go1.16.5 go arch amd64 go os linux&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="mtail-programの作成"&gt;mtail programの作成
&lt;/h3&gt;&lt;p&gt;続いてログをメトリクスに変換するための&lt;code&gt;mtail program&lt;/code&gt;と呼ばれるスクリプトを作成する。&lt;br&gt;
&lt;code&gt;mtail program&lt;/code&gt;は&lt;code&gt;pattern&lt;/code&gt;(ログの各行に対する条件)と&lt;code&gt;action&lt;/code&gt;(patternを満たしたログに関する処理)から構成されている。&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;br&gt;
(&lt;code&gt;awk&lt;/code&gt;にちょっと似ている)&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pattern&lt;/code&gt;は主に正規表現で記述するので、まずはメトリクス化したい&lt;code&gt;nginx&lt;/code&gt;のアクセスログのフォーマットを確認する。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# nginxのログフォーマットを確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run -it --rm nginx:1.21.1 cat /etc/nginx/nginx.conf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...&lt;span class="o"&gt;(&lt;/span&gt;省略&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;http &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; log_format main &lt;span class="s1"&gt;&amp;#39;$remote_addr - $remote_user [$time_local] &amp;#34;$request&amp;#34; &amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;$status $body_bytes_sent &amp;#34;$http_referer&amp;#34; &amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#34;$http_user_agent&amp;#34; &amp;#34;$http_x_forwarded_for&amp;#34;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;このときのログの具体例は次のとおり。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;172.20.0.1 - - [18/Aug/2021:14:04:48 +0000] &amp;#34;GET / HTTP/1.1&amp;#34; 200 612 &amp;#34;-&amp;#34; &amp;#34;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36&amp;#34; &amp;#34;-&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;このフォーマットのログに対して正規表現で名前付きキャプチャグループを設定すると次のような感じになる。&lt;br&gt;
&lt;code&gt;$request&lt;/code&gt;はメソッド、URI、バージョンに分割するようにした。　　&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-regex" data-lang="regex"&gt;^(?P&amp;lt;remote_addr&amp;gt;\S+) - (?P&amp;lt;remote_user&amp;gt;.+) \[(?P&amp;lt;time_local&amp;gt;.+)\] &amp;#34;(?P&amp;lt;request_method&amp;gt;\S+) (?P&amp;lt;request_uri&amp;gt;\S+) (?P&amp;lt;request_version&amp;gt;\S+)&amp;#34; (?P&amp;lt;status&amp;gt;\S+) (?P&amp;lt;body_bytes_sent&amp;gt;\S+) &amp;#34;(?P&amp;lt;http_referer&amp;gt;\S+)&amp;#34; &amp;#34;(?P&amp;lt;http_user_agent&amp;gt;.+)&amp;#34; &amp;#34;(?P&amp;lt;http_x_forwarded_for&amp;gt;\S+)&amp;#34;$
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;この正規表現を&lt;code&gt;pattern&lt;/code&gt;とした&lt;code&gt;mtail program&lt;/code&gt;を次のように作成した。&lt;br&gt;
&lt;code&gt;nginx_request&lt;/code&gt;はリクエスト数を数えるカウンタで、ラベルとしてリクエストメソッドとステータスコードを付与するようにした。&lt;br&gt;
&lt;code&gt;nginx_request_pattern_matching_failed&lt;/code&gt;は&lt;code&gt;pattern&lt;/code&gt;にマッチしなかったログの行数を数えるカウンタとして使用する。&lt;br&gt;
また、どちらもログファイル名としてsourceラベルを付与するようにした。&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/43e3d2be955c413ad9621a10007d4283.js"&gt;&lt;/script&gt;
&lt;h3 id="動作確認"&gt;動作確認
&lt;/h3&gt;&lt;p&gt;これで&lt;code&gt;mtail&lt;/code&gt;を使う準備ができたので&lt;code&gt;Docker Compose&lt;/code&gt;で&lt;code&gt;nginx&lt;/code&gt;や&lt;code&gt;Prometheus&lt;/code&gt;と一緒に起動してみる。&lt;br&gt;
&lt;code&gt;mtail&lt;/code&gt;の実行時引数などは公式ドキュメント&lt;sup id="fnref:4"&gt;&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref"&gt;4&lt;/a&gt;&lt;/sup&gt;を参考にした。　　&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/94361b604882d47f1d7d23e8d04d47dc.js"&gt;&lt;/script&gt;
&lt;p&gt;&lt;code&gt;Docker&lt;/code&gt;版の&lt;code&gt;nginx&lt;/code&gt;はアクセスログ(&lt;code&gt;/var/log/nginx/access.log&lt;/code&gt;)とエラーログ(&lt;code&gt;/var/log/nginx/error.log&lt;/code&gt;)がそれぞれ標準出力(&lt;code&gt;/dev/stdout&lt;/code&gt;)と標準エラー出力(&lt;code&gt;/dev/stderr&lt;/code&gt;)へのシンボリックリンクになっていて、&lt;br&gt;
ファイルとして参照するのが難しかったのでログの出力先を変更するようにした。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ログファイルが標準出力へのシンボリックリンクになっている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run -it --rm nginx:1.21.1 ls -l /var/log/nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;total &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;lrwxrwxrwx &lt;span class="m"&gt;1&lt;/span&gt; root root &lt;span class="m"&gt;11&lt;/span&gt; Aug &lt;span class="m"&gt;17&lt;/span&gt; 11:46 access.log -&amp;gt; /dev/stdout
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;lrwxrwxrwx &lt;span class="m"&gt;1&lt;/span&gt; root root &lt;span class="m"&gt;11&lt;/span&gt; Aug &lt;span class="m"&gt;17&lt;/span&gt; 11:46 error.log -&amp;gt; /dev/stderr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;script src="https://gist.github.com/uzimihsr/f8e818ce19cd58ea3510f96d37a8bed7.js"&gt;&lt;/script&gt;
&lt;script src="https://gist.github.com/uzimihsr/86c39e9998912169da3991e074cd3f87.js"&gt;&lt;/script&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 起動前のディレクトリの状態&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ tree
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── Dockerfile
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── README.md
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── docker-compose.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── mtail
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   └── nginx.mtail
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   └── nginx.conf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── prometheus
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └── prometheus.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker compose up -d --force-recreate
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker compose ps
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME COMMAND SERVICE STATUS PORTS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mtail-nginx_mtail_1 &lt;span class="s2"&gt;&amp;#34;./mtail --progs=/et…&amp;#34;&lt;/span&gt; mtail running 0.0.0.0:3903-&amp;gt;3903/tcp, :::3903-&amp;gt;3903/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mtail-nginx_nginx_1 &lt;span class="s2"&gt;&amp;#34;/docker-entrypoint.…&amp;#34;&lt;/span&gt; nginx running 0.0.0.0:80-&amp;gt;80/tcp, :::80-&amp;gt;80/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mtail-nginx_prometheus_1 &lt;span class="s2"&gt;&amp;#34;/bin/prometheus --c…&amp;#34;&lt;/span&gt; prometheus running 0.0.0.0:9090-&amp;gt;9090/tcp, :::9090-&amp;gt;9090/tcp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;この状態で&lt;a class="link" href="http://localhost:3903/" target="_blank" rel="noopener"
 &gt;http://localhost:3903/&lt;/a&gt;を開くと&lt;code&gt;mtail&lt;/code&gt;が正常に動作していることを確認できる。&lt;/p&gt;
&lt;p&gt;&lt;img alt="mtail" class="gallery-image" data-flex-basis="410px" data-flex-grow="171" height="665" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-08-19-mtail-nginx-access-log-regexp/sc01.png" srcset="https://blog.uzimihsr.com/post/2021-08-19-mtail-nginx-access-log-regexp/sc01_hu_3905fbfd493db5ce.png 800w, https://blog.uzimihsr.com/post/2021-08-19-mtail-nginx-access-log-regexp/sc01.png 1138w" width="1138"&gt;&lt;/p&gt;
&lt;p&gt;次に&lt;code&gt;nginx&lt;/code&gt;&lt;a class="link" href="http://localhost/" target="_blank" rel="noopener"
 &gt;http://localhost/&lt;/a&gt;に対していくつかリクエストを送ってみる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# nginxにホストOSからリクエストを送る&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -X GET &lt;span class="s2"&gt;&amp;#34;http://localhost/index.html&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -X GET &lt;span class="s2"&gt;&amp;#34;http://localhost/index.html&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -X GET &lt;span class="s2"&gt;&amp;#34;http://localhost/hogehoge.html&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -X POST &lt;span class="s2"&gt;&amp;#34;http://localhost/index.html&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -X PUT &lt;span class="s2"&gt;&amp;#34;http://localhost/index.html&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -X DELETE &lt;span class="s2"&gt;&amp;#34;http://localhost/index.html&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ログファイルの内容&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker compose &lt;span class="nb"&gt;exec&lt;/span&gt; nginx cat /var/log/mtail-nginx/access.log
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;172.22.0.1 - - &lt;span class="o"&gt;[&lt;/span&gt;19/Aug/2021:11:09:05 +0000&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;GET /index.html HTTP/1.1&amp;#34;&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt; &lt;span class="m"&gt;612&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;-&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;curl/7.64.1&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;-&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;172.22.0.1 - - &lt;span class="o"&gt;[&lt;/span&gt;19/Aug/2021:11:09:06 +0000&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;GET /index.html HTTP/1.1&amp;#34;&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt; &lt;span class="m"&gt;612&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;-&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;curl/7.64.1&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;-&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;172.22.0.1 - - &lt;span class="o"&gt;[&lt;/span&gt;19/Aug/2021:11:09:12 +0000&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;GET /hogehoge.html HTTP/1.1&amp;#34;&lt;/span&gt; &lt;span class="m"&gt;404&lt;/span&gt; &lt;span class="m"&gt;153&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;-&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;curl/7.64.1&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;-&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;172.22.0.1 - - &lt;span class="o"&gt;[&lt;/span&gt;19/Aug/2021:11:09:18 +0000&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;POST /index.html HTTP/1.1&amp;#34;&lt;/span&gt; &lt;span class="m"&gt;405&lt;/span&gt; &lt;span class="m"&gt;157&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;-&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;curl/7.64.1&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;-&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;172.22.0.1 - - &lt;span class="o"&gt;[&lt;/span&gt;19/Aug/2021:11:09:22 +0000&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;PUT /index.html HTTP/1.1&amp;#34;&lt;/span&gt; &lt;span class="m"&gt;405&lt;/span&gt; &lt;span class="m"&gt;157&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;-&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;curl/7.64.1&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;-&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;172.22.0.1 - - &lt;span class="o"&gt;[&lt;/span&gt;19/Aug/2021:11:09:27 +0000&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;DELETE /index.html HTTP/1.1&amp;#34;&lt;/span&gt; &lt;span class="m"&gt;405&lt;/span&gt; &lt;span class="m"&gt;157&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;-&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;curl/7.64.1&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;-&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker compose &lt;span class="nb"&gt;exec&lt;/span&gt; nginx cat /var/log/mtail-nginx/error.log
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2021/08/19 11:09:12 &lt;span class="o"&gt;[&lt;/span&gt;error&lt;span class="o"&gt;]&lt;/span&gt; 31#31: *3 open&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;/usr/share/nginx/html/hogehoge.html&amp;#34;&lt;/span&gt; failed &lt;span class="o"&gt;(&lt;/span&gt;2: No such file or directory&lt;span class="o"&gt;)&lt;/span&gt;, client: 172.22.0.1, server: localhost, request: &lt;span class="s2"&gt;&amp;#34;GET /hogehoge.html HTTP/1.1&amp;#34;&lt;/span&gt;, host: &lt;span class="s2"&gt;&amp;#34;localhost&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;mtail&lt;/code&gt;のメトリクスはPrometheusのフォーマットに対応していて、&lt;br&gt;
&lt;a class="link" href="http://localhost:3903/metrics" target="_blank" rel="noopener"
 &gt;http://localhost:3903/metrics&lt;/a&gt;で内容を確認できる。&lt;/p&gt;
&lt;p&gt;&lt;img alt="mtail" class="gallery-image" data-flex-basis="918px" data-flex-grow="382" height="204" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-08-19-mtail-nginx-access-log-regexp/sc02.png" width="781"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;nginx.mtail&lt;/code&gt;で定義したとおり、&lt;br&gt;
アクセスログの内容は正規表現の&lt;code&gt;pattern&lt;/code&gt;にマッチするのでメソッドとステータスがラベル化されて&lt;code&gt;nginx_request&lt;/code&gt;としてカウントされていて、&lt;br&gt;
エラーログの内容は&lt;code&gt;pattern&lt;/code&gt;にマッチしないので&lt;code&gt;nginx_request_pattern_matching_failed&lt;/code&gt;としてカウントされている。&lt;/p&gt;
&lt;p&gt;最後に一応&lt;code&gt;Prometheus&lt;/code&gt;&lt;a class="link" href="http://localhost:9090/graph" target="_blank" rel="noopener"
 &gt;http://localhost:9090/graph&lt;/a&gt;でもメトリクスを確認する。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ログのメトリクスが時系列データとして扱える" class="gallery-image" data-flex-basis="365px" data-flex-grow="152" height="938" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-08-19-mtail-nginx-access-log-regexp/sc03.png" srcset="https://blog.uzimihsr.com/post/2021-08-19-mtail-nginx-access-log-regexp/sc03_hu_2b54a6475da5b5ca.png 800w, https://blog.uzimihsr.com/post/2021-08-19-mtail-nginx-access-log-regexp/sc03.png 1430w" width="1430"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;mtail&lt;/code&gt;のメトリクスは通常のexporterと同様に扱えるので、時系列データとしてグラフ化もできている。&lt;/p&gt;
&lt;p&gt;やったぜ。🎉&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;mtail&lt;/code&gt;で&lt;code&gt;nginx&lt;/code&gt;のログファイルをメトリクス化できた。&lt;br&gt;
&lt;code&gt;nginx&lt;/code&gt;に限らず、ログのフォーマットが決まっていてそれにマッチする正規表現が書ければ何でもメトリクス化できるのでかなり便利だと思った。　　&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="しっぽがながいねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-08-19-mtail-nginx-access-log-regexp/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2021-08-19-mtail-nginx-access-log-regexp/sotochan_hu_86e62a06eed3056f.jpg 800w, https://blog.uzimihsr.com/post/2021-08-19-mtail-nginx-access-log-regexp/sotochan_hu_2cda5776277a0c83.jpg 1600w, https://blog.uzimihsr.com/post/2021-08-19-mtail-nginx-access-log-regexp/sotochan_hu_ef8d0346808867a4.jpg 2400w, https://blog.uzimihsr.com/post/2021-08-19-mtail-nginx-access-log-regexp/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/google/mtail/blob/main/docs/Building.md" target="_blank" rel="noopener"
 &gt;https://github.com/google/mtail/blob/main/docs/Building.md&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/google/mtail/releases" target="_blank" rel="noopener"
 &gt;https://github.com/google/mtail/releases&lt;/a&gt;&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/google/mtail/blob/main/docs/Programming-Guide.md" target="_blank" rel="noopener"
 &gt;https://github.com/google/mtail/blob/main/docs/Programming-Guide.md&lt;/a&gt;&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:4"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/google/mtail/blob/main/docs/Deploying.md" target="_blank" rel="noopener"
 &gt;https://github.com/google/mtail/blob/main/docs/Deploying.md&lt;/a&gt;&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>COVID-19ワクチン(モデルナ筋注)を打った</title><link>https://blog.uzimihsr.com/post/2021-08-11-covid-19-vaccinated/</link><pubDate>Wed, 11 Aug 2021 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2021-08-11-covid-19-vaccinated/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2021-08-11-covid-19-vaccinated/sotochan.jpg" alt="Featured image of post COVID-19ワクチン(モデルナ筋注)を打った" /&gt;&lt;h2 id="はじめに予防線"&gt;はじめに(予防線)
&lt;/h2&gt;&lt;p&gt;これはCOVID-19ワクチンモデルナ筋注を打った&lt;strong&gt;私個人の感想&lt;/strong&gt;を書きなぐっただけの自己満日記です。&lt;br&gt;
COVID-19やそれに関連する情報に対する個人の思想等は極力切り離して客観的に書いたつもりです。&lt;br&gt;
特定の人物または団体を攻撃したり擁護するような意図はなく、&lt;br&gt;
読者に同ワクチンの接種を強く勧めたり逆に止めさせようということもありません。&lt;br&gt;
仮にそう読めたとしてもそれは筆者の未熟な文章力によるものなのでお察しください。&lt;/p&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;COVID-19ワクチンモデルナ筋注を打った&lt;/li&gt;
&lt;li&gt;筋肉注射は痛くなかったり痛かったりした
&lt;ul&gt;
&lt;li&gt;1回目と2回目で別の腕に打っても問題ないらしい&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;副反応は軽めだった
&lt;ul&gt;
&lt;li&gt;1回目はほぼ何もなし&lt;/li&gt;
&lt;li&gt;2回目は体調を崩したが接種翌々日以降は何もなし&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ある程度体調を崩すのに備えておいてよかった&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="もくじ"&gt;もくじ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e6%89%93%e3%81%a3%e3%81%9f%e3%83%af%e3%82%af%e3%83%81%e3%83%b3" &gt;打ったワクチン&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%af%e3%82%af%e3%83%81%e3%83%b3%e3%82%92%e6%89%93%e3%81%a3%e3%81%9f%e4%ba%ba%e3%81%bc%e3%81%8f" &gt;ワクチンを打った人(ぼく)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e6%8e%a5%e7%a8%ae1%e5%9b%9e%e7%9b%ae" &gt;接種(1回目)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e5%89%af%e5%8f%8d%e5%bf%9c1%e5%9b%9e%e7%9b%ae" &gt;副反応?(1回目)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e6%8e%a5%e7%a8%ae2%e5%9b%9e%e7%9b%ae" &gt;接種(2回目)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e5%89%af%e5%8f%8d%e5%bf%9c2%e5%9b%9e%e7%9b%ae" &gt;副反応?(2回目)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="打ったワクチン"&gt;打ったワクチン
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;COVID-19ワクチンモデルナ筋注&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;
&lt;ul&gt;
&lt;li&gt;約1ヶ月の間隔を空けて2回接種した&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="ワクチンを打った人ぼく"&gt;ワクチンを打った人(ぼく)
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;年齢
&lt;ul&gt;
&lt;li&gt;20代後半&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;性別
&lt;ul&gt;
&lt;li&gt;男&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;身長
&lt;ul&gt;
&lt;li&gt;170cm程度&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;体重
&lt;ul&gt;
&lt;li&gt;60kg程度&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;その他健康面
&lt;ul&gt;
&lt;li&gt;特に大きな持病は無し&lt;/li&gt;
&lt;li&gt;運動不足気味&lt;/li&gt;
&lt;li&gt;食生活は乱れがち&lt;/li&gt;
&lt;li&gt;お酒はあまり飲まない&lt;/li&gt;
&lt;li&gt;タバコもあまり吸わない&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="接種1回目"&gt;接種(1回目)
&lt;/h3&gt;&lt;p&gt;予約前に厚生労働省のサイト&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;はちょっとだけ読んだ。&lt;br&gt;
化学はさっぱりなので成分とかはよくわからなかったけど、臨床試験の概要とか統計のとり方はおもしろかった。&lt;br&gt;
副反応があるという話は聞いていたので、それに備えてスポーツドリンクと頭に貼る冷却シートを多めに用意した。&lt;/p&gt;
&lt;p&gt;当日は午前10時~12時ごろに接種。&lt;br&gt;
健康状態は問題なく、普通に問診してそのままワクチンを打ってもらった。&lt;/p&gt;
&lt;p&gt;利き腕が右なので左肩に注射。&lt;br&gt;
結構ガッツリ肩を出して打ってもらうので、半袖Tシャツを着ていったのは正解だったと思う。&lt;br&gt;
筋肉注射がたぶん初めてなので緊張していたが、 担当の方が上手だったのか針が刺さっていることすら気づかず数秒で接種終了。&lt;br&gt;
当日は激しい運動をしない、打ったところは強く触らないように言われた。&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="こんな紙をもらう" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1512" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-08-11-covid-19-vaccinated/img01.jpg" srcset="https://blog.uzimihsr.com/post/2021-08-11-covid-19-vaccinated/img01_hu_75d9a7091be262.jpg 800w, https://blog.uzimihsr.com/post/2021-08-11-covid-19-vaccinated/img01_hu_6fa77b19bafc1a72.jpg 1600w, https://blog.uzimihsr.com/post/2021-08-11-covid-19-vaccinated/img01.jpg 2016w" width="2016"&gt;&lt;/p&gt;
&lt;p&gt;接種後は会場内の椅子に座って15分待つよう指示があった。&lt;br&gt;
持病があったりしてリスクの高い人は30分待つように言われる場合もあるらしい。&lt;br&gt;
待機する場所には接種を終えた人(年齢性別バラバラ)がだいたい10~30人くらいいた。&lt;br&gt;
緊急時に備えて看護師?医師?の方が複数人準備してくれていたが、自分がお世話になることはなかったし、周りで具合が悪くなった人もいなかった。&lt;/p&gt;
&lt;p&gt;幸いなことに15分経っても何も起こらなかったのでそのまま退場。&lt;br&gt;
後述のとおり副反応?も軽かったので普通に仕事をして、&lt;br&gt;
昼ごはんは担々麺、晩ごはんはラーメンを食べて帰宅後はシャワーを少しだけ短めに浴びて普通に寝た。&lt;/p&gt;
&lt;p&gt;&lt;img alt="接種記録書とかいうやつ" class="gallery-image" data-flex-basis="489px" data-flex-grow="203" height="1879" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-08-11-covid-19-vaccinated/img02.jpg" srcset="https://blog.uzimihsr.com/post/2021-08-11-covid-19-vaccinated/img02_hu_f1aa3fe3df3b560b.jpg 800w, https://blog.uzimihsr.com/post/2021-08-11-covid-19-vaccinated/img02_hu_d647111c0a240dfb.jpg 1600w, https://blog.uzimihsr.com/post/2021-08-11-covid-19-vaccinated/img02_hu_d129921f5e938a81.jpg 2400w, https://blog.uzimihsr.com/post/2021-08-11-covid-19-vaccinated/img02.jpg 3833w" width="3833"&gt;&lt;/p&gt;
&lt;h3 id="副反応1回目"&gt;副反応?(1回目)
&lt;/h3&gt;&lt;p&gt;一応副反応というか普段と接種後で違う体の症状は次のようなものがあった。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;注射した左腕に筋肉痛に似た症状(接種から2時間後~24時間後)
&lt;ul&gt;
&lt;li&gt;腕を体の前方に向かって挙げる動き(フロントレイズ)はちょっと痛い&lt;/li&gt;
&lt;li&gt;体の横から腕を挙げる動き(サイドレイズ)はめちゃくちゃ痛い&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;顎の下のリンパ節？のあたりに痛み(接種から24時間後~48時間後)
&lt;ul&gt;
&lt;li&gt;口を閉じていると特に気にならないが、大きく口をあけたり手で押すと痛い&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;下痢(接種当日夜)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;とはいえ、特に生活に支障をきたすほどの症状はなかった。&lt;br&gt;
翌日以降も顎下リンパ節?の痛み以外は何もなかったのでこれまで通りの生活をした。&lt;/p&gt;
&lt;h3 id="接種2回目"&gt;接種(2回目)
&lt;/h3&gt;&lt;p&gt;1回目とほぼ同じ時間帯に同じように接種。&lt;/p&gt;
&lt;p&gt;違う点があったとすれば、&lt;br&gt;
接種前日までにトラブルがあり左肩を強く打って内出血していたので、&lt;br&gt;
1回目とは異なり利き腕の右肩に注射を打ってもらった。&lt;br&gt;
問診のときに心配になって質問したけど、1回目と2回目で違う腕に打っても効果に問題はないらしい。&lt;/p&gt;
&lt;p&gt;また、2回目の注射は針が刺さったのがわかるくらいの痛みがちょっとだけあった。&lt;br&gt;
このあたりは打つ人のテクニックによる気がする。&lt;/p&gt;
&lt;p&gt;接種後の指示も1回目とは変わらず、同じように待機して同じように何もなかったので同じように退場。&lt;br&gt;
後述のだるさがあったので仕事も早めに切り上げた。&lt;br&gt;
昼ごはんはカレー、晩ごはんはラーメンを食べて軽くシャワーを浴びていつもより早めに寝た。&lt;/p&gt;
&lt;p&gt;&lt;img alt="1回目に比べてシールが小さい" class="gallery-image" data-flex-basis="512px" data-flex-grow="213" height="1783" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-08-11-covid-19-vaccinated/img03.jpg" srcset="https://blog.uzimihsr.com/post/2021-08-11-covid-19-vaccinated/img03_hu_c60a31bca0f502f3.jpg 800w, https://blog.uzimihsr.com/post/2021-08-11-covid-19-vaccinated/img03_hu_1c0c8b0be368267f.jpg 1600w, https://blog.uzimihsr.com/post/2021-08-11-covid-19-vaccinated/img03_hu_614f7fe9a6133626.jpg 2400w, https://blog.uzimihsr.com/post/2021-08-11-covid-19-vaccinated/img03.jpg 3807w" width="3807"&gt;&lt;/p&gt;
&lt;h3 id="副反応2回目"&gt;副反応?(2回目)
&lt;/h3&gt;&lt;p&gt;前評判どおり2回目は1回目よりも体調の変化が大きかった。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;注射した右腕に筋肉痛に似た症状(接種から2時間後~12時間後)
&lt;ul&gt;
&lt;li&gt;1回目とだいたい同じだが、期間がちょっと短く接種当日の夜には治まった&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;全身の疲労感、関節の痛み、眠気(接種から4時間後~36時間後)
&lt;ul&gt;
&lt;li&gt;座ってるとなにもしたくなくなる、すぐ横になりたくなるくらいのだるさ&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;発熱(接種から24時間後~36時間後)
&lt;ul&gt;
&lt;li&gt;平熱+2℃くらい&lt;/li&gt;
&lt;li&gt;寝ている間に熱でうなされて目が冷めた&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;下痢(接種当日~翌日夕方)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;特に翌日朝からの発熱がつらかった。&lt;br&gt;
風邪のときほど苦しくはないけど、動くのがめんどくさかったり食欲が出なかったりで夕方まで寝て過ごした。&lt;br&gt;
1回目の接種前に用意した冷却シートがまるまる残っていたのと、保冷剤を首や脇に当てたおかげでいくらか楽だった。&lt;br&gt;
とにかく喉が渇いたので、スポーツドリンクを多めに用意しておいたのも正解だったと思う。&lt;/p&gt;
&lt;p&gt;&lt;img alt="最高記録" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-08-11-covid-19-vaccinated/img04.jpg" srcset="https://blog.uzimihsr.com/post/2021-08-11-covid-19-vaccinated/img04_hu_cbf8e3a196d5cf94.jpg 800w, https://blog.uzimihsr.com/post/2021-08-11-covid-19-vaccinated/img04_hu_6e198803cbc014bb.jpg 1600w, https://blog.uzimihsr.com/post/2021-08-11-covid-19-vaccinated/img04_hu_105199e76fb1b562.jpg 2400w, https://blog.uzimihsr.com/post/2021-08-11-covid-19-vaccinated/img04.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;俺が発熱してるのでねこが暖をとりにきた &lt;a href="https://t.co/FpddgoBsRF"&gt;pic.twitter.com/FpddgoBsRF&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1420163170866323456?ref_src=twsrc%5Etfw"&gt;July 27, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;2回目の副反応?はその後接種翌日の夕方(接種から36時間後)にはほとんどおさまり、&lt;br&gt;
以降は大きく体調を崩すこともなかった。&lt;br&gt;
(この記事は2回目の接種から2週後に書いているが、今現在体調で困っていることはない)&lt;/p&gt;
&lt;p&gt;周りで同じワクチンを接種した人の話を聞くともっと高い熱が2日以上出たケースもあったみたいで、&lt;br&gt;
自分はかなり軽く済んだ方だったらしい。&lt;br&gt;
よかった(?)。&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;COVID-19のワクチンについて周りの人の話やメディアを見ると「副反応が強い」というケースが多いように見えたので、&lt;br&gt;
副反応が結構軽め(?)だった人の話も少しはあると良いかと思って駄文を書いてみた。&lt;br&gt;
若者と呼ばれる世代の中では比較的早めに打ったほうだと思うので、人柱として誰かの参考になればいいと思う。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="そろそろ混合ワクチンを打たなきゃいけない気がするねこちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="2268" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-08-11-covid-19-vaccinated/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2021-08-11-covid-19-vaccinated/sotochan_hu_e05968269d1636f0.jpg 800w, https://blog.uzimihsr.com/post/2021-08-11-covid-19-vaccinated/sotochan_hu_73d5f4f3e0631230.jpg 1600w, https://blog.uzimihsr.com/post/2021-08-11-covid-19-vaccinated/sotochan_hu_5721d17f92fb498b.jpg 2400w, https://blog.uzimihsr.com/post/2021-08-11-covid-19-vaccinated/sotochan.jpg 3024w" width="3024"&gt;&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a class="link" href="https://www.take-care-covid-19.jp/" target="_blank" rel="noopener"
 &gt;https://www.take-care-covid-19.jp/&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;a class="link" href="https://www.mhlw.go.jp/stf/seisakunitsuite/bunya/vaccine_moderna.html" target="_blank" rel="noopener"
 &gt;https://www.mhlw.go.jp/stf/seisakunitsuite/bunya/vaccine_moderna.html&lt;/a&gt;&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;&lt;a class="link" href="https://www.mhlw.go.jp/content/000805693.pdf" target="_blank" rel="noopener"
 &gt;https://www.mhlw.go.jp/content/000805693.pdf&lt;/a&gt;&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>7月のそとちゃん(2021)</title><link>https://blog.uzimihsr.com/post/2021-08-08-sotochan/</link><pubDate>Sun, 08 Aug 2021 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2021-08-08-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2021-08-08-sotochan/sotochan.jpg" alt="Featured image of post 7月のそとちゃん(2021)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%8b%e3%82%8f%e3%81%84%e3%81%84%e3%83%9d%e3%83%bc%e3%82%ba" &gt;かわいいポーズ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%91%e3%82%bd%e3%82%b3%e3%83%b3%e5%a6%a8%e5%ae%b3%e3%81%ad%e3%81%93" &gt;パソコン妨害ねこ&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="かわいいポーズ"&gt;かわいいポーズ
&lt;/h3&gt;&lt;p&gt;そとちゃんの得意技、おでこを床につけるポーズ&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;はみがき断固拒否のポーズ &lt;a href="https://t.co/FfkCxGBvM2"&gt;pic.twitter.com/FfkCxGBvM2&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1410577350937354240?ref_src=twsrc%5Etfw"&gt;July 1, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;甘えてるのか「かかってこいや」なのかはわからないけど、&lt;br&gt;
特に夕方のごはん前とか俺が外出して戻ってきたときによくやる。&lt;/p&gt;
&lt;p&gt;ちなみにこのときおなかを触るとバチボコに噛んで掴んで蹴ってくる。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;椅子取られた &lt;a href="https://t.co/TqR1zFoYMx"&gt;pic.twitter.com/TqR1zFoYMx&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1412623691016404992?ref_src=twsrc%5Etfw"&gt;July 7, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;かわいい。🥰&lt;/p&gt;
&lt;h3 id="パソコン妨害ねこ"&gt;パソコン妨害ねこ
&lt;/h3&gt;&lt;p&gt;ちょっと前まで仕事は&lt;a class="link" href="http://localhost:1313/post/2020-12-30-sotochan/#%e3%83%91%e3%82%bd%e3%82%b3%e3%83%b3%e7%b5%b6%e5%af%be%e9%82%aa%e9%ad%94%e3%81%99%e3%82%8b%e3%81%ad%e3%81%93" target="_blank" rel="noopener"
 &gt;MacBookを普通に開いてやっていた&lt;/a&gt;んだけど、&lt;br&gt;
最近ついにディスプレイを買ってMacBookを閉じて使うようになった。&lt;/p&gt;
&lt;p&gt;机が広くなって快適！生産性向上！&lt;br&gt;
と思ったのだが、うちには妖怪パソコン妨害ねこちゃんがいるのを忘れていた。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;仕事バチクソ妨害ねこちゃんが現れた &lt;a href="https://t.co/nSR5Xde428"&gt;pic.twitter.com/nSR5Xde428&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1420686863820414990?ref_src=twsrc%5Etfw"&gt;July 29, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;まずはシンプルに画面を観にくるパターン。&lt;/p&gt;
&lt;p&gt;&lt;img alt="これは猫用動画で釣ったから俺も悪い" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-08-08-sotochan/sotochan01.jpg" srcset="https://blog.uzimihsr.com/post/2021-08-08-sotochan/sotochan01_hu_e9555b1378caec3c.jpg 800w, https://blog.uzimihsr.com/post/2021-08-08-sotochan/sotochan01_hu_fedf74b56b361c43.jpg 1600w, https://blog.uzimihsr.com/post/2021-08-08-sotochan/sotochan01_hu_fb024758f9d72a8b.jpg 2400w, https://blog.uzimihsr.com/post/2021-08-08-sotochan/sotochan01.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;これがエスカレートすると次はディスプレイとキーボードの間に挟まってくる。&lt;/p&gt;
&lt;p&gt;&lt;img alt="せまそう" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-08-08-sotochan/sotochan02.jpg" srcset="https://blog.uzimihsr.com/post/2021-08-08-sotochan/sotochan02_hu_a33283d0ec8d0754.jpg 800w, https://blog.uzimihsr.com/post/2021-08-08-sotochan/sotochan02_hu_b837c1196d9e1e88.jpg 1600w, https://blog.uzimihsr.com/post/2021-08-08-sotochan/sotochan02_hu_674c9ba22699455e.jpg 2400w, https://blog.uzimihsr.com/post/2021-08-08-sotochan/sotochan02.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;このとき躊躇なくキーを踏んだりするので普通に仕事に支障をきたす。&lt;/p&gt;
&lt;p&gt;また、今までトラックパッドで作業していたのをマウスに変えたのだが、&lt;br&gt;
これがそとちゃんの新たなおもちゃになってしまった。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;マウスは枕 &lt;a href="https://t.co/ftCYn2UfXZ"&gt;pic.twitter.com/ftCYn2UfXZ&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1421382163551834113?ref_src=twsrc%5Etfw"&gt;July 31, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;マウスの滑りが良いので、&lt;br&gt;
力の弱いそとちゃんでもかんたんに動かせるのが楽しいらしい。&lt;/p&gt;
&lt;p&gt;&lt;img alt="このあと机から落とす" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-08-08-sotochan/sotochan03.jpg" srcset="https://blog.uzimihsr.com/post/2021-08-08-sotochan/sotochan03_hu_78dc986b3bb240f5.jpg 800w, https://blog.uzimihsr.com/post/2021-08-08-sotochan/sotochan03_hu_9a6471bbbb1d3a13.jpg 1600w, https://blog.uzimihsr.com/post/2021-08-08-sotochan/sotochan03_hu_b43785302a81bab5.jpg 2400w, https://blog.uzimihsr.com/post/2021-08-08-sotochan/sotochan03.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;マウスを机から落としてご満悦 &lt;a href="https://t.co/hKeaNWWO3J"&gt;pic.twitter.com/hKeaNWWO3J&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1420694860705800196?ref_src=twsrc%5Etfw"&gt;July 29, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;よかったね。😭&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;7月のそとちゃんはよくつっかかってきた。&lt;/p&gt;
&lt;p&gt;これまでに比べるとちょっと出社が多かったり(月に数回だが&amp;hellip;)して寂しい思いをさせているので、&lt;br&gt;
またあまえんぼ期がきているかもしれない。&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="バトルシップとねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-08-08-sotochan/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2021-08-08-sotochan/sotochan_hu_e314f9d65f82078.jpg 800w, https://blog.uzimihsr.com/post/2021-08-08-sotochan/sotochan_hu_1de29b0f85312660.jpg 1600w, https://blog.uzimihsr.com/post/2021-08-08-sotochan/sotochan_hu_49dadeff3f94d2d.jpg 2400w, https://blog.uzimihsr.com/post/2021-08-08-sotochan/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>Kubernetesのsample-controllerをDeploymentとして動かす</title><link>https://blog.uzimihsr.com/post/2021-07-13-kubernetes-run-sample-controller-as-deployment/</link><pubDate>Tue, 13 Jul 2021 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2021-07-13-kubernetes-run-sample-controller-as-deployment/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2021-07-13-kubernetes-run-sample-controller-as-deployment/sotochan.jpg" alt="Featured image of post Kubernetesのsample-controllerをDeploymentとして動かす" /&gt;&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/kubernetes/sample-controller" target="_blank" rel="noopener"
 &gt;sample-controller&lt;/a&gt;を&lt;code&gt;Deployment&lt;/code&gt;として&lt;a class="link" href="https://github.com/kubernetes-sigs/kind/" target="_blank" rel="noopener"
 &gt;kind&lt;/a&gt;のクラスタ内で動かした&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Big Sur 11.2.3&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/editions/community/docker-ce-desktop-mac" target="_blank" rel="noopener"
 &gt;Docker Desktop for Mac&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Version 3.4.0&lt;/li&gt;
&lt;li&gt;Docker Engine Version 20.10.7&lt;/li&gt;
&lt;li&gt;Docker Compose Version 1.29.2&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/kubernetes-sigs/kind/" target="_blank" rel="noopener"
 &gt;kind&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;v0.11.0 go1.16.4 darwin/amd64&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/kubernetes/kubernetes" target="_blank" rel="noopener"
 &gt;Kubernetes&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;v1.21.1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%b3%e3%83%bc%e3%83%89%e3%81%ae%e4%bf%ae%e6%ad%a3%e3%81%a8image%e3%81%ae%e3%83%93%e3%83%ab%e3%83%89" &gt;コードの修正とimageのビルド&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#kind%e3%81%a7%e3%83%ad%e3%83%bc%e3%82%ab%e3%83%abimage%e3%82%92%e4%bd%bf%e3%81%86%e8%a8%ad%e5%ae%9a%e3%81%a8deployment%e3%81%ae%e4%bd%9c%e6%88%90" &gt;kindでローカルimageを使う設定とDeploymentの作成&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#clusterrole%e3%81%a8clusterrolebinding%e3%81%ae%e4%bd%9c%e6%88%90" &gt;ClusterRoleとClusterRoleBindingの作成&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e5%86%8d%e5%ba%a6%e5%8b%95%e3%81%8b%e3%81%97%e3%81%a6%e3%81%bf%e3%82%8b" &gt;再度動かしてみる&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="コードの修正とimageのビルド"&gt;コードの修正とimageのビルド
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2021-07-12-kubernetes-crd-controller-practice/" target="_blank" rel="noopener"
 &gt;前回sample-controllerを動かしたとき&lt;/a&gt;はコントローラー自体はクラスタ外で動かし,&lt;br&gt;
&lt;code&gt;Kubernetes API&lt;/code&gt;への接続にはローカルの&lt;code&gt;kubeconfig&lt;/code&gt;を使用していた.&lt;/p&gt;
&lt;p&gt;今回はコントローラー自体も&lt;code&gt;Pod&lt;/code&gt;としてクラスタ内で動かすため,&lt;br&gt;
&lt;code&gt;Kubernetes API&lt;/code&gt;に接続するための情報を&lt;code&gt;Pod&lt;/code&gt;に持たせる必要がある.&lt;/p&gt;
&lt;p&gt;ここで使えるのが&lt;code&gt;client-go&lt;/code&gt;の&lt;code&gt;rest.InClusterConfig()&lt;/code&gt;.&lt;br&gt;
&lt;code&gt;Pod&lt;/code&gt;にマウントされた&lt;code&gt;ServiceAccount&lt;/code&gt;のトークンを使って&lt;code&gt;Kubernetes API&lt;/code&gt;へ接続する設定を作ってくれる&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/uzimihsr/sample-controller/blob/in-cluster-config/main.go" target="_blank" rel="noopener"
 &gt;kubeconfigを使わないようにしたmain.go&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;rest.InClusterConfig()&lt;/code&gt;を使うようにコードを書き換えた状態で&lt;code&gt;Docker image&lt;/code&gt;をビルドする.&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/uzimihsr/sample-controller/blob/in-cluster-config/Dockerfile" target="_blank" rel="noopener"
 &gt;Dockerfile&lt;/a&gt;は&lt;code&gt;Go&lt;/code&gt;用のものを&lt;a class="link" href="https://uzimihsr.github.io/post/2020-03-15-golang-build-image/" target="_blank" rel="noopener"
 &gt;いい感じ&lt;/a&gt;に書いてみた.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Docker imageのビルド&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls Dockerfile
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Dockerfile
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image build -t sample-controller:develop .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Dockerでこのまま実行しても必要な情報が無いので怒られる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run sample-controller:develop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;panic: unable to load in-cluster configuration, KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT must be defined
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;goroutine &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;running&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;main.main&lt;span class="o"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	/sample-controller/main.go:56 +0x685&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;とりあえず動きそう.&lt;/p&gt;
&lt;h3 id="kindでローカルimageを使う設定とdeploymentの作成"&gt;kindでローカルimageを使う設定とDeploymentの作成
&lt;/h3&gt;&lt;p&gt;次にローカルでビルドしたカスタムコントローラーの&lt;code&gt;Docker image&lt;/code&gt;を&lt;code&gt;kind&lt;/code&gt;で作ったクラスタで使えるように設定する&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# CRDが作成されていない場合は作成しておく&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f artifacts/examples/crd.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;customresourcedefinition.apiextensions.k8s.io/foos.samplecontroller.k8s.io created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ローカルDockerのimageをkindのクラスタで使えるようにする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kind load docker-image sample-controller:develop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Image: &lt;span class="s2"&gt;&amp;#34;sample-controller:develop&amp;#34;&lt;/span&gt; with ID &lt;span class="s2"&gt;&amp;#34;sha256:dde0eac9c3c272e80dc1e98c705c34ddf35b7d5c585fc32364563d2d96db386d&amp;#34;&lt;/span&gt; not yet present on node &lt;span class="s2"&gt;&amp;#34;kind-control-plane&amp;#34;&lt;/span&gt;, loading...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;この&lt;code&gt;image&lt;/code&gt;を使った&lt;code&gt;Deployment&lt;/code&gt;を作成する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Deploymentの作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create deployment sample-controller --image&lt;span class="o"&gt;=&lt;/span&gt;sample-controller:develop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps/sample-controller created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get deployment
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY UP-TO-DATE AVAILABLE AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-controller 1/1 &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 2m11s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample-controller
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-controller-f48d54cf4-drqwl 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 2m31s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# PodにデフォルトのServiceAccount(default:default)が設定されている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Tokenなどの情報が/var/run/secrets/kubernetes.io/serviceaccountにマウントされている(rest.InClusterConfig()はこれを参照している)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pod sample-controller-f48d54cf4-drqwl -o yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apiVersion: v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kind: Pod
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; containers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - image: sample-controller:develop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: sample-controller
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; volumeMounts:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: kube-api-access-vx85f
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; readOnly: &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; serviceAccount: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; serviceAccountName: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; volumes:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - name: kube-api-access-vx85f
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; projected:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; defaultMode: &lt;span class="m"&gt;420&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; sources:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - serviceAccountToken:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; expirationSeconds: &lt;span class="m"&gt;3607&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; path: token
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - configMap:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; items:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - key: ca.crt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; path: ca.crt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: kube-root-ca.crt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - downwardAPI:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; items:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - fieldRef:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; apiVersion: v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; fieldPath: metadata.namespace
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; path: namespace&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;すると今度は&lt;code&gt;Docker&lt;/code&gt;で動かしたときと異なり,&lt;br&gt;
&lt;code&gt;ServiceAccount&lt;/code&gt;の情報が取得できるのでコントローラーが動いた!&lt;/p&gt;
&lt;p&gt;&amp;hellip;が, 次は&lt;code&gt;Pod&lt;/code&gt;に自動で紐づくデフォルトの&lt;code&gt;ServiceAccount&lt;/code&gt;(&lt;strong&gt;default:default&lt;/strong&gt;)にこのコントローラーで操作する&lt;code&gt;Deployment&lt;/code&gt;と&lt;strong&gt;Foo&lt;/strong&gt;(カスタムリソース)の一覧を取得する権限(list)がないためエラーになってしまった.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 今度はconfigが作成できて動作を開始している&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ...が, DeploymentとFoo(カスタムリソース)を参照する権限がないためうまく動いていない&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl logs sample-controller-f48d54cf4-drqwl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;I0707 09:01:00.813715 &lt;span class="m"&gt;1&lt;/span&gt; controller.go:115&lt;span class="o"&gt;]&lt;/span&gt; Setting up event handlers
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;I0707 09:01:00.813806 &lt;span class="m"&gt;1&lt;/span&gt; controller.go:156&lt;span class="o"&gt;]&lt;/span&gt; Starting Foo controller
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;I0707 09:01:00.813810 &lt;span class="m"&gt;1&lt;/span&gt; controller.go:159&lt;span class="o"&gt;]&lt;/span&gt; Waiting &lt;span class="k"&gt;for&lt;/span&gt; informer caches to sync
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;E0707 09:01:00.826284 &lt;span class="m"&gt;1&lt;/span&gt; reflector.go:138&lt;span class="o"&gt;]&lt;/span&gt; pkg/mod/k8s.io/client-go@v0.0.0-20210701054555-843bb800b12a/tools/cache/reflector.go:167: Failed to watch *v1alpha1.Foo: failed to list *v1alpha1.Foo: foos.samplecontroller.k8s.io is forbidden: User &lt;span class="s2"&gt;&amp;#34;system:serviceaccount:default:default&amp;#34;&lt;/span&gt; cannot list resource &lt;span class="s2"&gt;&amp;#34;foos&amp;#34;&lt;/span&gt; in API group &lt;span class="s2"&gt;&amp;#34;samplecontroller.k8s.io&amp;#34;&lt;/span&gt; at the cluster scope
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;E0707 09:01:00.826385 &lt;span class="m"&gt;1&lt;/span&gt; reflector.go:138&lt;span class="o"&gt;]&lt;/span&gt; pkg/mod/k8s.io/client-go@v0.0.0-20210701054555-843bb800b12a/tools/cache/reflector.go:167: Failed to watch *v1.Deployment: failed to list *v1.Deployment: deployments.apps is forbidden: User &lt;span class="s2"&gt;&amp;#34;system:serviceaccount:default:default&amp;#34;&lt;/span&gt; cannot list resource &lt;span class="s2"&gt;&amp;#34;deployments&amp;#34;&lt;/span&gt; in API group &lt;span class="s2"&gt;&amp;#34;apps&amp;#34;&lt;/span&gt; at the cluster scope
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...&lt;span class="o"&gt;(&lt;/span&gt;以下繰り返し&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# いったん消しておく&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl delete deployment sample-controller
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps &lt;span class="s2"&gt;&amp;#34;sample-controller&amp;#34;&lt;/span&gt; deleted&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="clusterroleとclusterrolebindingの作成"&gt;ClusterRoleとClusterRoleBindingの作成
&lt;/h3&gt;&lt;p&gt;というわけで次は&lt;code&gt;ServiceAccount&lt;/code&gt;で&lt;code&gt;Deployemnt&lt;/code&gt;と&lt;strong&gt;Foo&lt;/strong&gt;のリソースを操作するための権限(&lt;code&gt;ClusterRole&lt;/code&gt;)を作成する.&lt;br&gt;
今回は使用するsample-controllerが全&lt;code&gt;namespace&lt;/code&gt;を対象に操作を行うため&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;,&lt;br&gt;
&lt;code&gt;namespace&lt;/code&gt;レベルの権限の&lt;code&gt;Role&lt;/code&gt;ではなくクラスタレベルの&lt;code&gt;ClusterRole&lt;/code&gt;を使用した.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ClusterRoleの作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# DeploymentとFoo(カスタムリソース)とEventに対する全ての操作を許可する権限&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create clusterrole foo-control --verb&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;*&amp;#34;&lt;/span&gt; --resource&lt;span class="o"&gt;=&lt;/span&gt;foo,deployment,event
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;clusterrole.rbac.authorization.k8s.io/foo-control created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get clusterrole foo-control -o yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apiVersion: rbac.authorization.k8s.io/v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kind: ClusterRole
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; creationTimestamp: &lt;span class="s2"&gt;&amp;#34;2021-07-12T14:04:28Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: foo-control
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; resourceVersion: &lt;span class="s2"&gt;&amp;#34;4126888&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; uid: 9b628c44-0320-48eb-8861-0e3c5d8f9ddf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rules:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- apiGroups:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; resources:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - events
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; verbs:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - &lt;span class="s1"&gt;&amp;#39;*&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- apiGroups:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - apps
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; resources:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - deployments
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; verbs:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - &lt;span class="s1"&gt;&amp;#39;*&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- apiGroups:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - samplecontroller.k8s.io
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; resources:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - foos
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; verbs:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - &lt;span class="s1"&gt;&amp;#39;*&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;最後に, 作成した&lt;code&gt;ClusterRole&lt;/code&gt;を&lt;code&gt;ServiceAccount&lt;/code&gt;に紐付けるための&lt;code&gt;ClusterRoleBinding&lt;/code&gt;を作成する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ClusterRoleBindingの作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ClusterRole(foo-control)をServiceAccount(default:default)に紐付ける&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create clusterrolebinding foo-control-binding --clusterrole&lt;span class="o"&gt;=&lt;/span&gt;foo-control --serviceaccount&lt;span class="o"&gt;=&lt;/span&gt;default:default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;clusterrolebinding.rbac.authorization.k8s.io/foo-control-binding created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get clusterrolebinding foo-control-binding -o yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apiVersion: rbac.authorization.k8s.io/v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kind: ClusterRoleBinding
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; creationTimestamp: &lt;span class="s2"&gt;&amp;#34;2021-07-12T14:06:04Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: foo-control-binding
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; resourceVersion: &lt;span class="s2"&gt;&amp;#34;4127049&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; uid: 09bde8fd-752a-433b-845a-5584aa1324a8
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;roleRef:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; apiGroup: rbac.authorization.k8s.io
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kind: ClusterRole
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: foo-control
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;subjects:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- kind: ServiceAccount
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; namespace: default&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;これで&lt;code&gt;Pod&lt;/code&gt;にデフォルトで紐づく&lt;code&gt;ServiceAccount&lt;/code&gt;(&lt;strong&gt;default:default&lt;/strong&gt;)にクラスタ内の&lt;code&gt;Deployment&lt;/code&gt;と&lt;strong&gt;Foo&lt;/strong&gt;(カスタムリソース)を操作する権限が与えられた.&lt;/p&gt;
&lt;h3 id="再度動かしてみる"&gt;再度動かしてみる
&lt;/h3&gt;&lt;p&gt;以上でコントローラーを&lt;code&gt;Deployment&lt;/code&gt;として動かすために必要な準備ができたはずなので,&lt;br&gt;
もう一度挑戦してみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Deploymentの作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create deployment sample-controller --image&lt;span class="o"&gt;=&lt;/span&gt;sample-controller:develop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps/sample-controller created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get deployment
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY UP-TO-DATE AVAILABLE AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-controller 1/1 &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 8s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample-controller
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-controller-f48d54cf4-jgv4w 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 12s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 動いた...!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl logs sample-controller-f48d54cf4-jgv4w
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;I0712 14:07:14.403608 &lt;span class="m"&gt;1&lt;/span&gt; controller.go:115&lt;span class="o"&gt;]&lt;/span&gt; Setting up event handlers
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;I0712 14:07:14.404169 &lt;span class="m"&gt;1&lt;/span&gt; controller.go:156&lt;span class="o"&gt;]&lt;/span&gt; Starting Foo controller
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;I0712 14:07:14.404319 &lt;span class="m"&gt;1&lt;/span&gt; controller.go:159&lt;span class="o"&gt;]&lt;/span&gt; Waiting &lt;span class="k"&gt;for&lt;/span&gt; informer caches to sync
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;I0712 14:07:14.705485 &lt;span class="m"&gt;1&lt;/span&gt; controller.go:164&lt;span class="o"&gt;]&lt;/span&gt; Starting workers
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;I0712 14:07:14.706297 &lt;span class="m"&gt;1&lt;/span&gt; controller.go:170&lt;span class="o"&gt;]&lt;/span&gt; Started workers&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;動いた&amp;hellip;!&lt;br&gt;
&lt;code&gt;Pod&lt;/code&gt;のログの内容も&lt;a class="link" href="https://uzimihsr.github.io/post/2021-07-12-kubernetes-crd-controller-practice/" target="_blank" rel="noopener"
 &gt;前回&lt;/a&gt;と同じで, 問題なく動いているように見える.&lt;/p&gt;
&lt;p&gt;最後に&lt;strong&gt;Foo&lt;/strong&gt;リソースを作成してみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Fooを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat &lt;span class="s"&gt;&amp;lt;&amp;lt; EOF | kubectl apply -f -
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: samplecontroller.k8s.io/v1alpha1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: Foo
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; name: my-foo
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; deploymentName: my-foo
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; replicas: 10
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;foo.samplecontroller.k8s.io/my-foo created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Fooとそれによって管理されるDeploymentが作成されている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get foo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-foo 40s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get deployment
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY UP-TO-DATE AVAILABLE AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-foo 10/10 &lt;span class="m"&gt;10&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt; 27s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-controller 1/1 &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 5m15s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods --show-labels
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE LABELS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-foo-65f55f8578-2j2g6 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 47s &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;nginx,controller&lt;span class="o"&gt;=&lt;/span&gt;my-foo,pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;65f55f8578
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-foo-65f55f8578-44tbj 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 47s &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;nginx,controller&lt;span class="o"&gt;=&lt;/span&gt;my-foo,pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;65f55f8578
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-foo-65f55f8578-5n58m 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 47s &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;nginx,controller&lt;span class="o"&gt;=&lt;/span&gt;my-foo,pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;65f55f8578
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-foo-65f55f8578-bdtwp 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 47s &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;nginx,controller&lt;span class="o"&gt;=&lt;/span&gt;my-foo,pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;65f55f8578
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-foo-65f55f8578-gq7hh 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 47s &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;nginx,controller&lt;span class="o"&gt;=&lt;/span&gt;my-foo,pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;65f55f8578
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-foo-65f55f8578-jb258 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 47s &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;nginx,controller&lt;span class="o"&gt;=&lt;/span&gt;my-foo,pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;65f55f8578
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-foo-65f55f8578-kr6mt 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 47s &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;nginx,controller&lt;span class="o"&gt;=&lt;/span&gt;my-foo,pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;65f55f8578
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-foo-65f55f8578-mmtlk 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 47s &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;nginx,controller&lt;span class="o"&gt;=&lt;/span&gt;my-foo,pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;65f55f8578
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-foo-65f55f8578-pk847 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 47s &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;nginx,controller&lt;span class="o"&gt;=&lt;/span&gt;my-foo,pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;65f55f8578
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-foo-65f55f8578-vpvf6 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 47s &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;nginx,controller&lt;span class="o"&gt;=&lt;/span&gt;my-foo,pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;65f55f8578
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-controller-f48d54cf4-jgv4w 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 5m35s &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample-controller,pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;f48d54cf4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Fooで管理されているのでDeploymentを手で消してもすぐ復活する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl delete deployment my-foo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps &lt;span class="s2"&gt;&amp;#34;my-foo&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get deployment
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY UP-TO-DATE AVAILABLE AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-foo 0/10 &lt;span class="m"&gt;10&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; 17s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-controller 1/1 &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 6m58s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Statusも正常に更新されている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get foo my-foo -o yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apiVersion: samplecontroller.k8s.io/v1alpha1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kind: Foo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; annotations:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubectl.kubernetes.io/last-applied-configuration: &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;apiVersion&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;samplecontroller.k8s.io/v1alpha1&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;kind&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;Foo&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;metadata&amp;#34;&lt;/span&gt;:&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;annotations&amp;#34;&lt;/span&gt;:&lt;span class="o"&gt;{}&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;my-foo&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;namespace&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;default&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;spec&amp;#34;&lt;/span&gt;:&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;deploymentName&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;my-foo&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;replicas&amp;#34;&lt;/span&gt;:10&lt;span class="o"&gt;}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; creationTimestamp: &lt;span class="s2"&gt;&amp;#34;2021-07-12T14:11:58Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; generation: &lt;span class="m"&gt;23&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: my-foo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; resourceVersion: &lt;span class="s2"&gt;&amp;#34;4128510&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; uid: a38bc894-769c-4dd0-9d2b-8b3be3ec864b
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; deploymentName: my-foo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; replicas: &lt;span class="m"&gt;10&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;status:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; availableReplicas: &lt;span class="m"&gt;10&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ログを見る限り正常にEventも吐かれている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl logs -f sample-controller-f48d54cf4-jgv4w
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;I0712 14:07:14.403608 &lt;span class="m"&gt;1&lt;/span&gt; controller.go:115&lt;span class="o"&gt;]&lt;/span&gt; Setting up event handlers
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;I0712 14:07:14.404169 &lt;span class="m"&gt;1&lt;/span&gt; controller.go:156&lt;span class="o"&gt;]&lt;/span&gt; Starting Foo controller
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;I0712 14:07:14.404319 &lt;span class="m"&gt;1&lt;/span&gt; controller.go:159&lt;span class="o"&gt;]&lt;/span&gt; Waiting &lt;span class="k"&gt;for&lt;/span&gt; informer caches to sync
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;I0712 14:07:14.705485 &lt;span class="m"&gt;1&lt;/span&gt; controller.go:164&lt;span class="o"&gt;]&lt;/span&gt; Starting workers
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;I0712 14:07:14.706297 &lt;span class="m"&gt;1&lt;/span&gt; controller.go:170&lt;span class="o"&gt;]&lt;/span&gt; Started workers
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;I0712 14:11:58.920953 &lt;span class="m"&gt;1&lt;/span&gt; controller.go:228&lt;span class="o"&gt;]&lt;/span&gt; Successfully synced &lt;span class="s1"&gt;&amp;#39;default/my-foo&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;I0712 14:11:58.948805 &lt;span class="m"&gt;1&lt;/span&gt; event.go:291&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Event occurred&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;object&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;default/my-foo&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;kind&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Foo&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;apiVersion&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;samplecontroller.k8s.io/v1alpha1&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Normal&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;reason&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Synced&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Foo synced successfully&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...&lt;span class="o"&gt;(&lt;/span&gt;以下繰り返し&lt;span class="o"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;Deployment&lt;/code&gt;として動かしたコントローラーでもちゃんとカスタムリソース(&lt;strong&gt;Foo&lt;/strong&gt;)の管理ができた.&lt;br&gt;
やったぜ.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://github.com/kubernetes/sample-controller" target="_blank" rel="noopener"
 &gt;sample-controller&lt;/a&gt;を&lt;code&gt;Docker image&lt;/code&gt;化して, &lt;code&gt;Deployment&lt;/code&gt;として動かすことができた.&lt;/p&gt;
&lt;p&gt;途中権限まわりでちょっとつまづいたけどなんとか乗り切れたので謎の達成感がある. うれしい.&lt;/p&gt;
&lt;p&gt;次は自分でカスタムコントローラーを書いてみたいけど, だいぶめんどくさい&amp;hellip;&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="しあわせなねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-07-13-kubernetes-run-sample-controller-as-deployment/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2021-07-13-kubernetes-run-sample-controller-as-deployment/sotochan_hu_2f3c8cadad293ed0.jpg 800w, https://blog.uzimihsr.com/post/2021-07-13-kubernetes-run-sample-controller-as-deployment/sotochan_hu_85ecd032664cc35e.jpg 1600w, https://blog.uzimihsr.com/post/2021-07-13-kubernetes-run-sample-controller-as-deployment/sotochan_hu_c66f5cbb1720e2f8.jpg 2400w, https://blog.uzimihsr.com/post/2021-07-13-kubernetes-run-sample-controller-as-deployment/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/kubernetes/client-go/tree/master/examples/in-cluster-client-configuration" target="_blank" rel="noopener"
 &gt;https://github.com/kubernetes/client-go/tree/master/examples/in-cluster-client-configuration&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;a class="link" href="https://kind.sigs.k8s.io/docs/user/quick-start/#loading-an-image-into-your-cluster" target="_blank" rel="noopener"
 &gt;https://kind.sigs.k8s.io/docs/user/quick-start/#loading-an-image-into-your-cluster&lt;/a&gt;&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/kubernetes/sample-controller/blob/b8d9e8c247129e53962d0dcfc08a4e8b47477318/pkg/generated/informers/externalversions/factory.go#L91-L108" target="_blank" rel="noopener"
 &gt;https://github.com/kubernetes/sample-controller/blob/b8d9e8c247129e53962d0dcfc08a4e8b47477318/pkg/generated/informers/externalversions/factory.go#L91-L108&lt;/a&gt;&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Kubernetesのsample-controllerで遊ぶ</title><link>https://blog.uzimihsr.com/post/2021-07-12-kubernetes-crd-controller-practice/</link><pubDate>Mon, 12 Jul 2021 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2021-07-12-kubernetes-crd-controller-practice/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2021-07-12-kubernetes-crd-controller-practice/sotochan.jpg" alt="Featured image of post Kubernetesのsample-controllerで遊ぶ" /&gt;&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/kubernetes/sample-controller" target="_blank" rel="noopener"
 &gt;sample-controller&lt;/a&gt;を読んで動かしてCRD(CustomResourceDefinition)とCustom Controllerの概要をつかんだ&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Big Sur 11.2.3&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/editions/community/docker-ce-desktop-mac" target="_blank" rel="noopener"
 &gt;Docker Desktop for Mac&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Version 3.4.0&lt;/li&gt;
&lt;li&gt;Docker Engine Version 20.10.7&lt;/li&gt;
&lt;li&gt;Docker Compose Version 1.29.2&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/kubernetes-sigs/kind/" target="_blank" rel="noopener"
 &gt;kind&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;v0.11.0 go1.16.4 darwin/amd64&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/kubernetes/kubernetes" target="_blank" rel="noopener"
 &gt;Kubernetes&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;v1.21.1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#crd%e3%81%ae%e4%bd%9c%e6%88%90" &gt;CRDの作成&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#controller%e3%81%ae%e3%83%87%e3%83%97%e3%83%ad%e3%82%a4" &gt;Controllerのデプロイ&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="crdの作成"&gt;CRDの作成
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Kubernetes&lt;/code&gt;には既存の&lt;code&gt;Pod&lt;/code&gt;や&lt;code&gt;Deployment&lt;/code&gt;などのリソースに加えて独自のリソースを定義できる&lt;code&gt;CustomResourceDefinition(CRD)&lt;/code&gt;&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;というリソースがある.&lt;br&gt;
これを使うことで既存のリソースでは物足りない機能なんかを自分で作ることができるらしい. すごい.&lt;/p&gt;
&lt;p&gt;CRDを自分で書くのは骨が折れるので, 今回は公式の&lt;a class="link" href="https://github.com/kubernetes/sample-controller" target="_blank" rel="noopener"
 &gt;sample-controller&lt;/a&gt;に付属のCRDを使ってみる.&lt;br&gt;
&lt;a class="link" href="https://github.com/kubernetes/sample-controller/blob/master/artifacts/examples/crd.yaml" target="_blank" rel="noopener"
 &gt;https://github.com/kubernetes/sample-controller/blob/master/artifacts/examples/crd.yaml&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;動かす前に重要そうな設定項目(ほんとは全部重要だが&amp;hellip;)を確認しておく.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;key&lt;/th&gt;
 &lt;th&gt;value&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;apiVersion&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&amp;ldquo;apiextensions.k8s.io/v1&amp;quot;で固定&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;kind&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&amp;ldquo;CustomResourceDefinition&amp;quot;で固定&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;metadata.name&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&amp;ldquo;{spec.names.plural}.{spec.group}&amp;ldquo;とする&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;spec.group&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;KubernetesのREST APIで使用するgroup&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;spec.versions[].name&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;KubernetesのREST APIで使用するAPIのversion&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;spec.versions[].schema&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;CustomResourceの構造の定義(たぶん一番重要)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;spec.scope&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;CustomResourceをNamespace単位で管理する場合:&amp;ldquo;Namespaced&amp;rdquo;,&lt;br&gt;Cluster単位で管理する場合:&amp;ldquo;Cluster&amp;rdquo;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;spec.names&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Kubernetes APIやkubectlで扱うときの名前の定義&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;これを実際にクラスタに適用する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# CRDを適用&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;pwd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/path/to/sample-controller
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f artifacts/examples/crd.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;customresourcedefinition.apiextensions.k8s.io/foos.samplecontroller.k8s.io created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get crd
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME CREATED AT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;foos.samplecontroller.k8s.io 2021-06-28T13:49:53Z
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# CRDで定義したリソース(Foo)がAPIで操作可能になる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl api-resources &lt;span class="p"&gt;|&lt;/span&gt; grep foo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;foos samplecontroller.k8s.io/v1alpha1 &lt;span class="nb"&gt;true&lt;/span&gt; Foo&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;クラスタに&lt;code&gt;CRD&lt;/code&gt;(&lt;strong&gt;foos.samplecontroller.k8s.io&lt;/strong&gt;)が追加された.&lt;/p&gt;
&lt;p&gt;次にこの&lt;code&gt;CRD&lt;/code&gt;に従ったリソースを作成する.&lt;br&gt;
&lt;a class="link" href="https://github.com/kubernetes/sample-controller/blob/master/artifacts/examples/example-foo.yaml" target="_blank" rel="noopener"
 &gt;https://github.com/kubernetes/sample-controller/blob/master/artifacts/examples/example-foo.yaml&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# CustomResourceを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f artifacts/examples/example-foo.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;foo.samplecontroller.k8s.io/example-foo created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# CRDで定義した名前(Foo)で参照できる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get foo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;example-foo 105s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get foo example-foo -o yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apiVersion: samplecontroller.k8s.io/v1alpha1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kind: Foo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; annotations:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubectl.kubernetes.io/last-applied-configuration: &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;apiVersion&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;samplecontroller.k8s.io/v1alpha1&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;kind&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;Foo&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;metadata&amp;#34;&lt;/span&gt;:&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;annotations&amp;#34;&lt;/span&gt;:&lt;span class="o"&gt;{}&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;example-foo&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;namespace&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;default&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;spec&amp;#34;&lt;/span&gt;:&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;deploymentName&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;example-foo&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;replicas&amp;#34;&lt;/span&gt;:1&lt;span class="o"&gt;}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; creationTimestamp: &lt;span class="s2"&gt;&amp;#34;2021-06-28T13:59:25Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; generation: &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: example-foo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; resourceVersion: &lt;span class="s2"&gt;&amp;#34;2385464&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; uid: 560ced47-d085-4b92-b92c-1be78639f878
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; deploymentName: example-foo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; replicas: &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl delete foo example-foo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;foo.samplecontroller.k8s.io &lt;span class="s2"&gt;&amp;#34;example-foo&amp;#34;&lt;/span&gt; deleted&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;apiVersion&lt;/code&gt;, &lt;code&gt;kind&lt;/code&gt;が&lt;code&gt;CRD&lt;/code&gt;で独自に定義した内容に合致しているので,&lt;br&gt;
それに沿った&lt;strong&gt;Foo&lt;/strong&gt;というリソースを作成することができた.&lt;/p&gt;
&lt;p&gt;ただし, この時点ではただ構造化されたデータがREST APIで扱えるようになっただけで,&lt;br&gt;
このリソースがどういった振る舞いをするかなどの情報はどこにも定義されていない.&lt;/p&gt;
&lt;p&gt;これについては次のカスタムコントローラーで定義していく.&lt;/p&gt;
&lt;h3 id="controllerのデプロイ"&gt;Controllerのデプロイ
&lt;/h3&gt;&lt;p&gt;カスタムコントローラーではリソースの&lt;code&gt;status&lt;/code&gt;が&lt;code&gt;spec&lt;/code&gt;で定義した所望の状態に近づくように対象のオブジェクトについて操作を繰り返す.&lt;br&gt;
これを自分で書くのは大変なので, こちらも公式のサンプルをそのまま使う.&lt;br&gt;
&lt;a class="link" href="https://github.com/kubernetes/sample-controller/blob/master/controller.go" target="_blank" rel="noopener"
 &gt;https://github.com/kubernetes/sample-controller/blob/master/controller.go&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;実際に動かす前にこのコントローラーを構成するコンポーネントについて確認しておく.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Informer
&lt;ul&gt;
&lt;li&gt;Kubernetes API(正確にはAPIをwatchしたReflectorによってオブジェクトが追加されたキュー)から変化のあったオブジェクトを順番に取り出す&lt;/li&gt;
&lt;li&gt;取り出したオブジェクトをIndexerに渡す&lt;/li&gt;
&lt;li&gt;オブジェクトの状態に応じたEvent Handlerを呼び出す&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Indexer
&lt;ul&gt;
&lt;li&gt;Informerから受け取ったオブジェクトをメタ情報(namespace/オブジェクト名)で参照可能な状態にしてスレッドセーフな領域に保持する&lt;/li&gt;
&lt;li&gt;必要なKeyが与えられた場合は対象のオブジェクトを返す&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Resource Event Handlers
&lt;ul&gt;
&lt;li&gt;Informerで取り出したオブジェクトの状態に応じた処理を行う&lt;/li&gt;
&lt;li&gt;基本的には対象のオブジェクトのKeyをWork queueに追加する&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Work queue
&lt;ul&gt;
&lt;li&gt;処理が必要なオブジェクトのKeyを保持するキュー&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Process Item
&lt;ul&gt;
&lt;li&gt;Work queueから取り出したKeyを参照してIndexerからオブジェクトを取り出し必要な操作を行う&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="CustomController" class="gallery-image" data-flex-basis="319px" data-flex-grow="133" height="794" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://raw.githubusercontent.com/kubernetes/sample-controller/master/docs/images/client-go-controller-interaction.jpeg" srcset="https://blog.uzimihsr.com/client-go-controller-interaction_4653964539945388113_hu_19115808137d0abd.jpg 800w, https://raw.githubusercontent.com/kubernetes/sample-controller/master/docs/images/client-go-controller-interaction.jpeg 1058w" width="1058"&gt;&lt;br&gt;
(画像は公式&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;のもの)&lt;/p&gt;
&lt;p&gt;この中で実際の&lt;code&gt;CRD&lt;/code&gt;(&lt;strong&gt;Foo&lt;/strong&gt;)の挙動を決めているのはProcess Itemの部分で,&lt;br&gt;
今回使用するコントローラーの場合は&lt;code&gt;syncHandler()&lt;/code&gt;&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;がそれにあたる.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;syncHandler()&lt;/code&gt;により, &lt;strong&gt;Foo&lt;/strong&gt;という&lt;code&gt;CRD&lt;/code&gt;は&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Specに&lt;code&gt;Deployment&lt;/code&gt;名とレプリカ数の情報を, Statusに利用可能なレプリカ数の情報を持つ(ここまでは&lt;code&gt;CRD&lt;/code&gt;で定義)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nginx&lt;/code&gt;コンテナ1台の&lt;code&gt;Pod&lt;/code&gt;をSpecで定義されたレプリカ数ぶん保持する&lt;code&gt;Deployment&lt;/code&gt;を管理する(&lt;code&gt;syncHandler()&lt;/code&gt;で定義)
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Deployment&lt;/code&gt;がなければ作り, &lt;code&gt;Deployment&lt;/code&gt;が保持する&lt;code&gt;Pod&lt;/code&gt;数(レプリカ数)がSpecで定義されたレプリカ数を満たすよう&lt;code&gt;Deployment&lt;/code&gt;を更新する&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Deployment&lt;/code&gt;の状態によってStatusを更新する(&lt;code&gt;syncHandler()&lt;/code&gt;で定義)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;という振る舞いをするリソースとなる.&lt;/p&gt;
&lt;p&gt;実際にカスタムコントローラーを動かしてみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# カスタムコントローラーのビルド&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go build -o sample-controller .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 有効なkubeconfigを指定して起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ./sample-controller -kubeconfig&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;/.kube/config
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;I0704 00:35:30.758496 &lt;span class="m"&gt;96780&lt;/span&gt; controller.go:115&lt;span class="o"&gt;]&lt;/span&gt; Setting up event handlers
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;I0704 00:35:30.758719 &lt;span class="m"&gt;96780&lt;/span&gt; controller.go:156&lt;span class="o"&gt;]&lt;/span&gt; Starting Foo controller
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;I0704 00:35:30.758731 &lt;span class="m"&gt;96780&lt;/span&gt; controller.go:159&lt;span class="o"&gt;]&lt;/span&gt; Waiting &lt;span class="k"&gt;for&lt;/span&gt; informer caches to sync
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;I0704 00:35:30.858942 &lt;span class="m"&gt;96780&lt;/span&gt; controller.go:164&lt;span class="o"&gt;]&lt;/span&gt; Starting workers
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;I0704 00:35:30.858973 &lt;span class="m"&gt;96780&lt;/span&gt; controller.go:170&lt;span class="o"&gt;]&lt;/span&gt; Started workers
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# (別のターミナルで実行)Fooリソースの作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f artifacts/examples/example-foo.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# カスタムコントローラー適用前とは異なりstatusに変化が生じている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get foo example-foo -o yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apiVersion: samplecontroller.k8s.io/v1alpha1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kind: Foo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; annotations:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubectl.kubernetes.io/last-applied-configuration: &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;apiVersion&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;samplecontroller.k8s.io/v1alpha1&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;kind&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;Foo&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;metadata&amp;#34;&lt;/span&gt;:&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;annotations&amp;#34;&lt;/span&gt;:&lt;span class="o"&gt;{}&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;example-foo&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;namespace&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;default&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;spec&amp;#34;&lt;/span&gt;:&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;deploymentName&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;example-foo&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;replicas&amp;#34;&lt;/span&gt;:1&lt;span class="o"&gt;}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; creationTimestamp: &lt;span class="s2"&gt;&amp;#34;2021-07-03T15:37:32Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; generation: &lt;span class="m"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: example-foo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; resourceVersion: &lt;span class="s2"&gt;&amp;#34;3127576&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; uid: 5bbab9a1-0baf-41b1-8f68-93be619a6048
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; deploymentName: example-foo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; replicas: &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;status:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; availableReplicas: &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Fooで定義されたDeploymentが作成されている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get deployment
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY UP-TO-DATE AVAILABLE AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;example-foo 1/1 &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 96s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Deploymentを削除してもカスタムコントローラーによりFooのspecを満たすようにすぐ再作成される&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl delete deployment example-foo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps &lt;span class="s2"&gt;&amp;#34;example-foo&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get deployment
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY UP-TO-DATE AVAILABLE AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;example-foo 1/1 &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 5s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# FooリソースのSpecをいじっても問題なく作成できる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat &lt;span class="s"&gt;&amp;lt;&amp;lt; EOF | kubectl apply -f -
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: samplecontroller.k8s.io/v1alpha1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: Foo
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; name: my-foo
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; deploymentName: my-foo
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; replicas: 10
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get foo my-foo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-foo 23s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get deployment my-foo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY UP-TO-DATE AVAILABLE AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-foo 10/10 &lt;span class="m"&gt;10&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt; 36s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;CRD&lt;/code&gt;(&lt;strong&gt;Foo&lt;/strong&gt;)で定義したリソースに対して所望の処理が行われることが確認できた.&lt;/p&gt;
&lt;p&gt;ここで面白いのはこのコントローラーがクラスタ外で稼働しているという点.&lt;/p&gt;
&lt;p&gt;各種リソースの操作は&lt;code&gt;Kubernetes API&lt;/code&gt;を通じて行われるので,&lt;br&gt;
APIに接続さえできればコントローラーの実体はどこで動いていても関係ないらしい.&lt;br&gt;
(デフォルトの&lt;code&gt;kube-controller-manager&lt;/code&gt;と同様に&lt;code&gt;Deployment&lt;/code&gt;として動かしても問題ないはず)&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;CRD&lt;/code&gt;とカスタムコントローラーのサンプルで遊んでみた.&lt;/p&gt;
&lt;p&gt;実際にコードを読んだりしてカスタムリソースとかコントローラーの仕組みがわかった気がする.&lt;/p&gt;
&lt;p&gt;時間があれば今回使ったカスタムコントローラーをクラスタ内で&lt;code&gt;Deployment&lt;/code&gt;として動かしてみたい.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="不機嫌なねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-07-12-kubernetes-crd-controller-practice/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2021-07-12-kubernetes-crd-controller-practice/sotochan_hu_ff0a156ee8846a1c.jpg 800w, https://blog.uzimihsr.com/post/2021-07-12-kubernetes-crd-controller-practice/sotochan_hu_1f79e695b53af9ff.jpg 1600w, https://blog.uzimihsr.com/post/2021-07-12-kubernetes-crd-controller-practice/sotochan_hu_91aaebdb3a8cde19.jpg 2400w, https://blog.uzimihsr.com/post/2021-07-12-kubernetes-crd-controller-practice/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a class="link" href="https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/" target="_blank" rel="noopener"
 &gt;https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/kubernetes/sample-controller/blob/master/docs/controller-client-go.md" target="_blank" rel="noopener"
 &gt;https://github.com/kubernetes/sample-controller/blob/master/docs/controller-client-go.md&lt;/a&gt;&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/kubernetes/sample-controller/blob/db75202208d77b1af79a3b04ee7612fb82564c6a/controller.go#L240-L319" target="_blank" rel="noopener"
 &gt;https://github.com/kubernetes/sample-controller/blob/db75202208d77b1af79a3b04ee7612fb82564c6a/controller.go#L240-L319&lt;/a&gt;&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>6月のそとちゃんまとめ(2021)</title><link>https://blog.uzimihsr.com/post/2021-07-08-sotochan/</link><pubDate>Thu, 08 Jul 2021 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2021-07-08-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan.jpg" alt="Featured image of post 6月のそとちゃんまとめ(2021)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%a4%e3%82%b9" &gt;イス&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%8a%e3%82%82%e3%81%a1%e3%82%83" &gt;おもちゃ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e7%9b%ae%e3%83%a4%e3%83%8b%e3%81%8c%e3%81%b2%e3%81%a9%e3%81%84" &gt;目ヤニがひどい&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="イス"&gt;イス
&lt;/h3&gt;&lt;p&gt;そとちゃんが以前にも増して仕事用のイスに座るようになった.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;仕事だめです &lt;a href="https://t.co/bINUc9pAab"&gt;pic.twitter.com/bINUc9pAab&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1400251435095183366?ref_src=twsrc%5Etfw"&gt;June 3, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;前はたまに座っている程度だったのが,&lt;br&gt;
今ではほぼ毎朝, というか俺が座っていないときは基本的にそとちゃんが座っている.&lt;br&gt;
おかげで仕事を始めるのがいつも遅くなる&amp;hellip;&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;もういる &lt;a href="https://t.co/qqDOhstuVR"&gt;pic.twitter.com/qqDOhstuVR&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1402774877929545732?ref_src=twsrc%5Etfw"&gt;June 9, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;おもちゃで気を引くと降りてくれるんだけど,&lt;br&gt;
休憩とかで一時的に離席するとその間にまた座っちゃう.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;昼休憩 &lt;a href="https://t.co/aYl0sp6zzq"&gt;pic.twitter.com/aYl0sp6zzq&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1407200949311991808?ref_src=twsrc%5Etfw"&gt;June 22, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;イスの座り心地が気に入っているのと,&lt;br&gt;
どうも&amp;quot;ここに座るとかまってもらえる&amp;quot;と覚えてしまったように思う.&lt;br&gt;
かしこい.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;またいる &lt;a href="https://t.co/7EBNE8qOkC"&gt;pic.twitter.com/7EBNE8qOkC&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1402981034803666945?ref_src=twsrc%5Etfw"&gt;June 10, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;でもたまに俺が座ってるときに&amp;quot;どけ!&amp;ldquo;って言ってる気もする.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;お昼寝終わっていきなりにゃんにゃん騒ぐから何事かと思ったら椅子を譲れということだった &lt;a href="https://t.co/b0jBCViXhH"&gt;pic.twitter.com/b0jBCViXhH&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1399302167043870729?ref_src=twsrc%5Etfw"&gt;May 31, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;なんでこんなに座りたがるのかはよくわからないが座っているときはとりあえず機嫌が良いので助かる.&lt;br&gt;
あとかわいい.😊&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ご満悦 &lt;a href="https://t.co/ciAjNIslWf"&gt;pic.twitter.com/ciAjNIslWf&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1409662067859025924?ref_src=twsrc%5Etfw"&gt;June 28, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;h3 id="おもちゃ"&gt;おもちゃ
&lt;/h3&gt;&lt;p&gt;またおもちゃをいくつか買ってしまった.&lt;/p&gt;
&lt;p&gt;まずはねこじゃらし.&lt;br&gt;
本物のエノコログサではなく人工のやつだけど, 割と喰い付きが良い.&lt;/p&gt;
&lt;p&gt;&lt;img alt="ねこじゃらし" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan01.jpg" srcset="https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan01_hu_955a4f399c6fb21d.jpg 800w, https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan01_hu_b782b7d215543277.jpg 1600w, https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan01_hu_663ae6a3bb64ee0.jpg 2400w, https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan01.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://www.doggyman.com/?p=showroom&amp;amp;id=655&amp;amp;toy=cat" target="_blank" rel="noopener"
 &gt;じゃれ猫　猫のお遊び草　２本セット&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;緑と茶色の2本入りで, そとちゃん的には緑色のほうが好きみたい.&lt;/p&gt;
&lt;p&gt;&lt;img alt="お気に召した" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan02.jpg" srcset="https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan02_hu_5743dc1c2d01553.jpg 800w, https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan02_hu_8f73f6591118c879.jpg 1600w, https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan02_hu_8e2827a9968ee60b.jpg 2400w, https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan02.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;これ&amp;quot;は&amp;quot;買ってよかった.&lt;/p&gt;
&lt;p&gt;次はこのニジマス.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ニジマス &lt;a href="https://t.co/voQLvW0Sr8"&gt;pic.twitter.com/voQLvW0Sr8&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1404029562271404035?ref_src=twsrc%5Etfw"&gt;June 13, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;&lt;a class="link" href="https://smack.official.ec/items/43643296" target="_blank" rel="noopener"
 &gt;じゃれぐるみ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;中にマタタビの枝と葉っぱがパンパンに詰まっているヤバいブツとの評判に期待して購入.&lt;br&gt;
評判通り, 俺の鼻でもわかるくらいにマタタビの匂いがプンプンする.&lt;/p&gt;
&lt;p&gt;またたびジャンキーのそとちゃんは大興奮!&lt;/p&gt;
&lt;p&gt;&amp;hellip;だったのは初日だけ.&lt;/p&gt;
&lt;p&gt;初めこそ本能むき出しでベロンベロンに舐めていたものの,&lt;br&gt;
表面のマタタビが薄くなってからはたまに匂いを嗅ぐくらいになった.&lt;/p&gt;
&lt;p&gt;&lt;img alt="もう狂わない" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan03.jpg" srcset="https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan03_hu_ab8450f161b02a7e.jpg 800w, https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan03_hu_7fed6347ed72562a.jpg 1600w, https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan03_hu_1948929b1381d902.jpg 2400w, https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan03.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;あとこのニジマスの重さが200gくらいあって,&lt;br&gt;
あんまり力が強くないそとちゃんには咥えて歩いたりするのも難しかったみたい.&lt;/p&gt;
&lt;p&gt;ちなみに今までまたたびをあげたときも匂いを嗅ぐよりベロベロ舐めて舐めてトリップすることが多かった気がする.&lt;br&gt;
鼻から吸うより経口摂取のほうが&amp;quot;効く&amp;quot;んだろうか&amp;hellip;?🤔&lt;/p&gt;
&lt;p&gt;最後は&lt;a class="link" href="https://www.doggyman.com/?p=showroom&amp;amp;id=2641&amp;amp;new=1" target="_blank" rel="noopener"
 &gt;猫ちゃんテンション爆アゲＢＯＸ&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;猫ちゃんテンション爆アゲBOXを買いました &lt;a href="https://t.co/xFrXfryxH1"&gt;pic.twitter.com/xFrXfryxH1&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1408013616746438656?ref_src=twsrc%5Etfw"&gt;June 24, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;開ける前からわかる圧倒的出オチ感.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;完成前からテンション爆アゲ &lt;a href="https://t.co/nnjzh6LRES"&gt;pic.twitter.com/nnjzh6LRES&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1408060569572102149?ref_src=twsrc%5Etfw"&gt;June 24, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;&amp;hellip;結局組み立て中がピークで,&lt;br&gt;
完成直後にちょっと遊んだだけで二度とテンションが爆アゲすることはなかった.&lt;/p&gt;
&lt;p&gt;&lt;img alt="猫ちゃんテンション爆アゲBOXの現在" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan04.jpg" srcset="https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan04_hu_58f431ced57e1e0.jpg 800w, https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan04_hu_a1fc862f4b3cb5bd.jpg 1600w, https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan04_hu_f7fae6ae45665a2d.jpg 2400w, https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan04.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;はい.😭&lt;/p&gt;
&lt;h3 id="目ヤニがひどい"&gt;目ヤニがひどい
&lt;/h3&gt;&lt;p&gt;ちょっと暖かくなって湿度も上がるとそとちゃんの右目の目ヤニがひどくなってくる.&lt;/p&gt;
&lt;p&gt;&lt;img alt="右目が痛々しい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan05.jpg" srcset="https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan05_hu_75ca82ae535c2ca4.jpg 800w, https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan05_hu_7b7af12c12868f5d.jpg 1600w, https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan05_hu_e93e60358dfd3c98.jpg 2400w, https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan05.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;そとちゃんは子猫のころの猫風邪の後遺症で右目の涙腺が詰まっていて,&lt;br&gt;
涙がそのまま目から溢れてしまって目ヤニができやすい.&lt;/p&gt;
&lt;p&gt;因果関係はよくわからないけど,&lt;br&gt;
寒くて乾燥していた時期に比べるとその症状がひどくなるように思う.&lt;/p&gt;
&lt;p&gt;&lt;img alt="かわいそう" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan06.jpg" srcset="https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan06_hu_3d256f977250066d.jpg 800w, https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan06_hu_155b575ca12f5e68.jpg 1600w, https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan06_hu_9b0c5f01d9ab8425.jpg 2400w, https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan06.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;お昼寝の後とかはちょっと痛々しいくらいに茶色い目やにが固まってしまうのがかわいそう.&lt;br&gt;
こまめに拭いてはいるのだが&amp;hellip;😭&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;梅雨の時期は部屋がじめじめするし,&lt;br&gt;
外の景色もどんよりしていてそとちゃんもあまり元気がなさそう.&lt;/p&gt;
&lt;p&gt;そとちゃんがだらだらごろごろしてるのもかわいいけど,&lt;br&gt;
このままだと運動不足になっちゃうのではやく梅雨明けしてほしい.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="目ヤニを拭かれるのもあまり好きじゃないねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan_hu_78956da22d52ede7.jpg 800w, https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan_hu_b074312c0c997ca9.jpg 1600w, https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan_hu_7a1d63111453bb3a.jpg 2400w, https://blog.uzimihsr.com/post/2021-07-08-sotochan/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>KubernetesのactiveDeadlineSecondsはJobとPodでちょっと違う</title><link>https://blog.uzimihsr.com/post/2021-06-12-kubernetes-active-deadline-seconds/</link><pubDate>Sat, 12 Jun 2021 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2021-06-12-kubernetes-active-deadline-seconds/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2021-06-12-kubernetes-active-deadline-seconds/sotochan.jpg" alt="Featured image of post KubernetesのactiveDeadlineSecondsはJobとPodでちょっと違う" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Kubernetes&lt;/code&gt;の&lt;code&gt;Pod&lt;/code&gt;と&lt;code&gt;Job&lt;/code&gt;にそれぞれ稼働時間の上限&lt;code&gt;activeDeadlineSeconds&lt;/code&gt;が指定できるけど, ちょっと挙動が違うので調べてみた.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;種類&lt;/th&gt;
 &lt;th&gt;&lt;code&gt;activeDeadlineSeconds&lt;/code&gt;超過時の挙動&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;Pod&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;ul&gt;&lt;li&gt;&lt;code&gt;kubelet&lt;/code&gt;によりコンテナがKILL(停止)される&lt;/li&gt;&lt;li&gt;&lt;code&gt;Kubernetes API&lt;/code&gt;上には&lt;code&gt;phase:Failed&lt;/code&gt;の&lt;code&gt;Pod&lt;/code&gt;が残る&lt;/li&gt;&lt;li&gt;&lt;code&gt;node&lt;/code&gt;上には停止したコンテナが残る&lt;/li&gt;&lt;li&gt;&lt;code&gt;Pod&lt;/code&gt;とコンテナはガベージコレクションのタイミングで削除される&lt;/li&gt;&lt;/ul&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;Job&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;ul&gt;&lt;li&gt;&lt;code&gt;Job Controller&lt;/code&gt;により&lt;code&gt;phase:Active&lt;/code&gt;の&lt;code&gt;Pod&lt;/code&gt;が明示的に削除される&lt;br&gt;(それ以外のphaseは残る)&lt;/li&gt;&lt;li&gt;&lt;code&gt;Kubernetes API&lt;/code&gt;上には&lt;code&gt;Job&lt;/code&gt;が残り, &lt;code&gt;Pod&lt;/code&gt;は削除される&lt;/li&gt;&lt;li&gt;&lt;code&gt;Pod&lt;/code&gt;が削除されるため, &lt;code&gt;node&lt;/code&gt;上のコンテナも削除される&lt;/li&gt;&lt;/ul&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Big Sur 11.2.3&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/editions/community/docker-ce-desktop-mac" target="_blank" rel="noopener"
 &gt;Docker Desktop for Mac&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Version 3.4.0&lt;/li&gt;
&lt;li&gt;Docker Engine Version 20.10.7&lt;/li&gt;
&lt;li&gt;Docker Compose Version 1.29.2&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/kubernetes-sigs/kind/" target="_blank" rel="noopener"
 &gt;kind&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;v0.11.0 go1.16.4 darwin/amd64&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/kubernetes/kubernetes" target="_blank" rel="noopener"
 &gt;Kubernetes&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;v1.21.1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="もくじ"&gt;もくじ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#pod%e3%81%aeactivedeadlineseconds" &gt;PodのactiveDeadlineSeconds&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#job%e3%81%aeactivedeadlineseconds" &gt;JobのactiveDeadlineSeconds&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e8%a9%b3%e3%81%97%e3%81%8f%e8%a6%8b%e3%81%a6%e3%81%bf%e3%82%8b" &gt;詳しく見てみる&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="podのactivedeadlineseconds"&gt;PodのactiveDeadlineSeconds
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Pod&lt;/code&gt;に設定できる&lt;code&gt;activeDeadlineSeconds&lt;/code&gt;の説明は次の通り.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl explain pod.spec.activeDeadlineSeconds
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;KIND: Pod
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VERSION: v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;FIELD: activeDeadlineSeconds &amp;lt;integer&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;DESCRIPTION:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Optional duration in seconds the pod may be active on the node relative to
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; StartTime before the system will actively try to mark it failed and &lt;span class="nb"&gt;kill&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; associated containers. Value must be a positive integer.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

 &lt;blockquote&gt;
 &lt;p&gt;(意訳) Podが開始してからactiveDeadlineSecondsより長く稼働してるとシステムがPodを失敗扱いにしてコンテナをKILLするよ&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;ということで適当な&lt;code&gt;Pod&lt;/code&gt;を作成して確認してみる.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/8fe740c4f1d04ecd616ff126384a0ed4.js"&gt;&lt;/script&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Pod作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f pod-01.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podが開始した時刻(startTime)の20秒後に削除されている(containerStatuses[].state.terminated.finishedAt)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# プロセスのexitCodeが137(シグナルを受けて終了)となっているので, &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# おそらくkubeletからコンテナランタイム(containerd)経由でSIGTERMが送られている.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pod -o yaml pod-01 &lt;span class="p"&gt;|&lt;/span&gt; yq -C r - &lt;span class="s2"&gt;&amp;#34;status&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;containerStatuses:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - containerID: containerd://f32f5d2995838397faaf0d2c4f312d941c1047001cb85e968fb4685cc75b5bda
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; image: docker.io/library/busybox:latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; imageID: docker.io/library/busybox@sha256:930490f97e5b921535c153e0e7110d251134cc4b72bbb8133c6a5065cc68580d
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; lastState: &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: main-container
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ready: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; restartCount: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; state:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; terminated:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; containerID: containerd://f32f5d2995838397faaf0d2c4f312d941c1047001cb85e968fb4685cc75b5bda
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; exitCode: &lt;span class="m"&gt;137&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; finishedAt: &lt;span class="s2"&gt;&amp;#34;2021-06-11T13:32:19Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; reason: Error
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; startedAt: &lt;span class="s2"&gt;&amp;#34;2021-06-11T13:31:31Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;message: Pod was active on the node longer than the specified deadline
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;phase: Failed
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;podIP: 10.244.0.36
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;podIPs:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - ip: 10.244.0.36
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;qosClass: Guaranteed
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;reason: DeadlineExceeded
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;startTime: &lt;span class="s2"&gt;&amp;#34;2021-06-11T13:31:29Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ログ(途中まで)は残っている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl logs pod-01 --timestamps
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2021-06-11T13:31:41.951165516Z &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2021-06-11T13:31:51.933749153Z &lt;span class="m"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2021-06-11T13:32:01.934770631Z &lt;span class="m"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2021-06-11T13:32:11.936129723Z &lt;span class="m"&gt;4&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;起動した時刻(&lt;code&gt;startTime&lt;/code&gt;)から&lt;code&gt;activeDeadlineSeconds&lt;/code&gt;で設定した秒数以上経過したあと(&lt;code&gt;containerStatuses[].state.terminated.finishedAt&lt;/code&gt;)に&lt;code&gt;Pod&lt;/code&gt;が&lt;code&gt;phase:Failed&lt;/code&gt;になっている.&lt;br&gt;
(たぶん同期のタイミングとかで少し遅れている)&lt;/p&gt;
&lt;p&gt;試しに&lt;code&gt;node&lt;/code&gt;上のコンテナの状態も確認してみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# kindなのでnodeもdockerコンテナとして動いている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;05f0d805c4dc kindest/node:v1.21.1 &lt;span class="s2"&gt;&amp;#34;/usr/local/bin/entr…&amp;#34;&lt;/span&gt; &lt;span class="m"&gt;25&lt;/span&gt; hours ago Up &lt;span class="m"&gt;25&lt;/span&gt; hours 127.0.0.1:53211-&amp;gt;6443/tcp kind-control-plane
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# nodeの中のコンテナをcontainerStatuses[].containerIDで探してみると確かにコンテナが残っている(プロセスは終了している)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container &lt;span class="nb"&gt;exec&lt;/span&gt; 05f0d805c4dc ctr --namespace k8s.io container ls &lt;span class="p"&gt;|&lt;/span&gt; grep f32f5d2995838397faaf0d2c4f312d941c1047001cb85e968fb4685cc75b5bda
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;f32f5d2995838397faaf0d2c4f312d941c1047001cb85e968fb4685cc75b5bda docker.io/library/busybox:latest io.containerd.runc.v2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;以上より,&lt;br&gt;
&lt;code&gt;Pod&lt;/code&gt;の稼働時間が&lt;code&gt;activeDeadlineSeconds&lt;/code&gt;を超えてしまった場合は&lt;code&gt;Pod&lt;/code&gt;の情報が&lt;code&gt;Kubernetes API&lt;/code&gt;に残り,&lt;br&gt;
&lt;code&gt;node&lt;/code&gt;にもコンテナの情報が残ることがわかった(プロセスはシグナルを受けて異常終了する).&lt;/p&gt;
&lt;h3 id="jobのactivedeadlineseconds"&gt;JobのactiveDeadlineSeconds
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Job&lt;/code&gt;にも&lt;code&gt;activeDeadlineSeconds&lt;/code&gt;を設定できる. 説明は以下の通り.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# JobのactiveDeadlineSecondsの説明&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl explain job.spec.activeDeadlineSeconds
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;KIND: Job
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VERSION: batch/v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;FIELD: activeDeadlineSeconds &amp;lt;integer&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;DESCRIPTION:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Specifies the duration in seconds relative to the startTime that the job
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; may be continuously active before the system tries to terminate it&lt;span class="p"&gt;;&lt;/span&gt; value
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; must be positive integer. If a Job is suspended &lt;span class="o"&gt;(&lt;/span&gt;at creation or through an
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; update&lt;span class="o"&gt;)&lt;/span&gt;, this timer will effectively be stopped and reset when the Job is
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; resumed again.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

 &lt;blockquote&gt;
 &lt;p&gt;(意訳) Jobが開始してからactiveDeadlineSecondsより長く稼働してるとシステムがJobを消すよ, アップデート(nodeの更新?)等でJobが中断した場合は再度稼働時間を数え直してくれるよ&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;&lt;code&gt;Pod&lt;/code&gt;のときと同様に&lt;code&gt;Job&lt;/code&gt;を作成して動作を確認してみる.&lt;br&gt;
コンテナの中身はだいたいおなじ.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/c9e326a88b0ed480cac38c504ea99b59.js"&gt;&lt;/script&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Job作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f job-01.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# DeadlineExceededによりJobがFailedになっている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get job -o yaml job-01 &lt;span class="p"&gt;|&lt;/span&gt; yq -C r - &lt;span class="s2"&gt;&amp;#34;status&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;conditions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - lastProbeTime: &lt;span class="s2"&gt;&amp;#34;2021-06-11T14:02:17Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; lastTransitionTime: &lt;span class="s2"&gt;&amp;#34;2021-06-11T14:02:17Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; message: Job was active longer than specified deadline
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; reason: DeadlineExceeded
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; status: &lt;span class="s2"&gt;&amp;#34;True&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; type: Failed
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;failed: &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;startTime: &lt;span class="s2"&gt;&amp;#34;2021-06-11T14:01:57Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podが見つからない...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -l job-name&lt;span class="o"&gt;=&lt;/span&gt;job-01
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;No resources found in default namespace.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;No resources found in default namespace.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Eventを確認するとPod(job-01-xntdw)が明示的に削除されている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl describe job job-01
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...&lt;span class="o"&gt;(&lt;/span&gt;省略&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Reason Age From Message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---- ------ ---- ---- -------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal SuccessfulCreate 7m44s job-controller Created pod: job-01-xntdw
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal SuccessfulDelete 7m24s job-controller Deleted pod: job-01-xntdw
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Warning DeadlineExceeded 7m24s job-controller Job was active longer than specified deadline
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 念の為nodeをimage名で探しても見つからない...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# (kindなのでnodeもdockerコンテナとして動いている)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container &lt;span class="nb"&gt;exec&lt;/span&gt; 05f0d805c4dc ctr --namespace k8s.io container ls &lt;span class="p"&gt;|&lt;/span&gt; grep -c busybox
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;今度は&lt;code&gt;Job&lt;/code&gt;は残っているものの&lt;code&gt;Pod&lt;/code&gt;が消えてしまった&amp;hellip;&lt;br&gt;
&lt;code&gt;Job&lt;/code&gt;の稼働時間が&lt;code&gt;activeDeadlineSeconds&lt;/code&gt;を超えた場合は&lt;code&gt;Pod&lt;/code&gt;が&lt;code&gt;Kubernetes API&lt;/code&gt;から削除され,&lt;br&gt;
&lt;code&gt;node&lt;/code&gt;上のコンテナも削除されてしまうらしい.&lt;/p&gt;
&lt;p&gt;ちなみに&lt;code&gt;Pod&lt;/code&gt;と&lt;code&gt;Job&lt;/code&gt;両方に&lt;code&gt;activeDeadlineSeconds&lt;/code&gt;を設定した場合はどうなるか?&lt;br&gt;
まずは&lt;code&gt;Pod&lt;/code&gt;の&lt;code&gt;activeDeadlineSeconds&lt;/code&gt; &amp;lt; &lt;code&gt;Job&lt;/code&gt;の&lt;code&gt;activeDeadlineSeconds&lt;/code&gt;の条件で試してみる.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/a8afa6424ace9ba0db6ecc796438d8cf.js"&gt;&lt;/script&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Job作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f job-02.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 今度はDeadlineExceededでなくBackoffLimitExceededによりJobがFailedになっている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get job -o yaml job-02 &lt;span class="p"&gt;|&lt;/span&gt; yq -C r - &lt;span class="s2"&gt;&amp;#34;status&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;conditions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - lastProbeTime: &lt;span class="s2"&gt;&amp;#34;2021-06-11T14:30:25Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; lastTransitionTime: &lt;span class="s2"&gt;&amp;#34;2021-06-11T14:30:25Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; message: Job has reached the specified backoff limit
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; reason: BackoffLimitExceeded
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; status: &lt;span class="s2"&gt;&amp;#34;True&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; type: Failed
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;failed: &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;startTime: &lt;span class="s2"&gt;&amp;#34;2021-06-11T14:30:05Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podが残っている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -l job-name&lt;span class="o"&gt;=&lt;/span&gt;job-02
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;job-02-d2w6v 0/1 Error &lt;span class="m"&gt;0&lt;/span&gt; 2m16s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# PodのactiveDeadlineSeconds超過時の挙動をしている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pod -o yaml job-02-d2w6v &lt;span class="p"&gt;|&lt;/span&gt; yq -C r - &lt;span class="s2"&gt;&amp;#34;status&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;containerStatuses:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - containerID: containerd://607cdbd019d8a1dc97473f6e62960ec68c0e70575b9c8dc7ac1fdfa18dab1dbd
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; image: docker.io/library/busybox:latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; imageID: docker.io/library/busybox@sha256:930490f97e5b921535c153e0e7110d251134cc4b72bbb8133c6a5065cc68580d
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; lastState: &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: main-container
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ready: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; restartCount: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; state:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; terminated:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; containerID: containerd://607cdbd019d8a1dc97473f6e62960ec68c0e70575b9c8dc7ac1fdfa18dab1dbd
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; exitCode: &lt;span class="m"&gt;137&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; finishedAt: &lt;span class="s2"&gt;&amp;#34;2021-06-11T14:30:55Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; reason: Error
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; startedAt: &lt;span class="s2"&gt;&amp;#34;2021-06-11T14:30:08Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;message: Pod was active on the node longer than the specified deadline
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;phase: Failed
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;podIP: 10.244.0.39
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;podIPs:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - ip: 10.244.0.39
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;qosClass: Guaranteed
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;reason: DeadlineExceeded
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;startTime: &lt;span class="s2"&gt;&amp;#34;2021-06-11T14:30:05Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ログが残っている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl logs job-02-d2w6v --timestamps
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2021-06-11T14:30:18.567995219Z &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2021-06-11T14:30:28.568766279Z &lt;span class="m"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2021-06-11T14:30:38.570408867Z &lt;span class="m"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2021-06-11T14:30:48.548898562Z &lt;span class="m"&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# nodeにコンテナも残っている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# (kindなのでnodeもdockerコンテナとして動いている)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container &lt;span class="nb"&gt;exec&lt;/span&gt; 05f0d805c4dc ctr --namespace k8s.io container ls &lt;span class="p"&gt;|&lt;/span&gt; grep 607cdbd019d8a1dc97473f6e62960ec68c0e70575b9c8dc7ac1fdfa18dab1dbd
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;607cdbd019d8a1dc97473f6e62960ec68c0e70575b9c8dc7ac1fdfa18dab1dbd docker.io/library/busybox:latest io.containerd.runc.v2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;おそらく&lt;code&gt;Pod&lt;/code&gt;の&lt;code&gt;activeDeadlineSeconds&lt;/code&gt;のほうが短いため, &lt;code&gt;Job&lt;/code&gt;の&lt;code&gt;activeDeadlineSeconds&lt;/code&gt;を超える前に&lt;code&gt;Pod&lt;/code&gt;が&lt;code&gt;phase:Failed&lt;/code&gt;になったように見える.&lt;/p&gt;
&lt;p&gt;次に&lt;code&gt;Pod&lt;/code&gt;の&lt;code&gt;activeDeadlineSeconds&lt;/code&gt; &amp;gt; &lt;code&gt;Job&lt;/code&gt;の&lt;code&gt;activeDeadlineSeconds&lt;/code&gt;の条件で試してみる.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/da825caf394db73fd9605a82eda285e6.js"&gt;&lt;/script&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Job作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f job-03.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 今度はDeadlineExceededでJobがFailedになっている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get job -o yaml job-03 &lt;span class="p"&gt;|&lt;/span&gt; yq -C r - &lt;span class="s2"&gt;&amp;#34;status&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;conditions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - lastProbeTime: &lt;span class="s2"&gt;&amp;#34;2021-06-11T14:47:00Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; lastTransitionTime: &lt;span class="s2"&gt;&amp;#34;2021-06-11T14:47:00Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; message: Job was active longer than specified deadline
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; reason: DeadlineExceeded
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; status: &lt;span class="s2"&gt;&amp;#34;True&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; type: Failed
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;failed: &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;startTime: &lt;span class="s2"&gt;&amp;#34;2021-06-11T14:46:40Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podが残っていない&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -l job-name&lt;span class="o"&gt;=&lt;/span&gt;job-03
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;No resources found in default namespace.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podが明示的に削除されている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl describe job job-03
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...&lt;span class="o"&gt;(&lt;/span&gt;省略&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Reason Age From Message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---- ------ ---- ---- -------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal SuccessfulCreate 83s job-controller Created pod: job-03-h66hc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal SuccessfulDelete 63s job-controller Deleted pod: job-03-h66hc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Warning DeadlineExceeded 63s job-controller Job was active longer than specified deadline
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# nodeを探してもコンテナが見つからない&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# (kindなのでnodeもdockerコンテナとして動いている)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container &lt;span class="nb"&gt;exec&lt;/span&gt; 05f0d805c4dc ctr --namespace k8s.io container ls &lt;span class="p"&gt;|&lt;/span&gt; grep -c busybox
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;今度は&lt;code&gt;Job&lt;/code&gt;の&lt;code&gt;activeDeadlineSeconds&lt;/code&gt;のほうが短いため, その時点で&lt;code&gt;phase:Active&lt;/code&gt;だった&lt;code&gt;Pod&lt;/code&gt;とコンテナが削除されてしまった.&lt;/p&gt;
&lt;h3 id="詳しく見てみる"&gt;詳しく見てみる
&lt;/h3&gt;&lt;p&gt;これらの挙動の違いはおそらく各オブジェクトを管理しているコンポーネントの違いから来ている.&lt;/p&gt;
&lt;h4 id="pod"&gt;Pod
&lt;/h4&gt;&lt;p&gt;&lt;code&gt;Pod&lt;/code&gt;は&lt;code&gt;kubelet&lt;/code&gt;によって管理されていて,&lt;br&gt;
&lt;code&gt;activeDeadlineSeconds&lt;/code&gt;を超過している場合は&lt;code&gt;activeDeadlineHandler.ShouldEvict()&lt;/code&gt;&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;と&lt;code&gt;Kubelet.generateAPIPodStatus()&lt;/code&gt;&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;によって&lt;code&gt;Kubernetes API&lt;/code&gt;上の&lt;code&gt;Pod&lt;/code&gt;が&lt;code&gt;phase:Failed&lt;/code&gt;にされ, &lt;code&gt;Kubelet.KillPod()&lt;/code&gt;&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;によってコンテナがKILLされるみたい.&lt;br&gt;
また, 公式Docsにも次のように書かれているあたり&lt;code&gt;kubelet&lt;/code&gt;が&lt;code&gt;Kubernetes API&lt;/code&gt;上から&lt;code&gt;Pod&lt;/code&gt;情報を削除するような処理はほぼないと思われる.&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;失敗したPodは人間またはcontrollerが明示的に削除するまで存在します。&lt;sup id="fnref:4"&gt;&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref"&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;(詳しく調べたところ&lt;code&gt;kubelet&lt;/code&gt;が&lt;code&gt;Kubernetes API&lt;/code&gt;上の&lt;code&gt;Pod&lt;/code&gt;情報を消してそうな部分が一つだけ見つかった&lt;sup id="fnref:5"&gt;&lt;a href="#fn:5" class="footnote-ref" role="doc-noteref"&gt;5&lt;/a&gt;&lt;/sup&gt;が, これは&lt;code&gt;Static Pod&lt;/code&gt;を扱う場合にしか呼び出されないため, 通常の&lt;code&gt;Pod&lt;/code&gt;には関係ないはず.)&lt;/p&gt;
&lt;p&gt;このため, &lt;code&gt;Pod&lt;/code&gt;が&lt;code&gt;activeDeadlineSeconds&lt;/code&gt;を超過したときの挙動は通常の&lt;code&gt;Pod&lt;/code&gt;が異常終了して&lt;code&gt;Failed&lt;/code&gt;となる場合と変わらず,&lt;br&gt;
やがてはガベージコレクションで削除される.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;activeDeadlineSeconds&lt;/code&gt;を超過しても&lt;code&gt;Pod&lt;/code&gt;とコンテナが残っていたのはこのためだと思う.&lt;/p&gt;
&lt;h4 id="job"&gt;Job
&lt;/h4&gt;&lt;p&gt;じゃあ&lt;code&gt;Job&lt;/code&gt;はどうなのかというと, こちらは&lt;code&gt;kubelet&lt;/code&gt;ではなく&lt;code&gt;Job Controller&lt;/code&gt;によって管理されている.&lt;br&gt;
&lt;code&gt;Job&lt;/code&gt;が&lt;code&gt;activeDeadlineSeconds&lt;/code&gt;を超過した場合は&lt;code&gt;Controller.syncJob()&lt;/code&gt;&lt;sup id="fnref:6"&gt;&lt;a href="#fn:6" class="footnote-ref" role="doc-noteref"&gt;6&lt;/a&gt;&lt;/sup&gt;と&lt;code&gt;RealPodControl.DeletePod()&lt;/code&gt;&lt;sup id="fnref:7"&gt;&lt;a href="#fn:7" class="footnote-ref" role="doc-noteref"&gt;7&lt;/a&gt;&lt;/sup&gt;によって&lt;code&gt;Kubernetes API&lt;/code&gt;を呼び出してその時点で&lt;code&gt;Phase: Active&lt;/code&gt;な&lt;code&gt;Pod&lt;/code&gt;を明示的に削除するみたい.&lt;/p&gt;
&lt;p&gt;したがって, &lt;code&gt;backoffLimit&lt;/code&gt;の設定により&lt;code&gt;Job&lt;/code&gt;の&lt;code&gt;Pod&lt;/code&gt;が失敗しても再度作成されるような場合は最後の1つだけがAPI上から削除される.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/0b790e3c95afc5eecbbbe1a35b1d6944.js"&gt;&lt;/script&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Job作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f job-04.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 今度はDeadlineExceededによりJobがFailedになっている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get job -o yaml job-04 &lt;span class="p"&gt;|&lt;/span&gt; yq -C r - &lt;span class="s2"&gt;&amp;#34;status&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;conditions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - lastProbeTime: &lt;span class="s2"&gt;&amp;#34;2021-06-12T00:35:57Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; lastTransitionTime: &lt;span class="s2"&gt;&amp;#34;2021-06-12T00:35:57Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; message: Job was active longer than specified deadline
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; reason: DeadlineExceeded
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; status: &lt;span class="s2"&gt;&amp;#34;True&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; type: Failed
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;failed: &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;startTime: &lt;span class="s2"&gt;&amp;#34;2021-06-12T00:35:07Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podが1つ(自身のactiveDeadlineSecondsによりphase:Failedとなったもの)だけ残っている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -l job-name&lt;span class="o"&gt;=&lt;/span&gt;job-04
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;job-04-vsw8x 0/1 Error &lt;span class="m"&gt;0&lt;/span&gt; 2m43s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# JobのactiveDeadlineSeconds超過時にActiveだったPod(job-04-5bjnz)が明示的に削除されている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl describe job job-04
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...&lt;span class="o"&gt;(&lt;/span&gt;省略&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Reason Age From Message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---- ------ ---- ---- -------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal SuccessfulCreate 2m59s job-controller Created pod: job-04-vsw8x
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal SuccessfulCreate 2m19s job-controller Created pod: job-04-5bjnz
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal SuccessfulDelete 2m9s job-controller Deleted pod: job-04-5bjnz
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Warning DeadlineExceeded 2m9s &lt;span class="o"&gt;(&lt;/span&gt;x2 over 2m9s&lt;span class="o"&gt;)&lt;/span&gt; job-controller Job was active longer than specified deadline
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# nodeを探してもコンテナは1つだけ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# (kindなのでnodeもdockerコンテナとして動いている)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container &lt;span class="nb"&gt;exec&lt;/span&gt; 05f0d805c4dc ctr --namespace k8s.io container ls &lt;span class="p"&gt;|&lt;/span&gt; grep -c busybox
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Pod&lt;/code&gt;と&lt;code&gt;Job&lt;/code&gt;の&lt;code&gt;activeDeadlineSeconds&lt;/code&gt;の違いを確認した.&lt;/p&gt;
&lt;p&gt;個人的には&lt;code&gt;Pod&lt;/code&gt;が消えちゃうと後から処理に時間がかかった理由がわからなくなっちゃうので,&lt;br&gt;
単純な&lt;code&gt;Job&lt;/code&gt;の場合は&lt;code&gt;Pod&lt;/code&gt;の&lt;code&gt;activeDeadlineSeconds&lt;/code&gt;を設定するほうが良い気がする.&lt;/p&gt;
&lt;p&gt;コードを読むのは疲れる&amp;hellip;&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="不機嫌なねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-06-12-kubernetes-active-deadline-seconds/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2021-06-12-kubernetes-active-deadline-seconds/sotochan_hu_2c7770d139f808b2.jpg 800w, https://blog.uzimihsr.com/post/2021-06-12-kubernetes-active-deadline-seconds/sotochan_hu_3180e220f2f79b2d.jpg 1600w, https://blog.uzimihsr.com/post/2021-06-12-kubernetes-active-deadline-seconds/sotochan_hu_f491ec6713a34bba.jpg 2400w, https://blog.uzimihsr.com/post/2021-06-12-kubernetes-active-deadline-seconds/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/kubernetes/kubernetes/blob/v1.21.1/pkg/kubelet/active_deadline.go#L63-L98" target="_blank" rel="noopener"
 &gt;https://github.com/kubernetes/kubernetes/blob/v1.21.1/pkg/kubelet/active_deadline.go#L63-L98&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/kubernetes/kubernetes/blob/v1.21.1/pkg/kubelet/kubelet_pods.go#L1526-L1530" target="_blank" rel="noopener"
 &gt;https://github.com/kubernetes/kubernetes/blob/v1.21.1/pkg/kubelet/kubelet_pods.go#L1526-L1530&lt;/a&gt;&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/kubernetes/kubernetes/blob/v1.21.1/pkg/kubelet/kubelet_pods.go#L846-L865" target="_blank" rel="noopener"
 &gt;https://github.com/kubernetes/kubernetes/blob/v1.21.1/pkg/kubelet/kubelet_pods.go#L846-L865&lt;/a&gt;&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:4"&gt;
&lt;p&gt;&lt;a class="link" href="https://kubernetes.io/ja/docs/concepts/workloads/pods/pod-lifecycle/#pod-garbage-collection" target="_blank" rel="noopener"
 &gt;https://kubernetes.io/ja/docs/concepts/workloads/pods/pod-lifecycle/#pod-garbage-collection&lt;/a&gt;&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:5"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/kubernetes/kubernetes/blob/v1.21.1/pkg/kubelet/pod/mirror_client.go#L109-L137" target="_blank" rel="noopener"
 &gt;https://github.com/kubernetes/kubernetes/blob/v1.21.1/pkg/kubelet/pod/mirror_client.go#L109-L137&lt;/a&gt;&amp;#160;&lt;a href="#fnref:5" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:6"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/kubernetes/kubernetes/blob/v1.21.1/pkg/controller/job/job_controller.go#L526-L541" target="_blank" rel="noopener"
 &gt;https://github.com/kubernetes/kubernetes/blob/v1.21.1/pkg/controller/job/job_controller.go#L526-L541&lt;/a&gt;&amp;#160;&lt;a href="#fnref:6" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:7"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/kubernetes/kubernetes/blob/v1.21.1/pkg/controller/controller_utils.go#L597-L614" target="_blank" rel="noopener"
 &gt;https://github.com/kubernetes/kubernetes/blob/v1.21.1/pkg/controller/controller_utils.go#L597-L614&lt;/a&gt;&amp;#160;&lt;a href="#fnref:7" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>クライアント認証のかかったPrometheusにGrafanaでアクセスする</title><link>https://blog.uzimihsr.com/post/2021-06-07-grafana-prometheus-client-auth/</link><pubDate>Mon, 07 Jun 2021 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2021-06-07-grafana-prometheus-client-auth/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2021-06-07-grafana-prometheus-client-auth/sotochan.jpg" alt="Featured image of post クライアント認証のかかったPrometheusにGrafanaでアクセスする" /&gt;&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2021-06-05-prometheus-client-auth/" target="_blank" rel="noopener"
 &gt;クライアント認証がかかったPrometheus&lt;/a&gt;に&lt;code&gt;Grafana&lt;/code&gt;でアクセスした.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Prometheus&lt;/code&gt;への認証に必要な情報(証明書と秘密鍵)を&lt;code&gt;Grafana&lt;/code&gt;に持たせることができるので,&lt;br&gt;
&lt;code&gt;Grafana&lt;/code&gt;へアクセスする権限さえあればクライアント認証のかかった&lt;code&gt;Prometheus&lt;/code&gt;のメトリクスが閲覧できるようになる.&lt;/p&gt;
&lt;p&gt;&lt;img alt="クライアント認証のかかったPrometheus+nginxにGrafanaからアクセスする" class="gallery-image" data-flex-basis="549px" data-flex-grow="229" height="927" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-06-07-grafana-prometheus-client-auth/component03.png" srcset="https://blog.uzimihsr.com/post/2021-06-07-grafana-prometheus-client-auth/component03_hu_2a6b303c5a6e624d.png 800w, https://blog.uzimihsr.com/post/2021-06-07-grafana-prometheus-client-auth/component03_hu_edb574bb946a9aac.png 1600w, https://blog.uzimihsr.com/post/2021-06-07-grafana-prometheus-client-auth/component03.png 2123w" width="2123"&gt;&lt;/p&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Big Sur 11.2.3&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/editions/community/docker-ce-desktop-mac" target="_blank" rel="noopener"
 &gt;Docker Desktop for Mac&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Version 3.3.1&lt;/li&gt;
&lt;li&gt;Docker Engine Version 20.10.5&lt;/li&gt;
&lt;li&gt;Docker Compose Version 1.29.0&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/prometheus/prometheus" target="_blank" rel="noopener"
 &gt;Prometheus&lt;/a&gt; (Docker)
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/layers/prom/prometheus/v2.27.1/images/sha256-3f7925343769a2c1c482ae812dd138ad38d156527781eb0ca6dbdda2494bd0e5?context=explore" target="_blank" rel="noopener"
 &gt;v2.27.1&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/nginx/nginx" target="_blank" rel="noopener"
 &gt;nginx&lt;/a&gt; (Docker)
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/layers/nginx/library/nginx/1.21.0/images/sha256-db7800fc7ee1e04e6fadd7d993e6030d49d4a99b1581d286478e068a62416097?context=explore" target="_blank" rel="noopener"
 &gt;1.21.0&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/grafana/grafana" target="_blank" rel="noopener"
 &gt;Grafana&lt;/a&gt; (Docker)
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/layers/grafana/grafana/7.5.7/images/sha256-cff19a140474ef840f09997768681a2dd99ebbbb43abed806dfe6b5420e706c7?context=explore" target="_blank" rel="noopener"
 &gt;7.5.7&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%af%e3%83%a9%e3%82%a4%e3%82%a2%e3%83%b3%e3%83%88%e8%aa%8d%e8%a8%bc%e3%82%92%e3%81%8b%e3%81%91%e3%81%9fprometheus%e3%81%ae%e6%ba%96%e5%82%99" &gt;クライアント認証をかけたPrometheusの準備&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#grafana%e3%81%a7%e3%82%af%e3%83%a9%e3%82%a4%e3%82%a2%e3%83%b3%e3%83%88%e8%aa%8d%e8%a8%bc%e3%82%92%e7%aa%81%e7%a0%b4%e3%81%99%e3%82%8b" &gt;Grafanaでクライアント認証を突破する&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="クライアント認証をかけたprometheusの準備"&gt;クライアント認証をかけたPrometheusの準備
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2021-06-05-prometheus-client-auth/" target="_blank" rel="noopener"
 &gt;Prometheusにクライアント認証をかける&lt;/a&gt;で用意したものを使う.&lt;br&gt;
秘密鍵や証明書もそのまま同じもの.&lt;br&gt;
(ただし&lt;code&gt;Grafana&lt;/code&gt;にはクライアント認証をかけないのでMacに証明書を読み込ませる必要はなし)&lt;/p&gt;
&lt;p&gt;今回は&lt;code&gt;nginx&lt;/code&gt;を挟んで使う方法を採用するが, &lt;code&gt;Prometheus&lt;/code&gt;単独でクライアント認証をかけた場合でも&lt;code&gt;Grafana&lt;/code&gt;の設定は同じはず.&lt;/p&gt;
&lt;h3 id="grafanaでクライアント認証を突破する"&gt;Grafanaでクライアント認証を突破する
&lt;/h3&gt;&lt;p&gt;&lt;img alt="Grafanaでクライアント認証を突破する" class="gallery-image" data-flex-basis="549px" data-flex-grow="229" height="927" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-06-07-grafana-prometheus-client-auth/component03.png" srcset="https://blog.uzimihsr.com/post/2021-06-07-grafana-prometheus-client-auth/component03_hu_2a6b303c5a6e624d.png 800w, https://blog.uzimihsr.com/post/2021-06-07-grafana-prometheus-client-auth/component03_hu_edb574bb946a9aac.png 1600w, https://blog.uzimihsr.com/post/2021-06-07-grafana-prometheus-client-auth/component03.png 2123w" width="2123"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Grafana&lt;/code&gt;はDataSource(&lt;code&gt;Prometheus&lt;/code&gt;)への認証方法としてクライアント認証に対応しているので,&lt;br&gt;
&lt;strong&gt;クライアント証明書&lt;/strong&gt;と&lt;strong&gt;クライアント秘密鍵&lt;/strong&gt;(クライアントの身元を証明するのに使用),&lt;br&gt;
&lt;strong&gt;サーバー認証局の証明書&lt;/strong&gt;(サーバーの身元を確認するのに使用)を持たせる.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Grafana&lt;/code&gt;がDataSourceへクライアント認証で接続するための設定は&lt;code&gt;datasource.yaml&lt;/code&gt;&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;に記述する.&lt;br&gt;
証明書と秘密鍵をベタ書きしたくないので, &lt;code&gt;File provider&lt;/code&gt;&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;を使ってファイル名を指定して指定して読み込むようにした.&lt;br&gt;
(このあたりはissue&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;を参考にした)&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/79888538348ecad2037da93cf6bfbfbe.js"&gt;&lt;/script&gt;
&lt;p&gt;各種ファイルを&lt;code&gt;Grafana&lt;/code&gt;のコンテナにマウントして起動する.&lt;br&gt;
(今回はProemtheus+nginxの構成にしているが, Prometheus単独でクライアント認証をかけた場合でもGrafana側の設定は同じになる)&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/4f42eec9ee61ad7a2b502b6a53c94e71.js"&gt;&lt;/script&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ディレクトリの状態(使わないものを消している)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls -1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;client-ca-cert.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;client-cert.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;client-private-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;datasource.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker-compose.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https.conf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;server-cert.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;server-private-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# コンテナを起動する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker compose up -d --force-recreate --remove-orphans&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;今回&lt;code&gt;Grafana&lt;/code&gt;は単独で動かしている(HTTPS化もしていない)のでChromeで&lt;a class="link" href="http://localhost:3000" target="_blank" rel="noopener"
 &gt;http://localhost:3000&lt;/a&gt;を開く.&lt;br&gt;
(&lt;code&gt;Grafana&lt;/code&gt;はデフォルトでBasic認証がかかっているので, admin:adminで突破する)&lt;/p&gt;
&lt;p&gt;&lt;img alt="DataSourceの状態. 手動で設定する場合もこんな感じでやればOK" class="gallery-image" data-flex-basis="207px" data-flex-grow="86" height="2083" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-06-07-grafana-prometheus-client-auth/sc12.png" srcset="https://blog.uzimihsr.com/post/2021-06-07-grafana-prometheus-client-auth/sc12_hu_c4c6ca4902193637.png 800w, https://blog.uzimihsr.com/post/2021-06-07-grafana-prometheus-client-auth/sc12_hu_80330691ffb6e273.png 1600w, https://blog.uzimihsr.com/post/2021-06-07-grafana-prometheus-client-auth/sc12.png 1800w" width="1800"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="メトリクスも正常に取得できている" class="gallery-image" data-flex-basis="384px" data-flex-grow="160" height="1800" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-06-07-grafana-prometheus-client-auth/sc13.png" srcset="https://blog.uzimihsr.com/post/2021-06-07-grafana-prometheus-client-auth/sc13_hu_15f5227069095e62.png 800w, https://blog.uzimihsr.com/post/2021-06-07-grafana-prometheus-client-auth/sc13_hu_78310644bb90dfe6.png 1600w, https://blog.uzimihsr.com/post/2021-06-07-grafana-prometheus-client-auth/sc13_hu_15b183063d24327a.png 2400w, https://blog.uzimihsr.com/post/2021-06-07-grafana-prometheus-client-auth/sc13.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Grafana&lt;/code&gt;で&lt;code&gt;nginx&lt;/code&gt;のクライアント認証を突破し,&lt;br&gt;
&lt;code&gt;Prometheus&lt;/code&gt;のメトリクスを取得できることが確認できた.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# コンテナを終了しておく&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker compose down&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Grafana&lt;/code&gt;でクライアント認証のかかった&lt;code&gt;Prometheus&lt;/code&gt;からメトリクスを習得する流れを確認した.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Prometheus&lt;/code&gt;のセキュリティまわりはこれで一安心な感じもするが, 要件によっては&lt;code&gt;Grafana&lt;/code&gt;にも別の認証をかけたほうがいいかも&amp;hellip;&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="見下ろしてくるねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-06-07-grafana-prometheus-client-auth/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2021-06-07-grafana-prometheus-client-auth/sotochan_hu_b9a481da12ed233.jpg 800w, https://blog.uzimihsr.com/post/2021-06-07-grafana-prometheus-client-auth/sotochan_hu_22f54132097d0f1f.jpg 1600w, https://blog.uzimihsr.com/post/2021-06-07-grafana-prometheus-client-auth/sotochan_hu_c829eed637a5dbfa.jpg 2400w, https://blog.uzimihsr.com/post/2021-06-07-grafana-prometheus-client-auth/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a class="link" href="https://grafana.com/docs/grafana/latest/administration/provisioning/#data-sources" target="_blank" rel="noopener"
 &gt;https://grafana.com/docs/grafana/latest/administration/provisioning/#data-sources&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;a class="link" href="https://grafana.com/docs/grafana/latest/administration/configuration/#file-provider" target="_blank" rel="noopener"
 &gt;https://grafana.com/docs/grafana/latest/administration/configuration/#file-provider&lt;/a&gt;&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/grafana/grafana/issues/25945" target="_blank" rel="noopener"
 &gt;https://github.com/grafana/grafana/issues/25945&lt;/a&gt;&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Prometheusにクライアント認証をかける</title><link>https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/</link><pubDate>Sat, 05 Jun 2021 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sotochan.jpg" alt="Featured image of post Prometheusにクライアント認証をかける" /&gt;&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Prometheus&lt;/code&gt;に&lt;a class="link" href="https://uzimihsr.github.io/post/2020-06-26-client-certification-practice/" target="_blank" rel="noopener"
 &gt;クライアント認証&lt;/a&gt;をかけてみた.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Prometheus&lt;/code&gt;単独でクライアント認証を行う方法と,&lt;br&gt;
クライアント認証をかけた&lt;code&gt;nginx&lt;/code&gt;でリバースプロキシする方法をそれぞれ試した.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Prometheus&lt;/code&gt;, &lt;code&gt;nginx&lt;/code&gt;はすべて&lt;code&gt;Docker Desktop for Mac&lt;/code&gt;で動かした.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Prometheus単独でクライアント認証する" class="gallery-image" data-flex-basis="857px" data-flex-grow="357" height="533" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/component01.png" srcset="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/component01_hu_94947a40abe5383c.png 800w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/component01_hu_84aadf9e20712897.png 1600w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/component01.png 1905w" width="1905"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Prometheus+nginxでクライアント認証する" class="gallery-image" data-flex-basis="955px" data-flex-grow="398" height="533" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/component02.png" srcset="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/component02_hu_3601d59dde5c9eb7.png 800w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/component02_hu_8021726e36e0afa2.png 1600w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/component02.png 2123w" width="2123"&gt;&lt;/p&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Big Sur 11.2.3&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/editions/community/docker-ce-desktop-mac" target="_blank" rel="noopener"
 &gt;Docker Desktop for Mac&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Version 3.3.1&lt;/li&gt;
&lt;li&gt;Docker Engine Version 20.10.5&lt;/li&gt;
&lt;li&gt;Docker Compose Version 1.29.0&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/prometheus/prometheus" target="_blank" rel="noopener"
 &gt;Prometheus&lt;/a&gt; (Docker)
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/layers/prom/prometheus/v2.27.1/images/sha256-3f7925343769a2c1c482ae812dd138ad38d156527781eb0ca6dbdda2494bd0e5?context=explore" target="_blank" rel="noopener"
 &gt;v2.27.1&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/nginx/nginx" target="_blank" rel="noopener"
 &gt;nginx&lt;/a&gt; (Docker)
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/layers/nginx/library/nginx/1.21.0/images/sha256-db7800fc7ee1e04e6fadd7d993e6030d49d4a99b1581d286478e068a62416097?context=explore" target="_blank" rel="noopener"
 &gt;1.21.0&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/openssl/openssl" target="_blank" rel="noopener"
 &gt;OpenSSL&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;1.1.1d&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e5%90%84%e7%a8%ae%e7%a7%98%e5%af%86%e9%8d%b5%e3%81%a8%e8%a8%bc%e6%98%8e%e6%9b%b8%e3%81%ae%e4%bd%9c%e6%88%90" &gt;各種秘密鍵と証明書の作成&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#prometheus%e5%8d%98%e7%8b%ac%e3%81%a7%e3%82%af%e3%83%a9%e3%82%a4%e3%82%a2%e3%83%b3%e3%83%88%e8%aa%8d%e8%a8%bc%e3%82%92%e3%81%8b%e3%81%91%e3%82%8b" &gt;Prometheus単独でクライアント認証をかける&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#prometheusnginx%e3%81%a7%e3%82%af%e3%83%a9%e3%82%a4%e3%82%a2%e3%83%b3%e3%83%88%e8%aa%8d%e8%a8%bc%e3%82%92%e3%81%8b%e3%81%91%e3%82%8b" &gt;Prometheus+nginxでクライアント認証をかける&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="各種秘密鍵と証明書の作成"&gt;各種秘密鍵と証明書の作成
&lt;/h3&gt;&lt;p&gt;まずはクライアント認証に必要なサーバーとクライアントの秘密鍵+証明書を&lt;code&gt;OpenSSL&lt;/code&gt;で作成する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# nginxコンテナを起動してOpenSSLを使う&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run --rm -it -v&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt;&lt;span class="s2"&gt;:/workdir&amp;#34;&lt;/span&gt; -w&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/workdir&amp;#34;&lt;/span&gt; --entrypoint&lt;span class="o"&gt;=&lt;/span&gt;/bin/bash nginx:1.21.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# サーバー用のオレオレ証明書を作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ホスト名はprometheus.hogehoge.comとしてSANsの設定もしておく(Chromeで開くため)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl genpkey -algorithm RSA -out server-private-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl req -x509 -key server-private-key.pem -out server-cert.pem -addext &lt;span class="s1"&gt;&amp;#39;subjectAltName = DNS:prometheus.hogehoge.com&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Country Name &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; letter code&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;AU&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;State or Province Name &lt;span class="o"&gt;(&lt;/span&gt;full name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Some-State&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Locality Name &lt;span class="o"&gt;(&lt;/span&gt;eg, city&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Organization Name &lt;span class="o"&gt;(&lt;/span&gt;eg, company&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Internet Widgits Pty Ltd&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Organizational Unit Name &lt;span class="o"&gt;(&lt;/span&gt;eg, section&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Common Name &lt;span class="o"&gt;(&lt;/span&gt;e.g. server FQDN or YOUR name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:prometheus.hogehoge.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Email Address &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# クライアント認証局の証明書を作成(オレオレ認証局)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl genpkey -algorithm RSA -out client-ca-private-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl req -x509 -key client-ca-private-key.pem -out client-ca-cert.pem -days &lt;span class="m"&gt;365&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Country Name &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; letter code&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;AU&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;State or Province Name &lt;span class="o"&gt;(&lt;/span&gt;full name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Some-State&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Locality Name &lt;span class="o"&gt;(&lt;/span&gt;eg, city&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Organization Name &lt;span class="o"&gt;(&lt;/span&gt;eg, company&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Internet Widgits Pty Ltd&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Organizational Unit Name &lt;span class="o"&gt;(&lt;/span&gt;eg, section&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Common Name &lt;span class="o"&gt;(&lt;/span&gt;e.g. server FQDN or YOUR name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:client-ca
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Email Address &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 署名のための準備&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mkdir -p demoCA/newcerts &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; touch demoCA/index.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="m"&gt;01&lt;/span&gt; &amp;gt; ./demoCA/serial
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# クライアント証明書を作成(クライアント認証局で署名する)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# PKCS#12形式のものも作成しておく&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl genpkey -algorithm RSA -out client-private-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl req -new -key client-private-key.pem -out client-csr.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Country Name &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; letter code&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;AU&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;State or Province Name &lt;span class="o"&gt;(&lt;/span&gt;full name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Some-State&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Locality Name &lt;span class="o"&gt;(&lt;/span&gt;eg, city&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Organization Name &lt;span class="o"&gt;(&lt;/span&gt;eg, company&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Internet Widgits Pty Ltd&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Organizational Unit Name &lt;span class="o"&gt;(&lt;/span&gt;eg, section&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Common Name &lt;span class="o"&gt;(&lt;/span&gt;e.g. server FQDN or YOUR name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:client
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Email Address &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;A challenge password &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;An optional company name &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl ca -in client-csr.pem -out client-cert.pem -keyfile client-ca-private-key.pem -cert client-ca-cert.pem -days &lt;span class="m"&gt;365&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Sign the certificate? &lt;span class="o"&gt;[&lt;/span&gt;y/n&lt;span class="o"&gt;]&lt;/span&gt;:y
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;1&lt;/span&gt; out of &lt;span class="m"&gt;1&lt;/span&gt; certificate requests certified, commit? &lt;span class="o"&gt;[&lt;/span&gt;y/n&lt;span class="o"&gt;]&lt;/span&gt;y
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl pkcs12 -export -clcerts -in client-cert.pem -inkey client-private-key.pem -out client-cert.p12
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Enter Export Password: fugafuga
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Verifying - Enter Export Password: fugafuga
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# コンテナから出ると鍵と証明書が作成されている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls -1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;client-ca-cert.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;client-ca-private-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;client-cert.p12
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;client-cert.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;client-csr.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;client-private-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;demoCA
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;server-cert.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;server-private-key.pem&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;今回は鍵と証明書をたくさん使っていて後で混乱しそうなのでここに内容をまとめておく.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;サーバー認証局の証明書&lt;/strong&gt;(&lt;code&gt;server-cert.pem&lt;/code&gt;)
&lt;ul&gt;
&lt;li&gt;サーバー証明書に署名した認証局の証明書&lt;/li&gt;
&lt;li&gt;今回はオレオレ証明書なのでサーバー証明書と同一だが, ちゃんとした認証局(CA)によってサーバー証明書を発行した場合は認証局の証明書を使う.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;サーバー認証局の秘密鍵(&lt;code&gt;server-private-key.pem&lt;/code&gt;)
&lt;ul&gt;
&lt;li&gt;サーバー証明書に署名した認証局の秘密鍵&lt;/li&gt;
&lt;li&gt;今回はオレオレ証明書なのでサーバー秘密鍵と同一&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;このあとは使わない&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;サーバー証明書&lt;/strong&gt;(&lt;code&gt;server-cert.pem&lt;/code&gt;)
&lt;ul&gt;
&lt;li&gt;サーバー(Prometheus)の身元を証明する証明書. 今回はオレオレ証明書を使う.&lt;/li&gt;
&lt;li&gt;ホスト名はprometheus.hogehoge.comとした(オレオレ証明書なので任意の名前)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;サーバー秘密鍵&lt;/strong&gt;(&lt;code&gt;server-private-key.pem&lt;/code&gt;)
&lt;ul&gt;
&lt;li&gt;サーバー(Prometheus)に持たせる秘密鍵&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;クライアント認証局の証明書&lt;/strong&gt;(&lt;code&gt;client-ca-cert.pem&lt;/code&gt;)
&lt;ul&gt;
&lt;li&gt;クライアント証明書に署名した認証局の証明書&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;クライアント認証局の秘密鍵(&lt;code&gt;client-ca-private-key.pem&lt;/code&gt;)
&lt;ul&gt;
&lt;li&gt;クライアント証明書に署名した認証局の秘密鍵&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;このあとは使わない&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;クライアント証明書&lt;/strong&gt;(&lt;code&gt;client-cert.pem&lt;/code&gt;, &lt;code&gt;client-cert.p12&lt;/code&gt;)
&lt;ul&gt;
&lt;li&gt;クライアントの身元を証明する証明書&lt;/li&gt;
&lt;li&gt;クライアント(Prometheus, Grafana, User)ごとに分けてもいいけど, 面倒なので全部同じものを使う&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;クライアント秘密鍵&lt;/strong&gt;(&lt;code&gt;client-private-key.pem&lt;/code&gt;)
&lt;ul&gt;
&lt;li&gt;クライアントに持たせる秘密鍵&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;クライアントのCSR(&lt;code&gt;client-csr.pem&lt;/code&gt;)
&lt;ul&gt;
&lt;li&gt;クライアント証明書を発行するときに使ったCSR&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;このあとは使わない&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ついでにブラウザでも動作確認できるように, Macで&lt;strong&gt;サーバー証明書&lt;/strong&gt;を信頼する設定と&lt;strong&gt;クライアント証明書&lt;/strong&gt;を持たせる設定を行う.&lt;/p&gt;
&lt;p&gt;Finderから&lt;code&gt;client-cert.p12&lt;/code&gt;と&lt;code&gt;server-cert.pem&lt;/code&gt;をそれぞれダブルクリックして,&lt;br&gt;
証明書を&lt;code&gt;キーチェーンアクセス&lt;/code&gt;で信頼するように設定する.&lt;/p&gt;
&lt;p&gt;&lt;img alt=".p12を開くとパスワードを求められるので, 作成時に指定したもの(fugafuga)を入力する" class="gallery-image" data-flex-basis="515px" data-flex-grow="214" height="518" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc01.png" srcset="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc01_hu_fcdb4c025f5b37dd.png 800w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc01.png 1112w" width="1112"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="クライアント証明書の信頼設定を\"常に信頼\"に変えておく" class="gallery-image" data-flex-basis="275px" data-flex-grow="114" height="1088" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc02.png" srcset="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc02_hu_9525e7ecbe46b4c4.png 800w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc02.png 1250w" width="1250"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="サーバー証明書も同様に設定" class="gallery-image" data-flex-basis="275px" data-flex-grow="114" height="1088" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc03.png" srcset="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc03_hu_a3d98b4e444772a5.png 800w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc03.png 1250w" width="1250"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="最終的なキーチェーンアクセスの状態" class="gallery-image" data-flex-basis="355px" data-flex-grow="148" height="1334" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc04.png" srcset="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc04_hu_43a453c238cc1620.png 800w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc04_hu_cc35dfb58ad42ce7.png 1600w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc04.png 1978w" width="1978"&gt;&lt;/p&gt;
&lt;p&gt;最後に, 今回はサーバー証明書で実在しないドメイン(prometheus.hogehoge.com)を指定しているので,&lt;br&gt;
Macの&lt;code&gt;/etc/hosts&lt;/code&gt;に名前解決の設定を記述しておく.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# /etc/hostsにprometheus.hogehoge.com(localhostに飛ばす)を追加&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;127.0.0.1 prometheus.hogehoge.com&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sudo tee -a /etc/hosts&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;以上で証明書とか秘密鍵の準備は完了.&lt;/p&gt;
&lt;h3 id="prometheus単独でクライアント認証をかける"&gt;Prometheus単独でクライアント認証をかける
&lt;/h3&gt;&lt;p&gt;&lt;img alt="Prometheus単独でクライアント認証する" class="gallery-image" data-flex-basis="857px" data-flex-grow="357" height="533" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/component01.png" srcset="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/component01_hu_94947a40abe5383c.png 800w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/component01_hu_84aadf9e20712897.png 1600w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/component01.png 1905w" width="1905"&gt;&lt;/p&gt;
&lt;p&gt;Prometheus自体にクライアント認証の仕組みがあるので&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;,&lt;br&gt;
&lt;strong&gt;サーバー証明書&lt;/strong&gt;と&lt;strong&gt;サーバー秘密鍵&lt;/strong&gt;(HTTPS化してサーバーの身元を証明するのに使用),&lt;br&gt;
&lt;strong&gt;クライアント認証局の証明書&lt;/strong&gt;(クライアントの身元を確認するのに使用)を持たせる.&lt;/p&gt;
&lt;p&gt;クライアント認証の設定は&lt;code&gt;web-config.yml&lt;/code&gt;に記述する.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/510bab0fc65e9583fd98e6f7e76d85a9.js"&gt;&lt;/script&gt;
&lt;p&gt;Prometheus自身のメトリクスを取得する際にもクライアント認証を突破する必要があるので,&lt;br&gt;
&lt;strong&gt;クライアント証明書&lt;/strong&gt;と&lt;strong&gt;クライアント秘密鍵&lt;/strong&gt;(クライアントの身元を証明するのに使用),&lt;br&gt;
&lt;strong&gt;サーバー認証局の証明書&lt;/strong&gt;(HTTPSサーバーの身元を確認するのに使用)も持たせることにする.&lt;br&gt;
(Prometheus自身のメトリクスを取得しない場合は不要)&lt;/p&gt;
&lt;p&gt;クライアント認証を突破するための設定は&lt;code&gt;prometheus.yml&lt;/code&gt;の&lt;code&gt;scrape_configs&lt;/code&gt;&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;に記述する.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/3da411b41e374518cfe708600d3ac259.js"&gt;&lt;/script&gt;
&lt;p&gt;あとは指定のパスにそれぞれの秘密鍵, 証明書ファイルを配置する.&lt;br&gt;
今回は&lt;code&gt;Docker&lt;/code&gt;で起動するのでパスを指定してマウントしてあげれば良い.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/72933b18de8ac24833461867c1693e8d.js"&gt;&lt;/script&gt;
&lt;p&gt;以上で準備ができたので, いよいよ&lt;code&gt;Docker&lt;/code&gt;で起動する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ディレクトリの状態(使わないものは消している)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls -1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;client-ca-cert.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;client-cert.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;client-private-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker-compose.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;prometheus.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;server-cert.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;server-private-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;web-config.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# コンテナを起動する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker compose up -d --force-recreate --remove-orphans&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;動作確認のため,&lt;br&gt;
Chromeで &lt;a class="link" href="https://prometheus.hogehoge.com" target="_blank" rel="noopener"
 &gt;https://prometheus.hogehoge.com&lt;/a&gt; を開く.&lt;/p&gt;
&lt;p&gt;&lt;img alt="クライアント証明書を要求されるので\"OK\"を選択" class="gallery-image" data-flex-basis="563px" data-flex-grow="234" height="1227" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc05.png" srcset="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc05_hu_3187248fe7d73580.png 800w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc05_hu_8add1d3442aabfa4.png 1600w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc05_hu_a29ab18bc2b25dec.png 2400w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc05.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="この画面が出たらMacにログインしているユーザー名とパスワードを入力する" class="gallery-image" data-flex-basis="436px" data-flex-grow="182" height="600" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc06.png" srcset="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc06_hu_d93a9e1d0c4c6500.png 800w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc06.png 1092w" width="1092"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="クライアント認証に成功. サーバー証明書も有効になっている" class="gallery-image" data-flex-basis="574px" data-flex-grow="239" height="1204" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc07.png" srcset="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc07_hu_201c336e89fef6fd.png 800w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc07_hu_fb04778860b52f2b.png 1600w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc07_hu_7da2402a2b85fc45.png 2400w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc07.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;Macにクライアント証明書をもたせたため, 問題なく閲覧できた.&lt;/p&gt;
&lt;p&gt;今度はクライアント証明書を使わずに &lt;a class="link" href="https://prometheus.hogehoge.com" target="_blank" rel="noopener"
 &gt;https://prometheus.hogehoge.com&lt;/a&gt; を開いてみる.&lt;/p&gt;
&lt;p&gt;&lt;img alt="クライアント証明書を信頼しない設定に戻す" class="gallery-image" data-flex-basis="275px" data-flex-grow="114" height="1088" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc08.png" srcset="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc08_hu_9ff1e4b32468cb48.png 800w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc08.png 1250w" width="1250"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="今度はここで\"キャンセル\"を選択" class="gallery-image" data-flex-basis="563px" data-flex-grow="234" height="1227" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc05.png" srcset="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc05_hu_3187248fe7d73580.png 800w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc05_hu_8add1d3442aabfa4.png 1600w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc05_hu_a29ab18bc2b25dec.png 2400w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc05.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="クライアント認証に失敗したので閲覧できない" class="gallery-image" data-flex-basis="687px" data-flex-grow="286" height="1005" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc09.png" srcset="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc09_hu_bf5adc16e23bcf8b.png 800w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc09_hu_d4bbfa6c3258d6a5.png 1600w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc09_hu_eb4b1f65cba50513.png 2400w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc09.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;要求されたクライアント証明書を提示しなかったため, 閲覧ができない.&lt;br&gt;
以上で&lt;code&gt;Prometheus&lt;/code&gt;にクライアント認証がかかっていることを確認できた.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# コンテナを終了しておく&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker compose down&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="prometheusnginxでクライアント認証をかける"&gt;Prometheus+nginxでクライアント認証をかける
&lt;/h3&gt;&lt;p&gt;&lt;img alt="Prometheus+nginxでクライアント認証する" class="gallery-image" data-flex-basis="955px" data-flex-grow="398" height="533" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/component02.png" srcset="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/component02_hu_3601d59dde5c9eb7.png 800w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/component02_hu_8021726e36e0afa2.png 1600w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/component02.png 2123w" width="2123"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Prometheus&lt;/code&gt;の前段に&lt;code&gt;nginx&lt;/code&gt;(リバースプロキシ)を用意して, そこで&lt;a class="link" href="https://uzimihsr.github.io/post/2020-06-26-client-certification-practice/" target="_blank" rel="noopener"
 &gt;クライアント認証をかける&lt;/a&gt;こともできる.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;nginx&lt;/code&gt;に&lt;strong&gt;サーバー証明書&lt;/strong&gt;と&lt;strong&gt;サーバー秘密鍵&lt;/strong&gt;(HTTPSサーバーの身元を証明するのに使用),&lt;br&gt;
&lt;strong&gt;クライアント認証局の証明書&lt;/strong&gt;(クライアントの身元を確認するのに使用)を持たせる.&lt;/p&gt;
&lt;p&gt;今回はHTTPS化と認証まわりの設定を&lt;code&gt;https.conf&lt;/code&gt;に記述する.&lt;br&gt;
今回はクライアント認証を行うポート(443)と別に認証をかけないポート(44433)も用意してみる.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/e439f6b08097892baea2855ad8d11662.js"&gt;&lt;/script&gt;
&lt;p&gt;この場合&lt;code&gt;Prometheus&lt;/code&gt;自体にはクライアント認証をかけないので&lt;code&gt;web-config.yml&lt;/code&gt;は不要,&lt;br&gt;
さらに自身のメトリクスを取得する場合でも&lt;strong&gt;クライアント証明書&lt;/strong&gt;と&lt;strong&gt;クライアント秘密鍵&lt;/strong&gt;は不要となる.&lt;br&gt;
(したがって&lt;code&gt;prometheus.yml&lt;/code&gt;も自分で作らずデフォルトのものを使用する)&lt;/p&gt;
&lt;p&gt;あとは各種ファイルを&lt;code&gt;nginx&lt;/code&gt;のコンテナにマウントして起動する.&lt;br&gt;
(先程とは異なり, &lt;code&gt;Prometheus&lt;/code&gt;にファイルを持たせないなど設定が変わっていることに注意)&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/3f6c3b2ef2a2dddfed0e3b9ab49a7c42.js"&gt;&lt;/script&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ディレクトリの状態(使わないものを消している)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls -1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;client-ca-cert.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker-compose.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https.conf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;server-cert.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;server-private-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# コンテナを起動する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker compose up -d --force-recreate --remove-orphans&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Chromeで&lt;a class="link" href="https://prometheus.hogehoge.com" target="_blank" rel="noopener"
 &gt;https://prometheus.hogehoge.com&lt;/a&gt;を開く.&lt;/p&gt;
&lt;p&gt;&lt;img alt="クライアント証明書を要求されるが\"キャンセル\"を選択" class="gallery-image" data-flex-basis="563px" data-flex-grow="234" height="1227" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc05.png" srcset="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc05_hu_3187248fe7d73580.png 800w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc05_hu_8add1d3442aabfa4.png 1600w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc05_hu_a29ab18bc2b25dec.png 2400w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc05.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="nginxのクライアント認証失敗画面に遷移する" class="gallery-image" data-flex-basis="1437px" data-flex-grow="598" height="481" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc10.png" srcset="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc10_hu_c37134d9a76d9c05.png 800w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc10_hu_84727c1897d90db9.png 1600w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc10_hu_9e9e3c6b8866f230.png 2400w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc10.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;クライアント証明書を提示しなかったので認証に失敗した.&lt;br&gt;
(クライアント証明書を要求された際に&amp;quot;OK&amp;quot;を選択すると認証に成功する)&lt;/p&gt;
&lt;p&gt;この状態で次は&lt;a class="link" href="https://prometheus.hogehoge.com:44433" target="_blank" rel="noopener"
 &gt;https://prometheus.hogehoge.com:44433&lt;/a&gt;を開く.&lt;/p&gt;
&lt;p&gt;&lt;img alt="クライアント認証がかかっていないのでそのまま開ける. サーバー証明書も有効" class="gallery-image" data-flex-basis="568px" data-flex-grow="236" height="1216" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc11.png" srcset="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc11_hu_87ec9ae99750028c.png 800w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc11_hu_c5a569ddef22f449.png 1600w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc11_hu_a0e6899cc46dfb1.png 2400w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sc11.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;44433ポートにはクライアント認証をかけていないため, そのまま開くことができた.&lt;/p&gt;
&lt;p&gt;こんな感じの出し分けを&lt;code&gt;Prometheus&lt;/code&gt;単独でやるのは難しいが,&lt;br&gt;
&lt;code&gt;nginx&lt;/code&gt;を使うと比較的カンタンに実現できるし, &lt;code&gt;Prometheus&lt;/code&gt;自身のメトリクスを取得するためにクライアント証明書などを持たせる必要もなくなる.&lt;/p&gt;
&lt;p&gt;クライアント認証以外の認証方式も設定しやすいので,&lt;br&gt;
個人的にはこちらのほうがすき.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# コンテナを終了しておく&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker compose down&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Prometheus&lt;/code&gt;にクライアント認証をかけてみた.&lt;/p&gt;
&lt;p&gt;セキュリティ要件で&lt;code&gt;Prometheus&lt;/code&gt;へのアクセスに認証が必要な場合は,&lt;br&gt;
基本は前段の&lt;code&gt;nginx&lt;/code&gt;で認証設定をかけてクライアント側(&lt;code&gt;Grafana&lt;/code&gt;とか)に認証情報を持たせてアクセスするのが良いと思う.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="箱より袋派なねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sotochan_hu_3d7b2435ed09744.jpg 800w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sotochan_hu_326d483a94e6169f.jpg 1600w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sotochan_hu_fece8887be28e86f.jpg 2400w, https://blog.uzimihsr.com/post/2021-06-05-prometheus-client-auth/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a class="link" href="https://prometheus.io/docs/prometheus/latest/configuration/https/" target="_blank" rel="noopener"
 &gt;https://prometheus.io/docs/prometheus/latest/configuration/https/&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;a class="link" href="https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config" target="_blank" rel="noopener"
 &gt;https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config&lt;/a&gt;&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>5月のそとちゃんまとめ(2021)</title><link>https://blog.uzimihsr.com/post/2021-06-01-sotochan/</link><pubDate>Tue, 01 Jun 2021 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2021-06-01-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan.jpg" alt="Featured image of post 5月のそとちゃんまとめ(2021)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e8%aa%95%e7%94%9f%e6%97%a5" &gt;誕生日&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e8%a8%98%e5%bf%b5%e5%86%99%e7%9c%9f" &gt;記念写真&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="誕生日"&gt;誕生日
&lt;/h3&gt;&lt;p&gt;そとちゃんは5月1日でたぶん5さいになった.&lt;/p&gt;
&lt;p&gt;元野良なので本当の誕生日はわからないけど,&lt;br&gt;
うちに来た記念日と病院で推測してもらった日にちから5月1日生まれということにしている.&lt;/p&gt;
&lt;p&gt;今年は気合を入れて猫用の誕生日ケーキも買った.&lt;/p&gt;
&lt;p&gt;&lt;img alt="誕生日ケーキ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan01.jpg" srcset="https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan01_hu_cec8e4f6f97b6369.jpg 800w, https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan01_hu_a252c72926e4b1a2.jpg 1600w, https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan01_hu_2f55726af6666b08.jpg 2400w, https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan01.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;そとちゃんも大喜び.🤗&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;たぶん5さいになった🎉 &lt;a href="https://t.co/OnaNLYQUGJ"&gt;pic.twitter.com/OnaNLYQUGJ&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1388479486434283522?ref_src=twsrc%5Etfw"&gt;May 1, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;&amp;hellip;だったのは最初の一口だけで,&lt;br&gt;
その後はまたたびをふりかけても見向きもしなかった.😭&lt;br&gt;
お口に合わなかったらしい.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;お気に召さなかった😭 &lt;a href="https://t.co/W3XCohhG4F"&gt;pic.twitter.com/W3XCohhG4F&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1388491941566849025?ref_src=twsrc%5Etfw"&gt;May 1, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;ケーキはダメだったけど, 誕生日プレゼントに用意したおもちゃは喜んでくれた.&lt;/p&gt;
&lt;p&gt;&lt;img alt="誕生日プレゼント" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan02.jpg" srcset="https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan02_hu_848cff903c53df73.jpg 800w, https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan02_hu_cfefde1ced6addda.jpg 1600w, https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan02_hu_f771a128f804eb21.jpg 2400w, https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan02.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://www.necoichi.co.jp/Products/detail/id=7582" target="_blank" rel="noopener"
 &gt;キャッチ・ミー・イフ・ユー・キャン 2 猫と音符&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;もともと評判が良いおもちゃだったけど, そとちゃんもかなり喰い付きが良かった.&lt;br&gt;
電池を入れっぱなしにすると延々と遊び続ける.&lt;/p&gt;
&lt;div class="video-wrapper"&gt;
 &lt;iframe loading="lazy" 
 src="https://www.youtube.com/embed/D5xUNnj5KDU" 
 allowfullscreen 
 title="YouTube Video"
 &gt;
 &lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;成猫のそとちゃんが電池切れまで遊ぶのは初めてみた.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ねこもおもちゃも電池切れ &lt;a href="https://t.co/8sTYWa9qBn"&gt;pic.twitter.com/8sTYWa9qBn&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1391202178577027074?ref_src=twsrc%5Etfw"&gt;May 9, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;気に入ってくれてよかった.&lt;/p&gt;
&lt;h3 id="記念写真"&gt;記念写真
&lt;/h3&gt;&lt;p&gt;5さいになった記念に写真屋さんでそとちゃんを撮ってもらった.&lt;/p&gt;
&lt;p&gt;&lt;img alt="めんどくさそう" class="gallery-image" data-flex-basis="160px" data-flex-grow="66" height="1700" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan03.jpg" srcset="https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan03_hu_2f0969b018a7aa5b.jpg 800w, https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan03.jpg 1134w" width="1134"&gt;&lt;/p&gt;
&lt;p&gt;そとちゃんは妙に肝が据わっているので初めての場所でもガンガン探検しちゃう.&lt;/p&gt;
&lt;p&gt;&lt;img alt="探検がいそがしい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan04.jpg" srcset="https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan04_hu_5be723106081fed6.jpg 800w, https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan04_hu_98fcf51359c30615.jpg 1600w, https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan04_hu_9e4691b1c5bb66a1.jpg 2400w, https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan04.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;楽しすぎて撮影用のポジションになかなか止まってくれない.&lt;/p&gt;
&lt;p&gt;&lt;img alt="なかなか台に登らない" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan05.jpg" srcset="https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan05_hu_3882d0b104dd68d3.jpg 800w, https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan05_hu_41c473de1ddc3e62.jpg 1600w, https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan05.jpg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;こんなこともあろうかと持ってきていたお気に入りの&lt;a class="link" href="https://uzimihsr.github.io/post/2021-02-02-sotochan/#%e3%81%ad%e3%81%9a%e3%81%bf" target="_blank" rel="noopener"
 &gt;ねずみのおもちゃ&lt;/a&gt;で目線を釣ってもらい,&lt;br&gt;
なんとか撮影できた.&lt;/p&gt;
&lt;p&gt;&lt;img alt="おもちゃで解決" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1488" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan06.jpg" srcset="https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan06_hu_f9fd7d3c3d10772c.jpg 800w, https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan06_hu_9981887e48b5407e.jpg 1600w, https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan06.jpg 1984w" width="1984"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="カメラにのっかったおもちゃを見ている" class="gallery-image" data-flex-basis="160px" data-flex-grow="66" height="1701" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan07.jpg" srcset="https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan07_hu_eefd5cf993ded797.jpg 800w, https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan07.jpg 1134w" width="1134"&gt;&lt;/p&gt;
&lt;p&gt;それでもそとちゃん単独だとすぐに動いちゃって枚数が確保できないとのことで後半は俺も一緒に撮ってもらった.&lt;/p&gt;
&lt;p&gt;&lt;img alt="そとちゃんと俺" class="gallery-image" data-flex-basis="360px" data-flex-grow="150" height="1260" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan08.jpg" srcset="https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan08_hu_ae10650adcd63867.jpg 800w, https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan08_hu_339493375826d283.jpg 1600w, https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan08.jpg 1890w" width="1890"&gt;&lt;/p&gt;
&lt;p&gt;はしゃいで相当疲れたのか, うちに帰ってからはすぐに寝てしまった.💤&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;つかれた &lt;a href="https://t.co/vQjeA8us06"&gt;pic.twitter.com/vQjeA8us06&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1393780407372423168?ref_src=twsrc%5Etfw"&gt;May 16, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;がんばってくれてえらかった.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;そとちゃんが5さいになった. めでたい.🎉&lt;/p&gt;
&lt;p&gt;そとちゃんからしたらいきなり変なものを食わされたり,&lt;br&gt;
知らないところを探検したいのに無理やり写真を撮られたりでいい迷惑だったかもしれない.&lt;/p&gt;
&lt;p&gt;それでも, そとちゃんはたぶん俺より長くは生きられないのでできるだけお祝いとか記録に残ることをしたい.&lt;br&gt;
(これは俺のエゴだとわかっているけども&amp;hellip;)&lt;/p&gt;
&lt;p&gt;仕方なく(&lt;del&gt;あるいはおもちゃやおやつに釣られながら&lt;/del&gt;)付き合ってくれるそとちゃんには感謝しかないし,&lt;br&gt;
そとちゃんが6さいの誕生日を元気に迎えられるように俺もまた1年頑張ろうと思った.&lt;/p&gt;
&lt;p&gt;&amp;hellip;猫用ケーキは二度と買わない.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="ベストショット" class="gallery-image" data-flex-basis="360px" data-flex-grow="150" height="882" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan_hu_14ed513403446104.jpg 800w, https://blog.uzimihsr.com/post/2021-06-01-sotochan/sotochan.jpg 1323w" width="1323"&gt;&lt;/p&gt;</description></item><item><title>GoでSQLのユニットテストを書く(dockertest)</title><link>https://blog.uzimihsr.com/post/2021-05-14-golang-test-with-dockertest/</link><pubDate>Fri, 14 May 2021 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2021-05-14-golang-test-with-dockertest/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2021-05-14-golang-test-with-dockertest/sotochan.jpg" alt="Featured image of post GoでSQLのユニットテストを書く(dockertest)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://github.com/ory/dockertest" target="_blank" rel="noopener"
 &gt;dockertest&lt;/a&gt;を使うと&lt;code&gt;Go&lt;/code&gt;のコード内からテスト対象のDBを&lt;code&gt;Docker&lt;/code&gt;コンテナとして起動して接続することができる.&lt;/p&gt;
&lt;p&gt;これを使ってDBを都度立ち上げて, 実際にレコード操作の検証をするテストを書いてみた.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/dbae20b96e8fca750d4c251c3c3c9691.js"&gt;&lt;/script&gt;
&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Big Sur 11.2.3&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/golang/go" target="_blank" rel="noopener"
 &gt;go&lt;/a&gt; version go1.15.5 darwin/amd64&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/ory/dockertest" target="_blank" rel="noopener"
 &gt;dockertest&lt;/a&gt; v3.3.5&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/editions/community/docker-ce-desktop-mac" target="_blank" rel="noopener"
 &gt;Docker Desktop for Mac&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Version 3.3.0&lt;/li&gt;
&lt;li&gt;Docker Engine Version 20.10.5&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やりかた"&gt;やりかた
&lt;/h2&gt;&lt;p&gt;この前は&lt;a class="link" href="https://uzimihsr.github.io/post/2021-04-30-golang-test-with-go-sqlmock/" target="_blank" rel="noopener"
 &gt;DBをモック&lt;/a&gt;したテストを試したけど,&lt;br&gt;
やっぱり実際にテスト用のDBを立てて期待値が得られるか検証したいときもある.&lt;/p&gt;
&lt;p&gt;テスト対象となるのは前回同様こんな感じの処理.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/796476ea95ce1bc38e20361e8502f191.js"&gt;&lt;/script&gt;
&lt;p&gt;今回はGoからDockerをいじることができる&lt;a class="link" href="https://github.com/ory/dockertest" target="_blank" rel="noopener"
 &gt;dockertest&lt;/a&gt;を使ってテスト用DBを起動し,&lt;br&gt;
それに接続してテストを行う.&lt;/p&gt;
&lt;p&gt;まずはテーブル定義を記述したファイルをつくる.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/221f31024b523b82bf32cb25ae4931b9.js"&gt;&lt;/script&gt;
&lt;p&gt;ついでに&lt;code&gt;MySQL&lt;/code&gt;の設定ファイルを作っておく.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/5fb95078e7f7f60e03c0c9ed213034a7.js"&gt;&lt;/script&gt;
&lt;p&gt;次に公式の例&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;を参考に, &lt;code&gt;MySQL&lt;/code&gt;&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;のコンテナを立ち上げる関数を書いてみる.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/216853c0e070f2eaaf373436d5a653b1.js"&gt;&lt;/script&gt;
&lt;p&gt;頑張ったのは&lt;code&gt;createContainer()&lt;/code&gt;で&lt;code&gt;RunOptions&lt;/code&gt;&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;を使ってコンテナ起動時に細かいオプションを指定したり必要な設定ファイルをマウントできるようにしたところ.&lt;br&gt;
こうしておくことで大体のDBの設定をこのテストコードに封じ込めることができる.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;closeContainer()&lt;/code&gt;を呼び忘れるとテストが終わってもコンテナが残ってしまうので注意する(&lt;code&gt;defer&lt;/code&gt;で呼んでおくのが良さそう).&lt;/p&gt;
&lt;p&gt;各機能のテストではそれぞれこの関数を呼び出してテスト用のDBを作成する.&lt;/p&gt;
&lt;p&gt;前回同様&lt;code&gt;Create()&lt;/code&gt;についてテストを作るとこんな感じ.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/121e8fda691136fc391fbd27d7822e03.js"&gt;&lt;/script&gt;
&lt;p&gt;一応テスト対象の関数以外のDB操作(挿入したレコードを取得するときなど)も&lt;code&gt;Read()&lt;/code&gt;などの自分で定義している関数ではなく都度SQLを実行するようにした.&lt;/p&gt;
&lt;p&gt;最終的なテストコードはこんな感じ.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/d358e67d94fb9a9bd309e720c95fefb8.js"&gt;&lt;/script&gt;
&lt;p&gt;最後にテストを実行してみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ディレクトリの状態&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ tree .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── go.mod
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── go.sum
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── main.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── main_test.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── my.cnf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── todo.sql
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# テスト実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go &lt;span class="nb"&gt;test&lt;/span&gt; -v ./...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;===&lt;/span&gt; RUN &lt;span class="nv"&gt;TestCreateWithDB&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;===&lt;/span&gt; RUN TestCreateWithDB/レコードが正しく追加されることのテスト
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;mysql&lt;span class="o"&gt;]&lt;/span&gt; 2021/05/13 23:41:36 packets.go:37: unexpected EOF
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;mysql&lt;span class="o"&gt;]&lt;/span&gt; 2021/05/13 23:41:36 packets.go:37: unexpected EOF
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;mysql&lt;span class="o"&gt;]&lt;/span&gt; 2021/05/13 23:41:36 packets.go:37: unexpected EOF
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;--- PASS: TestCreateWithDB &lt;span class="o"&gt;(&lt;/span&gt;27.14s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --- PASS: TestCreateWithDB/レコードが正しく追加されることのテスト &lt;span class="o"&gt;(&lt;/span&gt;27.14s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;===&lt;/span&gt; RUN &lt;span class="nv"&gt;TestReadWithDB&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;===&lt;/span&gt; RUN TestReadWithDB/レコードが正しく取得できることのテスト
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;mysql&lt;span class="o"&gt;]&lt;/span&gt; 2021/05/13 23:42:03 packets.go:37: unexpected EOF
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;mysql&lt;span class="o"&gt;]&lt;/span&gt; 2021/05/13 23:42:03 packets.go:37: unexpected EOF
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;mysql&lt;span class="o"&gt;]&lt;/span&gt; 2021/05/13 23:42:03 packets.go:37: unexpected EOF
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;--- PASS: TestReadWithDB &lt;span class="o"&gt;(&lt;/span&gt;26.95s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --- PASS: TestReadWithDB/レコードが正しく取得できることのテスト &lt;span class="o"&gt;(&lt;/span&gt;26.95s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;===&lt;/span&gt; RUN &lt;span class="nv"&gt;TestUpdateWithDB&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;===&lt;/span&gt; RUN TestUpdateWithDB/レコードが正しく更新できることのテスト
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;mysql&lt;span class="o"&gt;]&lt;/span&gt; 2021/05/13 23:42:30 packets.go:37: unexpected EOF
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;mysql&lt;span class="o"&gt;]&lt;/span&gt; 2021/05/13 23:42:30 packets.go:37: unexpected EOF
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;mysql&lt;span class="o"&gt;]&lt;/span&gt; 2021/05/13 23:42:30 packets.go:37: unexpected EOF
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;--- PASS: TestUpdateWithDB &lt;span class="o"&gt;(&lt;/span&gt;27.15s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --- PASS: TestUpdateWithDB/レコードが正しく更新できることのテスト &lt;span class="o"&gt;(&lt;/span&gt;27.15s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;===&lt;/span&gt; RUN &lt;span class="nv"&gt;TestDeleteWithDB&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;===&lt;/span&gt; RUN TestDeleteWithDB/レコードが正しく削除できることのテスト
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;mysql&lt;span class="o"&gt;]&lt;/span&gt; 2021/05/13 23:42:58 packets.go:37: unexpected EOF
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;mysql&lt;span class="o"&gt;]&lt;/span&gt; 2021/05/13 23:42:58 packets.go:37: unexpected EOF
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;mysql&lt;span class="o"&gt;]&lt;/span&gt; 2021/05/13 23:42:58 packets.go:37: unexpected EOF
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;--- PASS: TestDeleteWithDB &lt;span class="o"&gt;(&lt;/span&gt;28.51s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --- PASS: TestDeleteWithDB/レコードが正しく削除できることのテスト &lt;span class="o"&gt;(&lt;/span&gt;28.51s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;PASS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ok 	github.com/uzimihsr/golang-db-test	110.730s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;コンテナを立ち上げてから疎通できるまでにちょっと時間がかかるので&lt;code&gt;unexpected EOF&lt;/code&gt;のエラーが何回か出てるけど, 内部でリトライをしてるので問題ないはず.&lt;/p&gt;
&lt;p&gt;都度&lt;code&gt;Docker&lt;/code&gt;の操作をしてるせいでかなり時間がかかっているので, &lt;code&gt;t.Parallel()&lt;/code&gt;&lt;sup id="fnref:4"&gt;&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref"&gt;4&lt;/a&gt;&lt;/sup&gt;とかを使って並列実行させたほうが良いかも.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://github.com/ory/dockertest" target="_blank" rel="noopener"
 &gt;dockertest&lt;/a&gt;を使ってテスト用の&lt;code&gt;MySQL&lt;/code&gt;コンテナを&lt;code&gt;Go&lt;/code&gt;のコードから立てて操作してみた.&lt;/p&gt;
&lt;p&gt;別に&lt;code&gt;DB&lt;/code&gt;に限らず外部とのやりとりをする部分は対象を&lt;code&gt;Docker&lt;/code&gt;化できるなら何でも使えちゃいそう.&lt;/p&gt;
&lt;p&gt;ただしテスト環境で&lt;code&gt;Go&lt;/code&gt;以外に&lt;code&gt;Docker&lt;/code&gt;が必要になったり,&lt;br&gt;
コンテナの立ち上げにかなり時間がかかるなどクセも強いのでどこまでやるかはテスト要件と相談して使いたい.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="かわいいねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-05-14-golang-test-with-dockertest/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2021-05-14-golang-test-with-dockertest/sotochan_hu_59007200f965991f.jpg 800w, https://blog.uzimihsr.com/post/2021-05-14-golang-test-with-dockertest/sotochan_hu_af9e45d54f48b93b.jpg 1600w, https://blog.uzimihsr.com/post/2021-05-14-golang-test-with-dockertest/sotochan_hu_79c0e6d5d6e39ddf.jpg 2400w, https://blog.uzimihsr.com/post/2021-05-14-golang-test-with-dockertest/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/ory/dockertest/blob/v3/examples/MySQL.md" target="_blank" rel="noopener"
 &gt;github.com/ory/dockertest/blob/v3/examples/MySQL.md&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;a class="link" href="https://hub.docker.com/_/mysql" target="_blank" rel="noopener"
 &gt;hub.docker.com/_/mysql&lt;/a&gt;&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;&lt;a class="link" href="https://pkg.go.dev/github.com/ory/dockertest#RunOptions" target="_blank" rel="noopener"
 &gt;pkg.go.dev/github.com/ory/dockertest&lt;/a&gt;&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:4"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/golang/go/wiki/TableDrivenTests#parallel-testing" target="_blank" rel="noopener"
 &gt;github.com/golang/go/wiki/TableDrivenTests&lt;/a&gt;&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>4月のそとちゃんまとめ(2021)</title><link>https://blog.uzimihsr.com/post/2021-05-12-sotochan/</link><pubDate>Wed, 12 May 2021 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2021-05-12-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2021-05-12-sotochan/sotochan.jpg" alt="Featured image of post 4月のそとちゃんまとめ(2021)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%b7%e3%83%a3%e3%83%b3%e3%83%97%e3%83%bc" &gt;シャンプー&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%b2%e3%81%96" &gt;ひざ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%a4%e3%81%84%e3%81%ab%e6%8d%89%e3%81%88%e3%81%9f" &gt;ついに捉えた&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="シャンプー"&gt;シャンプー
&lt;/h3&gt;&lt;p&gt;定期的に&lt;a class="link" href="https://uzimihsr.github.io/post/2021-04-23-sotochan/#%e3%83%96%e3%83%a9%e3%83%83%e3%82%b7%e3%83%b3%e3%82%b0" target="_blank" rel="noopener"
 &gt;ブラッシング&lt;/a&gt;はしてるものの,&lt;br&gt;
それでも静電気と抜け毛がすごかったので約1年半ぶりにそとちゃんにお風呂に入ってもらった.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ご機嫌なところに大変残念なお知らせですが今日はお風呂に入ります &lt;a href="https://t.co/pmsgsHc8KQ"&gt;pic.twitter.com/pmsgsHc8KQ&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1378557339783946240?ref_src=twsrc%5Etfw"&gt;April 4, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;そとちゃんはお風呂場がけっこう好きで, 普段も湯船のフタの上でごろごろしてたりする.&lt;/p&gt;
&lt;p&gt;この日もお風呂場の浴室乾燥を入れて暖かくなったところに自分から出向いてきた.&lt;br&gt;
(洗われるとは思っていない)&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="en" dir="ltr"&gt;before &lt;a href="https://t.co/LkLXZyI7Dv"&gt;pic.twitter.com/LkLXZyI7Dv&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1378669967592185861?ref_src=twsrc%5Etfw"&gt;April 4, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;まずはぬるめのシャワーで毛を濡らす.&lt;br&gt;
(そとちゃんはねこだけどシャワーは平気. えらい!)&lt;/p&gt;
&lt;p&gt;&lt;img alt="濡れたそとちゃん" class="gallery-image" data-flex-basis="343px" data-flex-grow="143" height="2817" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-05-12-sotochan/sotochan01.jpg" srcset="https://blog.uzimihsr.com/post/2021-05-12-sotochan/sotochan01_hu_ee6eca8424eed5a5.jpg 800w, https://blog.uzimihsr.com/post/2021-05-12-sotochan/sotochan01_hu_a6552b79075bba63.jpg 1600w, https://blog.uzimihsr.com/post/2021-05-12-sotochan/sotochan01_hu_27ecfd8f085a4f37.jpg 2400w, https://blog.uzimihsr.com/post/2021-05-12-sotochan/sotochan01.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;つぎに猫用シャンプーで体を洗っていく.&lt;/p&gt;
&lt;p&gt;そとちゃんはここが一番つらかったらしく, 暴れはしないけどわんわん鳴いていた.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;シャンプー &lt;a href="https://t.co/qsmDLQloSi"&gt;pic.twitter.com/qsmDLQloSi&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1378677145245941767?ref_src=twsrc%5Etfw"&gt;April 4, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;再びシャワーでシャンプーを洗い流す.&lt;/p&gt;
&lt;p&gt;このあたりで開始から20分くらいが経ち, そとちゃんも心が折れて鳴き声が弱々しくなった. かわいそう.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;すすぎ &lt;a href="https://t.co/UK4abqsbwt"&gt;pic.twitter.com/UK4abqsbwt&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1378682184307892229?ref_src=twsrc%5Etfw"&gt;April 4, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;でもしんどいのはここまで. あとは乾かしていくだけ.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;浴室乾燥とタオルで乾かす &lt;a href="https://t.co/esBDF7cpZ7"&gt;pic.twitter.com/esBDF7cpZ7&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1378685895402905601?ref_src=twsrc%5Etfw"&gt;April 4, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;div class="video-wrapper"&gt;
 &lt;iframe loading="lazy" 
 src="https://www.youtube.com/embed/Sb_5pG4oLSo" 
 allowfullscreen 
 title="YouTube Video"
 &gt;
 &lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;タオルで水気を吸い取り, ドライヤーで仕上げたら毛がふわふわに元通り.&lt;br&gt;
(そとちゃんはドライヤーも平気. えらい!)&lt;/p&gt;
&lt;p&gt;ごほうびのちゅーるをあげて終了.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="en" dir="ltr"&gt;after &lt;a href="https://t.co/6BSAmgPK4c"&gt;pic.twitter.com/6BSAmgPK4c&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1378691373243625473?ref_src=twsrc%5Etfw"&gt;April 4, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;そとちゃんは結局一度も暴れなかった. えらい.😊&lt;/p&gt;
&lt;p&gt;(シャンプー後に毛づくろいしすぎて次の日珍しく毛玉を吐いた)&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;毛玉吐いた &lt;a href="https://t.co/xirdjVBh5q"&gt;pic.twitter.com/xirdjVBh5q&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1378951005698629639?ref_src=twsrc%5Etfw"&gt;April 5, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;h3 id="ひざ"&gt;ひざ
&lt;/h3&gt;&lt;p&gt;そとちゃんは最近ほぼ毎日ひざに乗ってくる.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;あまえんぼ &lt;a href="https://t.co/3RqRbh12ni"&gt;pic.twitter.com/3RqRbh12ni&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1379784297272332289?ref_src=twsrc%5Etfw"&gt;April 7, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;俺がソファでだらだらしてるときによく乗ってくる.&lt;/p&gt;
&lt;p&gt;この体勢だとねこをなでながらスマホがいじれちゃうので時間が爆速で溶ける.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;支配者 &lt;a href="https://t.co/kcNNtHVRyK"&gt;pic.twitter.com/kcNNtHVRyK&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1382996385318936580?ref_src=twsrc%5Etfw"&gt;April 16, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;ちょっとお留守番したときなんかも乗ってくるけど,&lt;br&gt;
このときはスマホをいじると不機嫌になるのでやらない.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;おるすばんしたねこは膝を占領する権利がある &lt;a href="https://t.co/Edj5otupQV"&gt;pic.twitter.com/Edj5otupQV&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1383727656340914179?ref_src=twsrc%5Etfw"&gt;April 18, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;かわいい〜&lt;/p&gt;
&lt;h3 id="ついに捉えた"&gt;ついに捉えた
&lt;/h3&gt;&lt;p&gt;ついにカメラが決定的瞬間を捉えた!!!&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;現行犯 &lt;a href="https://t.co/Gdgjkor4zr"&gt;pic.twitter.com/Gdgjkor4zr&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1385969799495176192?ref_src=twsrc%5Etfw"&gt;April 24, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;めっちゃ悪い顔してる😭😭😭&lt;/p&gt;
&lt;p&gt;&lt;img alt="つめとぎ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-05-12-sotochan/sotochan02.jpg" srcset="https://blog.uzimihsr.com/post/2021-05-12-sotochan/sotochan02_hu_2f4738ef0bcd7d0.jpg 800w, https://blog.uzimihsr.com/post/2021-05-12-sotochan/sotochan02_hu_80111861db57957b.jpg 1600w, https://blog.uzimihsr.com/post/2021-05-12-sotochan/sotochan02_hu_f8c7805915706aec.jpg 2400w, https://blog.uzimihsr.com/post/2021-05-12-sotochan/sotochan02.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;スパゲッティみたいだ&amp;hellip;😭&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;そとちゃんはえらいねこなので, 久しぶりのお風呂も頑張ってくれた.&lt;/p&gt;
&lt;p&gt;濡れたらいつもより痩せて見えるかとおもったけど, そんなことはなかった&amp;hellip;&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="実はイスもバリバリしてるそとちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-05-12-sotochan/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2021-05-12-sotochan/sotochan_hu_67f600447118cd8b.jpg 800w, https://blog.uzimihsr.com/post/2021-05-12-sotochan/sotochan_hu_4516fe9e9c24a65.jpg 1600w, https://blog.uzimihsr.com/post/2021-05-12-sotochan/sotochan_hu_6548f0d2e6cbf66c.jpg 2400w, https://blog.uzimihsr.com/post/2021-05-12-sotochan/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>GoでSQLのユニットテストを書く(go-sqlmock)</title><link>https://blog.uzimihsr.com/post/2021-04-30-golang-test-with-go-sqlmock/</link><pubDate>Fri, 30 Apr 2021 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2021-04-30-golang-test-with-go-sqlmock/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2021-04-30-golang-test-with-go-sqlmock/sotochan.jpg" alt="Featured image of post GoでSQLのユニットテストを書く(go-sqlmock)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Go&lt;/code&gt;で&lt;code&gt;SQL&lt;/code&gt;のテストを書くときは&lt;a class="link" href="https://github.com/DATA-DOG/go-sqlmock" target="_blank" rel="noopener"
 &gt;go-sqlmock&lt;/a&gt;を使うとデータベースのモックがかんたんに作れる.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/475c41a72838b3e8c64a9f5986166de2.js"&gt;&lt;/script&gt;
&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Big Sur 11.2.3&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/golang/go" target="_blank" rel="noopener"
 &gt;go&lt;/a&gt; version go1.15.5 darwin/amd64&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/DATA-DOG/go-sqlmock" target="_blank" rel="noopener"
 &gt;go-sqlmock&lt;/a&gt; v1.5.0&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やりかた"&gt;やりかた
&lt;/h2&gt;&lt;p&gt;こんな感じでDB(&lt;code&gt;MySQL&lt;/code&gt;)のテーブル操作(CRUD)を行う関数について, ユニットテストを書きたくなった.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/796476ea95ce1bc38e20361e8502f191.js"&gt;&lt;/script&gt;
&lt;p&gt;テスト用のDBを立てて実際に操作しても良いんだけど,&lt;br&gt;
CIするときに面倒だったりするのでできれば&lt;code&gt;Go&lt;/code&gt;だけでDBをモックして完結したテストを書きたい.&lt;/p&gt;
&lt;p&gt;こんなときには&lt;a class="link" href="https://github.com/DATA-DOG/go-sqlmock" target="_blank" rel="noopener"
 &gt;go-sqlmock&lt;/a&gt;が使える.&lt;/p&gt;
&lt;p&gt;公式README&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;を参考にしながら関数&lt;code&gt;Create()&lt;/code&gt;についてテストを書いてみるとこんな感じ.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/e187fc4237a72869a48ec2dae650713d.js"&gt;&lt;/script&gt;
&lt;p&gt;&lt;code&gt;Arrange&lt;/code&gt;でDBのモックを作成し, 想定される引数に対する挙動を設定している.&lt;br&gt;
エラーの有無や返す値の内容なども&lt;code&gt;mock.Expect~().With~().With~()&lt;/code&gt;&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;で細かく設定できる.&lt;/p&gt;
&lt;p&gt;同様に&lt;code&gt;Read()&lt;/code&gt;, &lt;code&gt;Update()&lt;/code&gt;, &lt;code&gt;Delete()&lt;/code&gt;についても書いていく.&lt;br&gt;
最終的なテストコードはこんな感じ.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/a9abffc5b1fd4e4f394e241464321e5e.js"&gt;&lt;/script&gt;
&lt;p&gt;最後にテストを実行してみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ tree .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── go.mod
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── go.sum
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── main.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── main_test.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# テスト実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go &lt;span class="nb"&gt;test&lt;/span&gt; -v ./...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;===&lt;/span&gt; RUN &lt;span class="nv"&gt;TestCreate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;===&lt;/span&gt; RUN TestCreate/Createが成功するケース
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;===&lt;/span&gt; RUN TestCreate/Createが失敗するケース
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;--- PASS: TestCreate &lt;span class="o"&gt;(&lt;/span&gt;0.00s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --- PASS: TestCreate/Createが成功するケース &lt;span class="o"&gt;(&lt;/span&gt;0.00s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --- PASS: TestCreate/Createが失敗するケース &lt;span class="o"&gt;(&lt;/span&gt;0.00s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;===&lt;/span&gt; RUN &lt;span class="nv"&gt;TestRead&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;===&lt;/span&gt; RUN TestRead/Readが成功するケース
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;===&lt;/span&gt; RUN TestRead/Readが失敗するケース&lt;span class="o"&gt;(&lt;/span&gt;QueryRowでエラー&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;===&lt;/span&gt; RUN TestRead/Readが失敗するケース&lt;span class="o"&gt;(&lt;/span&gt;Scanでエラー&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;--- PASS: TestRead &lt;span class="o"&gt;(&lt;/span&gt;0.00s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --- PASS: TestRead/Readが成功するケース &lt;span class="o"&gt;(&lt;/span&gt;0.00s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --- PASS: TestRead/Readが失敗するケース&lt;span class="o"&gt;(&lt;/span&gt;QueryRowでエラー&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;0.00s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --- PASS: TestRead/Readが失敗するケース&lt;span class="o"&gt;(&lt;/span&gt;Scanでエラー&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;0.00s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;===&lt;/span&gt; RUN &lt;span class="nv"&gt;TestUpdate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;===&lt;/span&gt; RUN TestUpdate/Updateが成功するケース
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;===&lt;/span&gt; RUN TestUpdate/Updateが失敗するケース
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;--- PASS: TestUpdate &lt;span class="o"&gt;(&lt;/span&gt;0.00s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --- PASS: TestUpdate/Updateが成功するケース &lt;span class="o"&gt;(&lt;/span&gt;0.00s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --- PASS: TestUpdate/Updateが失敗するケース &lt;span class="o"&gt;(&lt;/span&gt;0.00s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;===&lt;/span&gt; RUN &lt;span class="nv"&gt;TestDelete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;===&lt;/span&gt; RUN TestDelete/Deleteが成功するケース
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;===&lt;/span&gt; RUN TestDelete/Deleteが失敗するケース
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;--- PASS: TestDelete &lt;span class="o"&gt;(&lt;/span&gt;0.00s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --- PASS: TestDelete/Deleteが成功するケース &lt;span class="o"&gt;(&lt;/span&gt;0.00s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --- PASS: TestDelete/Deleteが失敗するケース &lt;span class="o"&gt;(&lt;/span&gt;0.00s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;PASS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ok 	github.com/uzimihsr/golang-db-test	0.170s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;できた.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;go-sqlmock&lt;/code&gt;を使うことで, テスト用のDBを立ち上げることなく&lt;code&gt;Go&lt;/code&gt;で&lt;code&gt;SQL&lt;/code&gt;のテストができた. べんり.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="ブラッシング後に必死に毛づくろいするねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-04-30-golang-test-with-go-sqlmock/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2021-04-30-golang-test-with-go-sqlmock/sotochan_hu_5561b141a68bbf4b.jpg 800w, https://blog.uzimihsr.com/post/2021-04-30-golang-test-with-go-sqlmock/sotochan_hu_90c2d6f794baedbd.jpg 1600w, https://blog.uzimihsr.com/post/2021-04-30-golang-test-with-go-sqlmock/sotochan_hu_55004d6a230c72f2.jpg 2400w, https://blog.uzimihsr.com/post/2021-04-30-golang-test-with-go-sqlmock/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/DATA-DOG/go-sqlmock#documentation-and-examples" target="_blank" rel="noopener"
 &gt;公式README&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;a class="link" href="https://pkg.go.dev/github.com/data-dog/go-sqlmock" target="_blank" rel="noopener"
 &gt;sqlmock - pkg.go.dev&lt;/a&gt;&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>3月のそとちゃんまとめ(2021)</title><link>https://blog.uzimihsr.com/post/2021-04-23-sotochan/</link><pubDate>Fri, 23 Apr 2021 11:08:42 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2021-04-23-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2021-04-23-sotochan/sotochan.jpg" alt="Featured image of post 3月のそとちゃんまとめ(2021)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%8a%e3%82%82%e3%81%a1%e3%82%83" &gt;おもちゃ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e6%af%9b%e5%b8%83" &gt;毛布&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%96%e3%83%a9%e3%83%83%e3%82%b7%e3%83%b3%e3%82%b0" &gt;ブラッシング&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="おもちゃ"&gt;おもちゃ
&lt;/h3&gt;&lt;p&gt;3月は新しいおもちゃをいくつか買った.&lt;/p&gt;
&lt;p&gt;まずはねこじゃらし.&lt;br&gt;
&lt;img alt="ねこじゃらし" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-04-23-sotochan/sotochan01.jpg" srcset="https://blog.uzimihsr.com/post/2021-04-23-sotochan/sotochan01_hu_6d53572877a86346.jpg 800w, https://blog.uzimihsr.com/post/2021-04-23-sotochan/sotochan01_hu_cd21a4a3fc058a77.jpg 1600w, https://blog.uzimihsr.com/post/2021-04-23-sotochan/sotochan01_hu_668bb31ff0583394.jpg 2400w, https://blog.uzimihsr.com/post/2021-04-23-sotochan/sotochan01.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://www.doggyman.com/?p=showroom&amp;amp;id=681&amp;amp;toy=cat" target="_blank" rel="noopener"
 &gt;じゃれ猫　トリオ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;なんとこれ, おもちゃの部分がそとちゃんが大好きな&lt;a class="link" href="https://uzimihsr.github.io/post/2021-02-02-sotochan/#%e3%81%ad%e3%81%9a%e3%81%bf" target="_blank" rel="noopener"
 &gt;ねずみのおもちゃ&lt;/a&gt;にそっくり.&lt;/p&gt;
&lt;p&gt;&lt;img alt="似ている" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-04-23-sotochan/sotochan02.jpg" srcset="https://blog.uzimihsr.com/post/2021-04-23-sotochan/sotochan02_hu_bac4adc37072bf1f.jpg 800w, https://blog.uzimihsr.com/post/2021-04-23-sotochan/sotochan02_hu_83ae07b22d1c87fb.jpg 1600w, https://blog.uzimihsr.com/post/2021-04-23-sotochan/sotochan02_hu_ce34fa1c09b5b775.jpg 2400w, https://blog.uzimihsr.com/post/2021-04-23-sotochan/sotochan02.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;同じメーカーだから(?)かはわからないけど振るとシャカシャカ音がするのも同じで,&lt;br&gt;
当然そとちゃんは大興奮.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;うおお &lt;a href="https://t.co/IpdQslzcZm"&gt;pic.twitter.com/IpdQslzcZm&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1372719320053129222?ref_src=twsrc%5Etfw"&gt;March 19, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;これならヒモがついてるのでそとちゃんが失くすこともないので安心.&lt;br&gt;
買ってよかった.&lt;/p&gt;
&lt;p&gt;次に買ったのはペットショップでバラ売りされていたドギツい色のねずみのおもちゃ.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;新しいねずみ &lt;a href="https://t.co/8fksuAyoNh"&gt;pic.twitter.com/8fksuAyoNh&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1375057753727627266?ref_src=twsrc%5Etfw"&gt;March 25, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;これは大失敗.&lt;/p&gt;
&lt;p&gt;他のねずみと同じく軽くて振るとシャカシャカ音はするんだけど,&lt;br&gt;
音が少し小さいのが悪いのか色が悪いのかそとちゃんのお気に召さなかった.&lt;br&gt;
数回遊んでおもちゃ箱(戻ってこない)行き.&lt;/p&gt;
&lt;p&gt;さらに期待はずれだったのはまたたびボール.&lt;/p&gt;
&lt;p&gt;&lt;img alt="興味がなさそうな顔" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-04-23-sotochan/sotochan03.jpg" srcset="https://blog.uzimihsr.com/post/2021-04-23-sotochan/sotochan03_hu_ab0832f622846fdc.jpg 800w, https://blog.uzimihsr.com/post/2021-04-23-sotochan/sotochan03_hu_257f678f431f8499.jpg 1600w, https://blog.uzimihsr.com/post/2021-04-23-sotochan/sotochan03_hu_c7725d730d6a4982.jpg 2400w, https://blog.uzimihsr.com/post/2021-04-23-sotochan/sotochan03.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://www.doggyman.com/?p=showroom&amp;amp;id=621&amp;amp;toy=cat" target="_blank" rel="noopener"
 &gt;じゃれ猫　またたびタックル&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;中にまたたびの粒?が入っていて如何にもねこが食いつきそう.&lt;br&gt;
またたびがついてるおもちゃは手でガッツリ押さえてまたたび部分だけベロベロ舐めちゃうジャンキーのそとちゃんだけど,&lt;br&gt;
この形ならねこの手じゃ押さえづらいし飽きずに追いかけてくれるかな&amp;hellip;という期待もあった.&lt;/p&gt;
&lt;p&gt;結局最初の数分は匂いで興奮してたんだけど,&lt;br&gt;
何回か押さえようとして失敗したらすぐ興味をなくしてしまった.&lt;br&gt;
例のブツを効率良く摂取したいそとちゃんには合わなかったらしい.🌿&lt;/p&gt;
&lt;p&gt;ねこの好みは難しい&amp;hellip;&lt;/p&gt;
&lt;h3 id="毛布"&gt;毛布
&lt;/h3&gt;&lt;p&gt;3月上旬はまだ寒かったので俺のベッドに茶色の毛布を敷いていて,&lt;br&gt;
この毛布がそとちゃんのお気に入りになってしまった.&lt;/p&gt;
&lt;p&gt;ひっくり返っておでこをつけちゃうくらいの気に入りよう.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;かわいいポーズしてる &lt;a href="https://t.co/952eTB4SXU"&gt;pic.twitter.com/952eTB4SXU&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1366554324013260803?ref_src=twsrc%5Etfw"&gt;March 2, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;流石に暖かくなってきたので片付けようとしたんだけど,&lt;br&gt;
なかなか許可が降りず&amp;hellip;&lt;/p&gt;
&lt;p&gt;ベッドに敷いてたのを畳んでソファに置いたらすぐに占拠されてしまった.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;毛布片付けの許可が出ない &lt;a href="https://t.co/icem8UyvPy"&gt;pic.twitter.com/icem8UyvPy&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1374708390929203207?ref_src=twsrc%5Etfw"&gt;March 24, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;強い意志を感じる &lt;a href="https://t.co/pwUdYB5D14"&gt;pic.twitter.com/pwUdYB5D14&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1376351740157517826?ref_src=twsrc%5Etfw"&gt;March 29, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;しかたがないのでソファにそのまま置いておいて,　俺が座るときだけどかすようにしている.&lt;/p&gt;
&lt;p&gt;&lt;img alt="ソファはそとちゃんのもの" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-04-23-sotochan/sotochan04.jpg" srcset="https://blog.uzimihsr.com/post/2021-04-23-sotochan/sotochan04_hu_6ada437ce3351c71.jpg 800w, https://blog.uzimihsr.com/post/2021-04-23-sotochan/sotochan04_hu_1efe45d2aadc93db.jpg 1600w, https://blog.uzimihsr.com/post/2021-04-23-sotochan/sotochan04_hu_db1a0a549affbb3f.jpg 2400w, https://blog.uzimihsr.com/post/2021-04-23-sotochan/sotochan04.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;夏まで置いておくわけにもいかないので, 頃合いを見計らって片付けたい.&lt;/p&gt;
&lt;h3 id="ブラッシング"&gt;ブラッシング
&lt;/h3&gt;&lt;p&gt;部屋が乾燥してたのと毛布でゴロゴロしまくったのが原因でそとちゃんが帯電してしまい,&lt;br&gt;
撫でるたびに静電気でバチバチしてたのでブラッシングをした.&lt;/p&gt;
&lt;p&gt;そとちゃんはブラッシングが大嫌いで,&lt;br&gt;
あまりにも嫌がるので普段は2週に1回くらいの頻度でしかやっていない.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ブラシをかける&lt;/code&gt;→&lt;code&gt;我慢できなくなって逃げる&lt;/code&gt;→&lt;code&gt;おもちゃとおやつで機嫌を取る&lt;/code&gt;→&lt;code&gt;捕まえてブラシをかける&lt;/code&gt;&amp;hellip;&lt;br&gt;
を10回くらい繰り返すのでいつもだいたい1時間くらいかかるんだけど,&lt;br&gt;
今回は特によく逃げるので長期戦だった.&lt;/p&gt;
&lt;p&gt;途中でおひるねタイムまで入る始末.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ブラシから逃げ回って疲れ果てた &lt;a href="https://t.co/c0TJQpRXH2"&gt;pic.twitter.com/c0TJQpRXH2&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1370584806816247812?ref_src=twsrc%5Etfw"&gt;March 13, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;かわいそうだけど起こしてなんとか終了.&lt;/p&gt;
&lt;p&gt;約2時間の激戦で過去最大級の抜け毛が取れた.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;2時間 &lt;a href="https://t.co/CSQyDdXobb"&gt;pic.twitter.com/CSQyDdXobb&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1370598041934209024?ref_src=twsrc%5Etfw"&gt;March 13, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;丸めたらピンポン球くらいのサイズになったのでそとちゃんのおもちゃになった.&lt;/p&gt;
&lt;p&gt;&lt;img alt="抜け毛ボール" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-04-23-sotochan/sotochan05.jpg" srcset="https://blog.uzimihsr.com/post/2021-04-23-sotochan/sotochan05_hu_5b2b3076edb64360.jpg 800w, https://blog.uzimihsr.com/post/2021-04-23-sotochan/sotochan05_hu_2b66fcf6fa0a6fd9.jpg 1600w, https://blog.uzimihsr.com/post/2021-04-23-sotochan/sotochan05_hu_5f25006f6106069a.jpg 2400w, https://blog.uzimihsr.com/post/2021-04-23-sotochan/sotochan05.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;先月に引き続きまたも遅筆. 良くない.&lt;br&gt;
時間を見つけて書いてはいるけどなかなかまとめきれずに公開できない.&lt;/p&gt;
&lt;p&gt;4月はそとちゃんがお風呂に入ったりといろいろあったので早めに書きたい.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="食パンクッションに乗るそとちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-04-23-sotochan/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2021-04-23-sotochan/sotochan_hu_96a3c1fc0355375d.jpg 800w, https://blog.uzimihsr.com/post/2021-04-23-sotochan/sotochan_hu_8638c1bcdf667aa4.jpg 1600w, https://blog.uzimihsr.com/post/2021-04-23-sotochan/sotochan_hu_c9f02343143a25eb.jpg 2400w, https://blog.uzimihsr.com/post/2021-04-23-sotochan/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>2月のそとちゃんまとめ(2021)</title><link>https://blog.uzimihsr.com/post/2021-03-21-sotochan/</link><pubDate>Sun, 21 Mar 2021 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2021-03-21-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2021-03-21-sotochan/sotochan.jpg" alt="Featured image of post 2月のそとちゃんまとめ(2021)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e6%8f%ba%e3%82%8c%e3%81%9f" &gt;揺れた&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e7%8c%ab%e3%81%ae%e6%97%a5" &gt;猫の日&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%a4%e3%82%81%e3%81%a8%e3%81%8e" &gt;つめとぎ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#gero" &gt;GERO&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%af%e3%82%bd%e3%83%87%e3%82%ab%e3%83%88%e3%82%a4%e3%83%ac%e3%83%9e%e3%83%83%e3%83%88" &gt;クソデカトイレマット&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="揺れた"&gt;揺れた
&lt;/h3&gt;&lt;p&gt;2月はかなりでかい地震があった.&lt;/p&gt;
&lt;p&gt;うちもかなり揺れたんだけど, そとちゃんは本棚の上でぐーすか寝ていた&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="揺れの直後 めんどくさそうな顔をしていた" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-03-21-sotochan/sotochan01.jpg" srcset="https://blog.uzimihsr.com/post/2021-03-21-sotochan/sotochan01_hu_d0b1120f35da24f3.jpg 800w, https://blog.uzimihsr.com/post/2021-03-21-sotochan/sotochan01_hu_ec535208ebec6626.jpg 1600w, https://blog.uzimihsr.com/post/2021-03-21-sotochan/sotochan01_hu_c623903d767084bd.jpg 2400w, https://blog.uzimihsr.com/post/2021-03-21-sotochan/sotochan01.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;危機感がまるで感じられない.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ねこが地震に気づかず寝ていたので少しだけお説教した &lt;a href="https://t.co/P8KKo9pQvT"&gt;pic.twitter.com/P8KKo9pQvT&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1360594985171570703?ref_src=twsrc%5Etfw"&gt;February 13, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;万が一のことを考えて一応避難の準備もしたけど,&lt;br&gt;
そとちゃんはお出かけ大好きねこなのですんなりキャリーに入ってくれた.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;協力的で助かる〜 &lt;a href="https://t.co/thPoCTHDvQ"&gt;pic.twitter.com/thPoCTHDvQ&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1360600861479636999?ref_src=twsrc%5Etfw"&gt;February 13, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;結局避難せずに済んだけどごはんとトイレの道具を準備するのに結構時間がかかったし,&lt;br&gt;
災害への備えが全然できてなかったことを実感した&amp;hellip;&lt;/p&gt;
&lt;h3 id="猫の日"&gt;猫の日
&lt;/h3&gt;&lt;p&gt;2/22は猫の日だったらしい.&lt;/p&gt;
&lt;p&gt;去年に続けて今年も&lt;a class="link" href="C1ccWQJ2hDc" &gt;イエローハット&lt;/a&gt;が面白そうなキャンペーンをやっていたので,&lt;br&gt;
そとちゃんには&lt;a class="link" href="https://www.yellowhat.jp/campaign/202102/yellowhat_catquiz/index.html" target="_blank" rel="noopener"
 &gt;交通にゃん全クイズ&lt;/a&gt;に挑戦してもらった.&lt;/p&gt;
&lt;p&gt;結果は&amp;hellip;?&lt;/p&gt;
&lt;div class="video-wrapper"&gt;
 &lt;iframe loading="lazy" 
 src="https://www.youtube.com/embed/KS9Tuz-WCLY" 
 allowfullscreen 
 title="YouTube Video"
 &gt;
 &lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;😭&lt;/p&gt;
&lt;h3 id="つめとぎ"&gt;つめとぎ
&lt;/h3&gt;&lt;p&gt;今まで使っていたつめとぎがぼろぼろだったので, 全く同じものを買った.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;つめとぎボロボロなので2台目を買いました &lt;a href="https://t.co/bLhtsCQ6Uh"&gt;pic.twitter.com/bLhtsCQ6Uh&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1363664839671836673?ref_src=twsrc%5Etfw"&gt;February 22, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;&lt;a class="link" href="https://www.garigari-cat.com/product/gari-gari/gari-gari-wall/gari-gari-wall-scratcher-plus/" target="_blank" rel="noopener"
 &gt;Gari Gari Wall Scratcher PLUS&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;これはねこが立った姿勢でつめとぎができるスグレモノで, そとちゃんのお気に入り.&lt;/p&gt;
&lt;p&gt;&lt;img alt="組み立てを手伝うねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-03-21-sotochan/sotochan02.jpg" srcset="https://blog.uzimihsr.com/post/2021-03-21-sotochan/sotochan02_hu_bb5c158eadf45d13.jpg 800w, https://blog.uzimihsr.com/post/2021-03-21-sotochan/sotochan02_hu_1885e4628958b66f.jpg 1600w, https://blog.uzimihsr.com/post/2021-03-21-sotochan/sotochan02_hu_7e614016e7daec30.jpg 2400w, https://blog.uzimihsr.com/post/2021-03-21-sotochan/sotochan02.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;好きすぎて組み立て中にバリバリしちゃう.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;完成を待てない &lt;a href="https://t.co/08YHEILJs6"&gt;pic.twitter.com/08YHEILJs6&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1363667988293951489?ref_src=twsrc%5Etfw"&gt;February 22, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;新品と古いのを比べると一目瞭然で, そとちゃんがどれだけ今までバリバリしてくれたかがよくわかる.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;職人ねこは造り終えたものに興味は無い&lt;br&gt;また次の現場へ向かう &lt;a href="https://t.co/RrUGGUGzFx"&gt;pic.twitter.com/RrUGGUGzFx&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1363670894397169667?ref_src=twsrc%5Etfw"&gt;February 22, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;ちなみにつめとぎが新しくなってもそとちゃんはソファをバリバリし続けている&amp;hellip;&lt;br&gt;
どうして😭&lt;/p&gt;
&lt;h3 id="gero"&gt;GERO
&lt;/h3&gt;&lt;p&gt;久しぶりにそとちゃんが吐いた.&lt;/p&gt;
&lt;p&gt;早朝の5時くらいにかなり大きめの「オエッ、ゴポッ」とした音がしたのでびっくりして飛び起きた.&lt;/p&gt;
&lt;p&gt;現場を見てみるとけっこうガッツリやっていた.&lt;br&gt;
(画像はモザイクをかけてるけど, 直前に食べたらしいカリカリと胃液?が混ざった茶色いGEROが撒き散っていた)&lt;/p&gt;
&lt;p&gt;&lt;img alt="GERO" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="480" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-03-21-sotochan/sotochan03.jpg" width="640"&gt;&lt;/p&gt;
&lt;p&gt;そとちゃんは普段滅多に吐かない(&lt;a class="link" href="https://uzimihsr.github.io/post/2020-08-13-sotochan/" target="_blank" rel="noopener"
 &gt;誤飲騒動&lt;/a&gt;以来全く吐いてなかった)ので俺はもうパニック.&lt;/p&gt;
&lt;p&gt;急いで獣医さんに電話したけど,&lt;br&gt;
吐いたのが1回で終わっていたのと吐いた直後も食欲があったことから急患にはかからず家で様子を見ることに.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;早朝に半年ぶりのGEROを吐いてしもべを叩き起こしたねこ&lt;br&gt;余裕ぶっこいてるし食欲も遊ぶ元気もあるので獣医さんと相談した上で様子見 &lt;a href="https://t.co/dZfoQu162E"&gt;pic.twitter.com/dZfoQu162E&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1361829397896990721?ref_src=twsrc%5Etfw"&gt;February 17, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;結局その後は何も起こらず元気に運動会をしていたので, 病院にも行っていない.&lt;/p&gt;
&lt;p&gt;大変なことにならなくてよかった.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ごはんめっちゃ食べよる &lt;a href="https://t.co/6ze6P56hdq"&gt;pic.twitter.com/6ze6P56hdq&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1362007365772398593?ref_src=twsrc%5Etfw"&gt;February 17, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;どうして吐いたのかはわからずじまいだけど,&lt;br&gt;
フードの形がわかるくらいのGEROだったので空腹状態で食べ急いで胃がびっくりしたのかと推測している.🤔&lt;br&gt;
(GEROの前日は夕方のカリカリをガッツリ残していたのでおやつを抜いていた)&lt;/p&gt;
&lt;p&gt;GEROカーペットもすぐに外して洗濯したので今ではわからないくらいきれいになった.&lt;br&gt;
タイルカーペットにしておいてよかった.&lt;/p&gt;
&lt;h3 id="クソデカトイレマット"&gt;クソデカトイレマット
&lt;/h3&gt;&lt;p&gt;そとちゃんは掃除がめっちゃ便利な&lt;a class="link" href="https://www.litter-robot.com/litter-robot-3.html" target="_blank" rel="noopener"
 &gt;ロボットトイレ&lt;/a&gt;を使ってくれている. えらい.😊&lt;/p&gt;
&lt;p&gt;&lt;img alt="ロボットトイレ" class="gallery-image" data-flex-basis="291px" data-flex-grow="121" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-03-21-sotochan/sotochan04.jpg" srcset="https://blog.uzimihsr.com/post/2021-03-21-sotochan/sotochan04_hu_c5d26ddfb8e6ffa5.jpg 800w, https://blog.uzimihsr.com/post/2021-03-21-sotochan/sotochan04_hu_ce6d05dbc65e4a06.jpg 1600w, https://blog.uzimihsr.com/post/2021-03-21-sotochan/sotochan04_hu_9e21a2697f787528.jpg 2400w, https://blog.uzimihsr.com/post/2021-03-21-sotochan/sotochan04.jpg 3669w" width="3669"&gt;&lt;/p&gt;
&lt;p&gt;が, このトイレは横からの入り口が大きく開いていて,&lt;br&gt;
そとちゃんはうんちした後にハイテンションで飛び出てくるので周りに猫砂が飛び散る.😭&lt;/p&gt;
&lt;p&gt;一応&lt;a class="link" href="https://www.petio.com/fs/pshop/4903588251016" target="_blank" rel="noopener"
 &gt;小さめのトイレマット&lt;/a&gt;を敷いてたんだけど,&lt;br&gt;
そとちゃんの射出角度(?)によってはマットを超えちゃったりしてあんまり意味がなかった.&lt;/p&gt;
&lt;p&gt;そこでこのクソデカトイレマットを購入.&lt;/p&gt;
&lt;p&gt;&lt;img alt="でかい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-03-21-sotochan/sotochan05.jpg" srcset="https://blog.uzimihsr.com/post/2021-03-21-sotochan/sotochan05_hu_cab933c25cda322a.jpg 800w, https://blog.uzimihsr.com/post/2021-03-21-sotochan/sotochan05_hu_94dde3364e3a0ca2.jpg 1600w, https://blog.uzimihsr.com/post/2021-03-21-sotochan/sotochan05_hu_43a78760810efb65.jpg 2400w, https://blog.uzimihsr.com/post/2021-03-21-sotochan/sotochan05.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://www.petio.com/fs/pshop/4903588255847" target="_blank" rel="noopener"
 &gt;Petio necoco 猫トイレマット ワイド&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;今度はかなりの範囲がカバーできるようになった.&lt;/p&gt;
&lt;p&gt;飛び散った猫砂を裸足で踏んで悲しい思いをすることがなくなってうれしい.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;2月はそとちゃんも俺もいろいろありすぎて, 書くのが遅くなってしまった&amp;hellip;&lt;/p&gt;
&lt;p&gt;3月も既に新しいおもちゃをいくつか買ったりしているので, はやめに書いておきたい.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="毛布に埋まるそとちゃん" class="gallery-image" data-flex-basis="435px" data-flex-grow="181" height="2220" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-03-21-sotochan/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2021-03-21-sotochan/sotochan_hu_a81b5623e1029b04.jpg 800w, https://blog.uzimihsr.com/post/2021-03-21-sotochan/sotochan_hu_390bab6f427c411d.jpg 1600w, https://blog.uzimihsr.com/post/2021-03-21-sotochan/sotochan_hu_6e6e48cd9538abf9.jpg 2400w, https://blog.uzimihsr.com/post/2021-03-21-sotochan/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>GrafanaをHTTPS化する</title><link>https://blog.uzimihsr.com/post/2021-02-15-grafana-tls-ssl/</link><pubDate>Mon, 15 Feb 2021 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2021-02-15-grafana-tls-ssl/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2021-02-15-grafana-tls-ssl/sotochan.jpg" alt="Featured image of post GrafanaをHTTPS化する" /&gt;&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2021-02-11-prometheus-tls-ssl/" target="_blank" rel="noopener"
 &gt;Prometheus&lt;/a&gt;と同様に&lt;code&gt;Grafana&lt;/code&gt;も&lt;code&gt;HTTPS&lt;/code&gt;化してみた.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Prometheus&lt;/code&gt;と同様に&lt;code&gt;Grafana&lt;/code&gt;自体に証明書と秘密鍵をもたせる方法と&lt;code&gt;HTTPS&lt;/code&gt;対応したリバースプロキシを使う方法の2通りを試した.&lt;/p&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Mojave 10.14
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Docker&lt;/code&gt;のホストとして使用, 動作確認用のブラウザもこちらで起動する&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.google.com/chrome/" target="_blank" rel="noopener"
 &gt;Google Chrome&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;バージョン: 88.0.4324.150（Official Build） （x86_64）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/editions/community/docker-ce-desktop-mac" target="_blank" rel="noopener"
 &gt;Docker Desktop for Mac&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Version 3.1.0&lt;/li&gt;
&lt;li&gt;Docker Engine Version 20.10.2&lt;/li&gt;
&lt;li&gt;docker-compose version 1.27.4&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/grafana/grafana" target="_blank" rel="noopener"
 &gt;Grafana&lt;/a&gt; (Docker)
&lt;ul&gt;
&lt;li&gt;version &lt;a class="link" href="https://hub.docker.com/layers/grafana/grafana/7.3.7/images/sha256-f140fde5ba622745926b1e390b6ff335c1a0b7a1126cd4211600534f922ef4c0?context=explore" target="_blank" rel="noopener"
 &gt;7.3.7&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/nginx/nginx" target="_blank" rel="noopener"
 &gt;nginx&lt;/a&gt; (Docker)
&lt;ul&gt;
&lt;li&gt;version &lt;a class="link" href="https://hub.docker.com/layers/nginx/library/nginx/1.18.0/images/sha256-6907ea1bf7f121ae60f040dbca1ac676f42157face02d769cb8e39abdcd9b4fe?context=explore" target="_blank" rel="noopener"
 &gt;1.18.0&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/openssl/openssl" target="_blank" rel="noopener"
 &gt;openssl&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;version 1.1.1d&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e7%a7%98%e5%af%86%e9%8d%b5%e3%81%a8%e3%82%aa%e3%83%ac%e3%82%aa%e3%83%ac%e8%a8%bc%e6%98%8e%e6%9b%b8%e3%81%ae%e4%bd%9c%e6%88%90" &gt;秘密鍵とオレオレ証明書の作成&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#grafana%e3%81%ab%e8%a8%bc%e6%98%8e%e6%9b%b8%e3%81%a8%e7%a7%98%e5%af%86%e9%8d%b5%e3%82%92%e6%8c%81%e3%81%9f%e3%81%9b%e3%82%8b" &gt;Grafanaに証明書と秘密鍵を持たせる&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#nginx%e3%81%a7%e3%83%aa%e3%83%90%e3%83%bc%e3%82%b9%e3%83%97%e3%83%ad%e3%82%ad%e3%82%b7%e3%81%99%e3%82%8b" &gt;nginxでリバースプロキシする&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="秘密鍵とオレオレ証明書の作成"&gt;秘密鍵とオレオレ証明書の作成
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2021-02-11-prometheus-tls-ssl/#%e7%a7%98%e5%af%86%e9%8d%b5%e3%81%a8%e3%82%aa%e3%83%ac%e3%82%aa%e3%83%ac%e8%a8%bc%e6%98%8e%e6%9b%b8%e3%81%ae%e4%bd%9c%e6%88%90" target="_blank" rel="noopener"
 &gt;前回&lt;/a&gt;と全く同じ手順で秘密鍵と証明書を作成する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# cert.pemはSANsでhogehoge.comが指定されたSSL証明書&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl x509 -in cert.pem -noout -text
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Certificate:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Data:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Version: &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;0x2&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Serial Number:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 24:4c:ec:40:cc:94:5c:a2:af:30:6a:e9:7d:5c:17:28:5e:fb:ec:fc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Signature Algorithm: sha256WithRSAEncryption
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Issuer: &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;AU, &lt;span class="nv"&gt;ST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Some-State, &lt;span class="nv"&gt;O&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Internet Widgits Pty Ltd, &lt;span class="nv"&gt;CN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;hogehoge.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Validity
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Not Before: Feb &lt;span class="m"&gt;10&lt;/span&gt; 16:13:01 &lt;span class="m"&gt;2021&lt;/span&gt; GMT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Not After : Mar &lt;span class="m"&gt;12&lt;/span&gt; 16:13:01 &lt;span class="m"&gt;2021&lt;/span&gt; GMT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Subject: &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;AU, &lt;span class="nv"&gt;ST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Some-State, &lt;span class="nv"&gt;O&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Internet Widgits Pty Ltd, &lt;span class="nv"&gt;CN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;hogehoge.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; X509v3 extensions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; X509v3 Subject Alternative Name:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; DNS:hogehoge.com, DNS:fugafuga.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# private-key.pemはcert.pemに紐づく秘密鍵&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl rsa -in private-key.pem -text -noout
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Private-Key: &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2048&lt;/span&gt; bit&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;modulus:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;作成したオレオレ証明書は&lt;code&gt;Mac&lt;/code&gt;で&lt;a class="link" href="https://uzimihsr.github.io/post/2021-02-11-prometheus-tls-ssl/#%e7%a7%98%e5%af%86%e9%8d%b5%e3%81%a8%e3%82%aa%e3%83%ac%e3%82%aa%e3%83%ac%e8%a8%bc%e6%98%8e%e6%9b%b8%e3%81%ae%e4%bd%9c%e6%88%90" target="_blank" rel="noopener"
 &gt;信頼する&lt;/a&gt;設定にしておく.&lt;/p&gt;
&lt;h3 id="grafanaに証明書と秘密鍵を持たせる"&gt;Grafanaに証明書と秘密鍵を持たせる
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Grafana&lt;/code&gt;は元から&lt;code&gt;HTTPS&lt;/code&gt;化に対応しているので, SSL証明書とその秘密鍵をもたせる&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;だけで良さそう.&lt;/p&gt;
&lt;p&gt;証明書(&lt;code&gt;cert_file&lt;/code&gt;)と鍵の場所(&lt;code&gt;cert_key&lt;/code&gt;)などは&lt;code&gt;grafana.ini&lt;/code&gt;で設定できる.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/90383e86459263b69b6707660bbff8fa.js"&gt;&lt;/script&gt;
&lt;p&gt;あとはこの&lt;code&gt;grafana.ini&lt;/code&gt;と証明書, 秘密鍵を適切な場所に配置して&lt;code&gt;Grafana&lt;/code&gt;を起動する.&lt;/p&gt;
&lt;p&gt;今回は&lt;code&gt;Docker Compose&lt;/code&gt;で試すが, 非コンテナ環境でもやることは同じはず.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/f9334e7681e69d7672989548533f1d5e.js"&gt;&lt;/script&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ tree .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── cert.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── docker-compose.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── grafana.ini
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── private-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# コンテナ起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-compose up -d --force-recreate --remove-orphans
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# localhostの443番ポートがGrafanaコンテナの443に割り当てられている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-compose ps
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Name Command State Ports
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;----------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grafana /run.sh Up 3000/tcp, 0.0.0.0:443-&amp;gt;443/tcp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a class="link" href="https://hogehoge.com" target="_blank" rel="noopener"
 &gt;https://hogehoge.com&lt;/a&gt;を開く.&lt;br&gt;
(&lt;strong&gt;hogehoge.com&lt;/strong&gt;で&lt;strong&gt;localhost&lt;/strong&gt;にアクセスするためには&lt;code&gt;/etc/hosts&lt;/code&gt;を&lt;a class="link" href="https://uzimihsr.github.io/post/2021-02-11-prometheus-tls-ssl/#%e7%a7%98%e5%af%86%e9%8d%b5%e3%81%a8%e3%82%aa%e3%83%ac%e3%82%aa%e3%83%ac%e8%a8%bc%e6%98%8e%e6%9b%b8%e3%81%ae%e4%bd%9c%e6%88%90" target="_blank" rel="noopener"
 &gt;編集&lt;/a&gt;しておく)&lt;/p&gt;
&lt;p&gt;&lt;img alt="HTTPSで公開されている" class="gallery-image" data-flex-basis="402px" data-flex-grow="167" height="1716" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-15-grafana-tls-ssl/sc01.png" srcset="https://blog.uzimihsr.com/post/2021-02-15-grafana-tls-ssl/sc01_hu_4e4e363da242cf5b.png 800w, https://blog.uzimihsr.com/post/2021-02-15-grafana-tls-ssl/sc01_hu_942994ee3280d3f8.png 1600w, https://blog.uzimihsr.com/post/2021-02-15-grafana-tls-ssl/sc01_hu_14692ceca5f9d8a8.png 2400w, https://blog.uzimihsr.com/post/2021-02-15-grafana-tls-ssl/sc01.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="オレオレ証明書が有効になっている" class="gallery-image" data-flex-basis="384px" data-flex-grow="160" height="1800" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-15-grafana-tls-ssl/sc02.png" srcset="https://blog.uzimihsr.com/post/2021-02-15-grafana-tls-ssl/sc02_hu_e8cb4c98193a98d.png 800w, https://blog.uzimihsr.com/post/2021-02-15-grafana-tls-ssl/sc02_hu_63b411feb9e55c4c.png 1600w, https://blog.uzimihsr.com/post/2021-02-15-grafana-tls-ssl/sc02_hu_886a4f47eacc32ee.png 2400w, https://blog.uzimihsr.com/post/2021-02-15-grafana-tls-ssl/sc02.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Grafana&lt;/code&gt;が&lt;code&gt;HTTPS&lt;/code&gt;化されていることが確認できた.&lt;br&gt;
かんたん.😊&lt;/p&gt;
&lt;h3 id="nginxでリバースプロキシする"&gt;nginxでリバースプロキシする
&lt;/h3&gt;&lt;p&gt;もちろん&lt;code&gt;Prometheus&lt;/code&gt;と同様に&lt;code&gt;HTTPS&lt;/code&gt;化した&lt;code&gt;nginx&lt;/code&gt;でリバースプロキシすることもできるはず.&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2021-02-11-prometheus-tls-ssl/#nginx%e3%82%92%e6%8c%9f%e3%82%93%e3%81%a7https%e5%8c%96%e3%81%99%e3%82%8b" target="_blank" rel="noopener"
 &gt;前回&lt;/a&gt;と同様に&lt;code&gt;nginx&lt;/code&gt;に証明書と鍵を持たせて, &lt;code&gt;Grafana&lt;/code&gt;側でリバースプロキシ用の設定を入れてみる.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/062be860a744dcc4e33d14646711dee6.js"&gt;&lt;/script&gt;
&lt;script src="https://gist.github.com/uzimihsr/e064fcbde0797460aea5e0a28ef594dc.js"&gt;&lt;/script&gt;
&lt;script src="https://gist.github.com/uzimihsr/d4f78de3d4bbcd996487246e4f7b1fd5.js"&gt;&lt;/script&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ tree .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── cert.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── docker-compose.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── grafana.ini
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── https.conf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── private-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# コンテナ起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-compose up -d --force-recreate --remove-orphans
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# localhostの443番ポートがnginxコンテナの443に割り当てられている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-compose ps
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Name Command State Ports
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grafana /run.sh Up 3000/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nginx /docker-entrypoint.sh ngin ... Up 0.0.0.0:443-&amp;gt;443/tcp, 80/tcp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;Grafana&lt;/code&gt;と&lt;code&gt;nginx&lt;/code&gt;が起動したら&lt;a class="link" href="https://hogehoge.com/grafana/" target="_blank" rel="noopener"
 &gt;https://hogehoge.com/grafana/&lt;/a&gt;を開く.&lt;/p&gt;
&lt;p&gt;&lt;img alt="nginxを使ってもHTTPS化できた" class="gallery-image" data-flex-basis="403px" data-flex-grow="167" height="1715" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-15-grafana-tls-ssl/sc03.png" srcset="https://blog.uzimihsr.com/post/2021-02-15-grafana-tls-ssl/sc03_hu_fd19dead13edea0.png 800w, https://blog.uzimihsr.com/post/2021-02-15-grafana-tls-ssl/sc03_hu_b1026be40dcae7a9.png 1600w, https://blog.uzimihsr.com/post/2021-02-15-grafana-tls-ssl/sc03_hu_6762ee9f7ea85d47.png 2400w, https://blog.uzimihsr.com/post/2021-02-15-grafana-tls-ssl/sc03.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;先ほどと同様に&lt;code&gt;HTTPS&lt;/code&gt;で&lt;code&gt;Grafana&lt;/code&gt;が公開されていることが確認できた.&lt;/p&gt;
&lt;p&gt;やったぜ.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Grafana&lt;/code&gt;を&lt;code&gt;HTTPS&lt;/code&gt;化してみた.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Grafana&lt;/code&gt;自体に&lt;code&gt;HTTPS&lt;/code&gt;対応機能があるので設定はわりとカンタンだった.&lt;br&gt;
&lt;code&gt;nginx&lt;/code&gt;を使う場合も&lt;a class="link" href="https://uzimihsr.github.io/post/2021-02-11-prometheus-tls-ssl/" target="_blank" rel="noopener"
 &gt;PrometheusをHTTPS化&lt;/a&gt;したときと同じようにできたのでそんなにつまづくところはなかったと思う.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="目つきがわるいねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-15-grafana-tls-ssl/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2021-02-15-grafana-tls-ssl/sotochan_hu_4b5dee7dc062a2fd.jpg 800w, https://blog.uzimihsr.com/post/2021-02-15-grafana-tls-ssl/sotochan_hu_f213247ff8684df0.jpg 1600w, https://blog.uzimihsr.com/post/2021-02-15-grafana-tls-ssl/sotochan_hu_b8fd9185eacf0df5.jpg 2400w, https://blog.uzimihsr.com/post/2021-02-15-grafana-tls-ssl/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a class="link" href="https://grafana.com/docs/grafana/latest/administration/configuration/#cert_file" target="_blank" rel="noopener"
 &gt;https://grafana.com/docs/grafana/latest/administration/configuration/#cert_file&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>PrometheusをHTTPS化する</title><link>https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/</link><pubDate>Thu, 11 Feb 2021 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sotochan.jpg" alt="Featured image of post PrometheusをHTTPS化する" /&gt;&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Prometheus&lt;/code&gt;はデフォルトだと&lt;code&gt;HTTP&lt;/code&gt;(暗号化なし)で公開されるが, セキュリティの観点からどうしても&lt;code&gt;HTTPS&lt;/code&gt;で動かしたい場合がある.&lt;/p&gt;
&lt;p&gt;今回は&lt;code&gt;nginx&lt;/code&gt;を使ってリバースプロキシする方法と&lt;code&gt;Prometheus&lt;/code&gt;自体を&lt;code&gt;HTTPS&lt;/code&gt;化する方法の2通りの方法を試してみた.&lt;/p&gt;
&lt;p&gt;&lt;img alt="HTTPS化したPrometheus" class="gallery-image" data-flex-basis="990px" data-flex-grow="412" height="698" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc03.png" srcset="https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc03_hu_88aa663672c9a60e.png 800w, https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc03_hu_8872e9cd19ee5a2d.png 1600w, https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc03_hu_7f381bc2a349af02.png 2400w, https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc03.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Mojave 10.14
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Docker&lt;/code&gt;のホストとして使用, 動作確認用のブラウザもこちらで起動する&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.google.com/chrome/" target="_blank" rel="noopener"
 &gt;Google Chrome&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;バージョン: 88.0.4324.150（Official Build） （x86_64）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/editions/community/docker-ce-desktop-mac" target="_blank" rel="noopener"
 &gt;Docker Desktop for Mac&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Version 3.1.0&lt;/li&gt;
&lt;li&gt;Docker Engine Version 20.10.2&lt;/li&gt;
&lt;li&gt;docker-compose version 1.27.4&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/prometheus/prometheus" target="_blank" rel="noopener"
 &gt;Prometheus&lt;/a&gt; (Docker)
&lt;ul&gt;
&lt;li&gt;version &lt;a class="link" href="https://hub.docker.com/layers/prom/prometheus/v2.24.1/images/sha256-f4a858861e05c8611cdb5867a07e48742b8295400a5993ac05ad1ee67e6d5696?context=explore" target="_blank" rel="noopener"
 &gt;2.24.1&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/nginx/nginx" target="_blank" rel="noopener"
 &gt;nginx&lt;/a&gt; (Docker)
&lt;ul&gt;
&lt;li&gt;version &lt;a class="link" href="https://hub.docker.com/layers/nginx/library/nginx/1.18.0/images/sha256-6907ea1bf7f121ae60f040dbca1ac676f42157face02d769cb8e39abdcd9b4fe?context=explore" target="_blank" rel="noopener"
 &gt;1.18.0&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/openssl/openssl" target="_blank" rel="noopener"
 &gt;openssl&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;version 1.1.1d&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e7%a7%98%e5%af%86%e9%8d%b5%e3%81%a8%e3%82%aa%e3%83%ac%e3%82%aa%e3%83%ac%e8%a8%bc%e6%98%8e%e6%9b%b8%e3%81%ae%e4%bd%9c%e6%88%90" &gt;秘密鍵とオレオレ証明書の作成&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#nginx%e3%82%92%e6%8c%9f%e3%82%93%e3%81%a7https%e5%8c%96%e3%81%99%e3%82%8b" &gt;nginxを挟んでHTTPS化する&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#prometheus%e5%8d%98%e7%8b%ac%e3%81%a7https%e5%8c%96%e3%81%99%e3%82%8b" &gt;Prometheus単独でHTTPS化する&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="秘密鍵とオレオレ証明書の作成"&gt;秘密鍵とオレオレ証明書の作成
&lt;/h3&gt;&lt;p&gt;まずは&lt;code&gt;HTTPS&lt;/code&gt;で通信を行うために&lt;code&gt;openssl&lt;/code&gt;で秘密鍵とSSL証明書(オレオレ証明書)を作成する.&lt;br&gt;
(公的な証明書と鍵のペアがある場合は不要. 文中の&lt;strong&gt;hogehoge.com&lt;/strong&gt;は適切なホスト名に置き換える.)&lt;/p&gt;
&lt;p&gt;オレオレ証明書を作るときは&lt;a class="link" href="https://uzimihsr.github.io/post/2020-05-30-certification-practice/" target="_blank" rel="noopener"
 &gt;以前のやり方&lt;/a&gt;に加えて,&lt;br&gt;
ページを&lt;code&gt;Chrome&lt;/code&gt;で開いた場合も怒られないように&lt;code&gt;SANs(Subject Alternative Names)&lt;/code&gt;を設定するようにする.&lt;/p&gt;
&lt;p&gt;今回の鍵と証明書の作成に使用する&lt;code&gt;openssl&lt;/code&gt;は&lt;code&gt;nginx&lt;/code&gt;の&lt;code&gt;Docker image&lt;/code&gt;に入っているものを使う.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# nginxコンテナの中で実行(カレントディレクトリをマウントしておく)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run --rm -it -v&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt;&lt;span class="s2"&gt;:/workdir&amp;#34;&lt;/span&gt; -w&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/workdir&amp;#34;&lt;/span&gt; --entrypoint&lt;span class="o"&gt;=&lt;/span&gt;/bin/bash nginx:1.18.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;## ここからコンテナ内&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;OpenSSL 1.1.1d &lt;span class="m"&gt;10&lt;/span&gt; Sep &lt;span class="m"&gt;2019&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 秘密鍵(private-key.pem)の作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl genpkey -algorithm RSA -out private-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# オレオレ証明書(cert.pem)の作成(CSRの作成と署名)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# SANsの設定もやっておく(Chrome対応)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl req -x509 -key private-key.pem -out cert.pem -addext &lt;span class="s1"&gt;&amp;#39;subjectAltName = DNS:hogehoge.com,DNS:fugafuga.com&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;You are about to be asked to enter information that will be incorporated
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;into your certificate request.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;What you are about to enter is what is called a Distinguished Name or a DN.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;There are quite a few fields but you can leave some blank
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;For some fields there will be a default value,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;If you enter &lt;span class="s1"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;, the field will be left blank.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-----
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Country Name &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; letter code&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;AU&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;State or Province Name &lt;span class="o"&gt;(&lt;/span&gt;full name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Some-State&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Locality Name &lt;span class="o"&gt;(&lt;/span&gt;eg, city&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Organization Name &lt;span class="o"&gt;(&lt;/span&gt;eg, company&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Internet Widgits Pty Ltd&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Organizational Unit Name &lt;span class="o"&gt;(&lt;/span&gt;eg, section&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Common Name &lt;span class="o"&gt;(&lt;/span&gt;e.g. server FQDN or YOUR name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:hogehoge.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Email Address &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 証明書の中身を確認(SANsが追加されている)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl x509 -in cert.pem -noout -text
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Certificate:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Data:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Version: &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;0x2&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Serial Number:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 24:4c:ec:40:cc:94:5c:a2:af:30:6a:e9:7d:5c:17:28:5e:fb:ec:fc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Signature Algorithm: sha256WithRSAEncryption
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Issuer: &lt;span class="nv"&gt;C&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; AU, &lt;span class="nv"&gt;ST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; Some-State, &lt;span class="nv"&gt;O&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; Internet Widgits Pty Ltd, &lt;span class="nv"&gt;CN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; hogehoge.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Validity
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Not Before: Feb &lt;span class="m"&gt;10&lt;/span&gt; 16:13:01 &lt;span class="m"&gt;2021&lt;/span&gt; GMT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Not After : Mar &lt;span class="m"&gt;12&lt;/span&gt; 16:13:01 &lt;span class="m"&gt;2021&lt;/span&gt; GMT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Subject: &lt;span class="nv"&gt;C&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; AU, &lt;span class="nv"&gt;ST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; Some-State, &lt;span class="nv"&gt;O&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; Internet Widgits Pty Ltd, &lt;span class="nv"&gt;CN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; hogehoge.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; X509v3 extensions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; X509v3 Subject Alternative Name:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; DNS:hogehoge.com, DNS:fugafuga.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# コンテナから出る&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;exit&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;## ここからホストOS(Mac)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 秘密鍵と証明書ができている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cert.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;private-key.pem&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;次に&lt;code&gt;SANs&lt;/code&gt;に指定した&lt;strong&gt;hogehoge.com&lt;/strong&gt;で&lt;strong&gt;localhost&lt;/strong&gt;(&lt;strong&gt;127.0.0.1&lt;/strong&gt;)にアクセスできるよう,&lt;br&gt;
&lt;code&gt;Mac&lt;/code&gt;(&lt;code&gt;Prometheus&lt;/code&gt;を起動するマシン)の名前解決設定(&lt;code&gt;/etc/hosts&lt;/code&gt;)を編集する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# /etc/hostsにhogehoge.com(localhost)を追加&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;127.0.0.1 hogehoge.com&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sudo tee -a /etc/hosts&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;最後に今回作った証明書(&lt;code&gt;cert.pem&lt;/code&gt;)は公的な認証局が署名したものではないので,&lt;br&gt;
証明書を&lt;code&gt;Mac&lt;/code&gt;の&lt;code&gt;キーチェーンアクセス&lt;/code&gt;で開いて常に信頼するよう設定する.&lt;/p&gt;
&lt;p&gt;&lt;img alt="キーチェーンアクセスで開く" class="gallery-image" data-flex-basis="372px" data-flex-grow="155" height="834" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc01.png" srcset="https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc01_hu_c5c7e2955abdfb64.png 800w, https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc01.png 1294w" width="1294"&gt;
&lt;img alt="信頼設定を変更" class="gallery-image" data-flex-basis="275px" data-flex-grow="114" height="1088" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc02.png" srcset="https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc02_hu_26231777f865713c.png 800w, https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc02.png 1250w" width="1250"&gt;&lt;/p&gt;
&lt;p&gt;これで&lt;code&gt;HTTPS&lt;/code&gt;化に必要な証明書の設定は完了.&lt;/p&gt;
&lt;h3 id="nginxを挟んでhttps化する"&gt;nginxを挟んでHTTPS化する
&lt;/h3&gt;&lt;p&gt;次に公式の手順&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;に従って&lt;code&gt;nginx&lt;/code&gt;を&lt;code&gt;HTTPS&lt;/code&gt;化して, その後ろで&lt;code&gt;Prometheus&lt;/code&gt;が動く構成(リバースプロキシ)をつくる.&lt;/p&gt;
&lt;p&gt;今回も例に依って&lt;code&gt;Docker Compose&lt;/code&gt;で試すが, 非コンテナ環境の場合はコンテナ名で名前解決している部分を適切な名前(ホスト名)に置き換えて,&lt;br&gt;
&lt;code&gt;docker-compose.yml&lt;/code&gt;で指定している場所に各種の設定ファイルを配置すれば動くはず.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Prometheus&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2020-01-29-nginx/" target="_blank" rel="noopener"
 &gt;リバースプロキシ用の設定&lt;/a&gt;を引数で設定
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--web.external-url&lt;/code&gt; : 証明書の&lt;code&gt;SANs&lt;/code&gt;に指定した名前+リクエストを受け付けるパス&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--web.route-prefix&lt;/code&gt; : &lt;code&gt;/&lt;/code&gt;を明示的に指定&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nginx&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Prometheus&lt;/code&gt;のリバースプロキシとHTTPSの設定を&lt;code&gt;https.conf&lt;/code&gt;に記述する&lt;/li&gt;
&lt;li&gt;秘密鍵, 証明書を指定の場所に配置する&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;script src="https://gist.github.com/uzimihsr/ff1582fe112c2f5ba908b0c835ccfbb5.js"&gt;&lt;/script&gt;
&lt;script src="https://gist.github.com/uzimihsr/be6894488f63c4f9664d6d43b7d64c44.js"&gt;&lt;/script&gt;
&lt;p&gt;コンテナを立ち上げてみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# cert.pemとprivate-key.pemは先ほど作ったオレオレ証明書と秘密鍵&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ tree .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── cert.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── docker-compose.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── https.conf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── private-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# コンテナ起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-compose up -d --force-recreate --remove-orphans
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# localhostの443ポートがnginxコンテナに割り当てられている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-compose ps
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Name Command State Ports
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;----------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nginx /docker-entrypoint.sh ngin ... Up 0.0.0.0:443-&amp;gt;443/tcp, 80/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;prometheus /bin/prometheus --config.f ... Up 9090/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# オレオレ証明書(cert.pem)を信頼する設定でPrometheus APIを叩いてみる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl --cacert ./cert.pem https://hogehoge.com/prometheus/api/v1/label/job/values
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;status&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;success&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;data&amp;#34;&lt;/span&gt;:&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;prometheus&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;]}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;コンテナが立ち上がり, &lt;strong&gt;hogehoge.com&lt;/strong&gt;が&lt;code&gt;HTTPS&lt;/code&gt;で公開されていることが確認できた.&lt;/p&gt;
&lt;p&gt;念の為&lt;code&gt;Chrome&lt;/code&gt;で&lt;a class="link" href="https://hogehoge.com/prometheus/" target="_blank" rel="noopener"
 &gt;https://hogehoge.com/prometheus/&lt;/a&gt;を開いてみる.&lt;/p&gt;
&lt;p&gt;&lt;img alt="HTTPSで開けた" class="gallery-image" data-flex-basis="990px" data-flex-grow="412" height="698" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc03.png" srcset="https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc03_hu_88aa663672c9a60e.png 800w, https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc03_hu_8872e9cd19ee5a2d.png 1600w, https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc03_hu_7f381bc2a349af02.png 2400w, https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc03.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="オレオレ証明書が信頼されている" class="gallery-image" data-flex-basis="758px" data-flex-grow="316" height="911" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc04.png" srcset="https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc04_hu_26aa4e13f13d4e22.png 800w, https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc04_hu_287ab40c72225c77.png 1600w, https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc04_hu_df98ebaf3c967048.png 2400w, https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc04.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Prometheus&lt;/code&gt;が&lt;code&gt;HTTPS&lt;/code&gt;で公開されていて, &lt;code&gt;Chrome&lt;/code&gt;がオレオレ証明書を信頼していることが確認できた.&lt;/p&gt;
&lt;h3 id="prometheus単独でhttps化する"&gt;Prometheus単独でHTTPS化する
&lt;/h3&gt;&lt;p&gt;今まで&lt;code&gt;Prometheus&lt;/code&gt;を&lt;code&gt;HTTPS&lt;/code&gt;化する際は先ほど試したようにリバースプロキシを使うのが推奨されていたのだが,&lt;/p&gt;
&lt;p&gt;なんと&lt;strong&gt;version 2.24&lt;/strong&gt;からは&lt;code&gt;Prometheus&lt;/code&gt;単独での&lt;code&gt;HTTPS&lt;/code&gt;化にも対応した&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;らしい(まだお試し機能らしいが)ので試してみる.&lt;/p&gt;
&lt;p&gt;まずは新しい&lt;code&gt;HTTPS&lt;/code&gt;関連の設定ファイル&lt;code&gt;web-config.yml&lt;/code&gt;&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;で証明書と秘密鍵の場所を指定する.&lt;br&gt;
(この他にもクライアント認証やBasic認証も設定できるらしい.)&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/30513fef5f5eda0abdbe13a01a28eb0c.js"&gt;&lt;/script&gt;
&lt;p&gt;次に&lt;code&gt;Prometheus&lt;/code&gt;の実行時引数&lt;code&gt;--web.config.file&lt;/code&gt;で&lt;code&gt;web-config.yml&lt;/code&gt;の場所を指定する.&lt;br&gt;
また, &lt;strong&gt;hogehoge.com&lt;/strong&gt;でアクセスを受けられるように&lt;code&gt;--web.external-url&lt;/code&gt;を設定する(&lt;code&gt;nginx&lt;/code&gt;を使う場合と異なり&lt;code&gt;/prometheus&lt;/code&gt;は不要).&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/6f718ca17017388be63040390e815ad4.js"&gt;&lt;/script&gt;
&lt;p&gt;コンテナを立ち上げてみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# cert.pemとprivate-key.pemは先ほど作ったオレオレ証明書と秘密鍵&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ tree .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── cert.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── docker-compose.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── private-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── web-config.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# コンテナ起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-compose up -d --force-recreate --remove-orphans
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# localhostの443ポートがPrometheusコンテナに割り当てられている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-compose ps
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Name Command State Ports
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;------------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;prometheus /bin/prometheus --config.f ... Up 0.0.0.0:443-&amp;gt;443/tcp, 9090/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# オレオレ証明書(cert.pem)を信頼する設定でPrometheus APIを叩いてみる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl --cacert ./cert.pem https://hogehoge.com/api/v1/label/job/values
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;status&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;success&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;data&amp;#34;&lt;/span&gt;:&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;prometheus&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;]}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;次に&lt;code&gt;Chrome&lt;/code&gt;で&lt;a class="link" href="https://hogehoge.com/" target="_blank" rel="noopener"
 &gt;https://hogehoge.com/&lt;/a&gt;を開くと, &lt;code&gt;nginx&lt;/code&gt;を使ったときと同様に&lt;code&gt;Prometheus&lt;/code&gt;が&lt;code&gt;HTTPS&lt;/code&gt;で公開されていることがわかる.&lt;/p&gt;
&lt;p&gt;&lt;img alt="HTTPSで起動している" class="gallery-image" data-flex-basis="768px" data-flex-grow="320" height="900" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc05.png" srcset="https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc05_hu_a34bc58e36b0f24d.png 800w, https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc05_hu_991c83e62adf7dd2.png 1600w, https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc05_hu_1b9b6811a69023f2.png 2400w, https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc05.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;やったぜ.&lt;/p&gt;
&lt;p&gt;ただし&lt;code&gt;nginx&lt;/code&gt;を使う場合には無かった注意点として, 今回は&lt;code&gt;Prometheus&lt;/code&gt;自身が&lt;code&gt;HTTPS&lt;/code&gt;で起動しているため,&lt;br&gt;
自身のメトリクス(&lt;code&gt;/metrics&lt;/code&gt;)のスクレイプ設定がデフォルトのままだとプロトコルが&lt;code&gt;HTTP&lt;/code&gt;のままなのでスクレイプに失敗する.&lt;/p&gt;
&lt;p&gt;&lt;img alt="スクレイプに失敗している" class="gallery-image" data-flex-basis="939px" data-flex-grow="391" height="736" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc06.png" srcset="https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc06_hu_ddc7a0ccb915e6c2.png 800w, https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc06_hu_415d3800e118c901.png 1600w, https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc06_hu_72c93ea6bbdaf9f1.png 2400w, https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc06.png 2880w" width="2880"&gt;&lt;br&gt;
&lt;img alt="デフォルト設定だとHTTPでスクレイプしているのが原因" class="gallery-image" data-flex-basis="626px" data-flex-grow="261" height="1103" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc07.png" srcset="https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc07_hu_73e83af44ea0b609.png 800w, https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc07_hu_ca7f0bb9d0d182bd.png 1600w, https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc07_hu_bc07ad0740ee116a.png 2400w, https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sc07.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;今回はとりあえず&lt;code&gt;Prometheus&lt;/code&gt;を&lt;code&gt;HTTPS&lt;/code&gt;化するのが目的だったので, ここでおわり.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Prometheus&lt;/code&gt;を&lt;code&gt;HTTPS&lt;/code&gt;化してみた.&lt;br&gt;
&lt;code&gt;nginx&lt;/code&gt;を使う方法はそれはそう&amp;hellip;という感じだけど, &lt;code&gt;Prometheus&lt;/code&gt;単体で&lt;code&gt;HTTPS&lt;/code&gt;化できるのは知らなかった.&lt;/p&gt;
&lt;p&gt;ただし&lt;code&gt;Prometheus&lt;/code&gt;単独での&lt;code&gt;HTTPS&lt;/code&gt;対応はまだお試し機能っぽいのと,&lt;br&gt;
&lt;code&gt;Alertmanager&lt;/code&gt;はまだ対応してない?みたいなので, 併せて対応する場合は&lt;code&gt;nginx&lt;/code&gt;を使うように統一したほうが良さそう.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="顔をつよめに撫でられるのがすきなねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sotochan_hu_3b60ad5961443852.jpg 800w, https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sotochan_hu_96191d8f48d3106c.jpg 1600w, https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sotochan_hu_76d9b7fb22a5f01d.jpg 2400w, https://blog.uzimihsr.com/post/2021-02-11-prometheus-tls-ssl/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a class="link" href="https://prometheus.io/docs/guides/tls-encryption/" target="_blank" rel="noopener"
 &gt;https://prometheus.io/docs/guides/tls-encryption/&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;a class="link" href="https://prometheus.io/docs/prometheus/latest/configuration/https/" target="_blank" rel="noopener"
 &gt;https://prometheus.io/docs/prometheus/latest/configuration/https/&lt;/a&gt;&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/prometheus/prometheus/blob/master/documentation/examples/web-config.yml" target="_blank" rel="noopener"
 &gt;https://github.com/prometheus/prometheus/blob/master/documentation/examples/web-config.yml&lt;/a&gt;&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>PrometheusとAlertmanagerの冗長構成を試す</title><link>https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/</link><pubDate>Sun, 07 Feb 2021 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sotochan.jpg" alt="Featured image of post PrometheusとAlertmanagerの冗長構成を試す" /&gt;&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;同じ設定の&lt;code&gt;Prometheus&lt;/code&gt;を単純に複数台動かして冗長化した&lt;/li&gt;
&lt;li&gt;複数台の&lt;code&gt;Alertmanager&lt;/code&gt;をメッシュとして動かして冗長化した&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;Prometheus&lt;/code&gt;と&lt;code&gt;Alertmanager&lt;/code&gt;でサービスを監視するのは良いんだけど, 1台ずつで運用してると監視コンポーネント自身がダウンしたときに監視できなくなってしまう.&lt;/p&gt;
&lt;p&gt;だったら監視コンポーネント自体も冗長化すれば可用性を上げられるのでは?と思い試してみた.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Prometheus&lt;/code&gt;の時系列DBの冗長化はかなり難しいっぽいので今回はやらない.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Prometheus&lt;/code&gt;は単純に同じ設定のものを複数同時に動かし, &lt;code&gt;Alertmanager&lt;/code&gt;は複数台を同期してメッシュとして動かすのが良さそう.&lt;/p&gt;
&lt;p&gt;&lt;img alt="冗長化のイメージ" class="gallery-image" data-flex-basis="694px" data-flex-grow="289" height="716" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/component.png" srcset="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/component_hu_ec060de149b81f22.png 800w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/component_hu_e17b5038471ca03d.png 1600w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/component.png 2072w" width="2072"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/uzimihsr/prometheus-high-availability-example" target="_blank" rel="noopener"
 &gt;設定ファイルとか&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Mojave 10.14&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/editions/community/docker-ce-desktop-mac" target="_blank" rel="noopener"
 &gt;Docker Desktop for Mac&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Version 3.1.0&lt;/li&gt;
&lt;li&gt;Docker Engine Version 20.10.2&lt;/li&gt;
&lt;li&gt;docker-compose version 1.27.4&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/prometheus/prometheus" target="_blank" rel="noopener"
 &gt;Prometheus&lt;/a&gt; (Docker)
&lt;ul&gt;
&lt;li&gt;version &lt;a class="link" href="https://hub.docker.com/layers/prom/prometheus/v2.24.1/images/sha256-f4a858861e05c8611cdb5867a07e48742b8295400a5993ac05ad1ee67e6d5696?context=explore" target="_blank" rel="noopener"
 &gt;2.24.1&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/prometheus/alertmanager" target="_blank" rel="noopener"
 &gt;Alertmanager&lt;/a&gt; (Docker)
&lt;ul&gt;
&lt;li&gt;version &lt;a class="link" href="https://hub.docker.com/layers/prom/alertmanager/v0.21.0/images/sha256-913293083cb14085bfc01018bb30d1dcbbc9ed197ae21ef2ca917b0d29265198?context=explore" target="_blank" rel="noopener"
 &gt;0.21.0&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/grafana/grafana" target="_blank" rel="noopener"
 &gt;Grafana&lt;/a&gt; (Docker)
&lt;ul&gt;
&lt;li&gt;version &lt;a class="link" href="https://hub.docker.com/layers/grafana/grafana/7.3.7/images/sha256-f140fde5ba622745926b1e390b6ff335c1a0b7a1126cd4211600534f922ef4c0?context=explore" target="_blank" rel="noopener"
 &gt;7.3.7&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/nginx/nginx" target="_blank" rel="noopener"
 &gt;nginx&lt;/a&gt; (Docker)
&lt;ul&gt;
&lt;li&gt;version &lt;a class="link" href="https://hub.docker.com/layers/nginx/library/nginx/1.18.0/images/sha256-6907ea1bf7f121ae60f040dbca1ac676f42157face02d769cb8e39abdcd9b4fe?context=explore" target="_blank" rel="noopener"
 &gt;1.18.0&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#prometheus%e3%82%92%e5%86%97%e9%95%b7%e5%8c%96%e3%81%99%e3%82%8b" &gt;Prometheusを冗長化する&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#alertmanager%e3%82%82%e5%86%97%e9%95%b7%e5%8c%96%e3%81%99%e3%82%8b" &gt;Alertmanagerも冗長化する&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="prometheusを冗長化する"&gt;Prometheusを冗長化する
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Prometheus&lt;/code&gt;公式のFAQによると可用性を高めるには&lt;br&gt;
「同じ設定のものを複数台動かせ. 複数の&lt;code&gt;Prometheus&lt;/code&gt;で同じアラートが発火した場合でも&lt;code&gt;Alertmanager&lt;/code&gt;側で勝手に重複排除してくれる.(意訳)」&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;br&gt;
とのこと. 単純で良い.&lt;/p&gt;
&lt;p&gt;とりあえず&lt;code&gt;Prometheus&lt;/code&gt;を3台立てて&lt;code&gt;nginx&lt;/code&gt;で負荷分散(ラウンドロビン)する&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;ような構成を&lt;code&gt;Docker Compose&lt;/code&gt;で作ってみた.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/e59384b26251d76d497dea17908bed7a.js"&gt;&lt;/script&gt;
&lt;p&gt;その他の設定は下記のとおり.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Prometheus&lt;/code&gt; x3
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;prometheus.yml&lt;/code&gt; : 互いを監視するような設定を入れる&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rules.yml&lt;/code&gt; : 任意の設定&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Alertmanager&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;alertmanager.yml&lt;/code&gt; : 任意の設定&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Grafana&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;grafana.ini&lt;/code&gt; : 任意の設定(リバースプロキシ対応)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;datasource.yaml&lt;/code&gt; : &lt;code&gt;Prometheus&lt;/code&gt;をData Sourceとする設定&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nginx&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;default.conf&lt;/code&gt; : &lt;code&gt;Prometheus&lt;/code&gt;のロードバランシング設定(やらなくても良い)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;Prometheus&lt;/code&gt;, &lt;code&gt;Alertmanager&lt;/code&gt;, &lt;code&gt;Grafana&lt;/code&gt;のリバースプロキシ設定は&lt;a class="link" href="https://uzimihsr.github.io/post/2021-02-05-run-prometheus-and-grafana-on-docker/" target="_blank" rel="noopener"
 &gt;前回やったとき&lt;/a&gt;とほぼ同じだけど, 今回の目的は&lt;code&gt;Prometheus&lt;/code&gt;の冗長化なのでここらへんはやらなくても良い.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/2b72642a24005f15dabe66702d195430.js"&gt;&lt;/script&gt;
&lt;p&gt;&lt;code&gt;rules.yml&lt;/code&gt;, &lt;code&gt;alertmanager.yml&lt;/code&gt;の設定は有効なものなら何でも良いので&lt;a class="link" href="https://uzimihsr.github.io/post/2021-02-05-run-prometheus-and-grafana-on-docker/" target="_blank" rel="noopener"
 &gt;前回&lt;/a&gt;と同じものを使う.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;grafana.ini&lt;/code&gt;も一応&lt;a class="link" href="https://uzimihsr.github.io/post/2021-02-05-run-prometheus-and-grafana-on-docker/#%e3%83%aa%e3%83%90%e3%83%bc%e3%82%b9%e3%83%97%e3%83%ad%e3%82%ad%e3%82%b7%e3%81%99%e3%82%8b" target="_blank" rel="noopener"
 &gt;前回&lt;/a&gt;と同じものを使うけど今回の目的はあくまで&lt;code&gt;Prometheus&lt;/code&gt;の冗長化なのでデフォルト設定のままでも良い.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/cb3cb54ac29ecae0049e46981785ce4f.js"&gt;&lt;/script&gt;
&lt;script src="https://gist.github.com/uzimihsr/fae9918a0f3061719f614c9b186c08fe.js"&gt;&lt;/script&gt;
&lt;p&gt;設定ファイルが準備できたらコンテナを立ち上げる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ディレクトリ構成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ tree .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── deployment
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   ├── alertmanager
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   │   └── alertmanager.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   ├── grafana
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   │   ├── datasource.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   │   └── grafana.ini
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   ├── nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   │   └── default.conf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   └── prometheus
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   ├── prometheus.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   └── rules.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── docker-compose.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# コンテナ起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-compose up -d --force-recreate
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-compose ps
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Name Command State Ports
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;alertmanager /bin/alertmanager --config ... Up 9093/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grafana /run.sh Up 3000/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nginx /docker-entrypoint.sh ngin ... Up 0.0.0.0:80-&amp;gt;80/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;prometheus-01 /bin/prometheus --config.f ... Up 9090/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;prometheus-02 /bin/prometheus --config.f ... Up 9090/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;prometheus-03 /bin/prometheus --config.f ... Up 9090/tcp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;nginx&lt;/code&gt;で80番ポートが開けてあるので, &lt;a class="link" href="http://localhost/prometheus/" target="_blank" rel="noopener"
 &gt;http://localhost/prometheus/&lt;/a&gt;を開くと&lt;code&gt;Prometheus&lt;/code&gt;が起動していることを確認できる.&lt;/p&gt;
&lt;p&gt;画面上ではどの&lt;code&gt;Prometheus&lt;/code&gt;コンテナがレスポンスを返しているのかわからないが, 実際には&lt;code&gt;nginx&lt;/code&gt;により1台ずつ順番にリクエストを受け付けている(ラウンドロビン). はず. 　&lt;/p&gt;
&lt;p&gt;&lt;img alt="動作確認" class="gallery-image" data-flex-basis="403px" data-flex-grow="168" height="1713" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc01.png" srcset="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc01_hu_4faaf0f911367e00.png 800w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc01_hu_5d1b98516043739c.png 1600w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc01_hu_6b3dd28aa4c5824d.png 2400w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc01.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="http://localhost/grafana" target="_blank" rel="noopener"
 &gt;http://localhost/grafana&lt;/a&gt;を開き&lt;code&gt;Grafana&lt;/code&gt;でダッシュボードを作成する.&lt;/p&gt;
&lt;p&gt;Data Sourceとして&lt;code&gt;nginx&lt;/code&gt;の&lt;code&gt;Prometheus&lt;/code&gt;用エンドポイントと念の為それぞれの&lt;code&gt;Prometheus&lt;/code&gt;3台のエンドポイントを設定してあるのでそれぞれのData Sourceに対して同じメトリクス(&lt;strong&gt;up&lt;/strong&gt;)のダッシュボードを作ってみる.&lt;/p&gt;
&lt;p&gt;余談だけど今回は&lt;code&gt;nginx&lt;/code&gt;ロードバランサの下で複数台の&lt;code&gt;Prometheus&lt;/code&gt;を動かしているので, &lt;code&gt;Grafana&lt;/code&gt;のData Sourceが&lt;code&gt;nginx&lt;/code&gt;上の&lt;code&gt;Prometheus&lt;/code&gt;エンドポイントを見ている場合はロードするたびに微妙にグラフ(メトリクス)が変わったりする.&lt;/p&gt;
&lt;p&gt;この挙動が気持ち悪い場合は&lt;code&gt;nginx&lt;/code&gt;上のエンドポイントじゃなくて個別の&lt;code&gt;Prometheus&lt;/code&gt;をData Sourceにするほうが良いかもしれない(あとで気づいた).&lt;/p&gt;
&lt;p&gt;&lt;img alt="Data Sourceは複数設定済み" class="gallery-image" data-flex-basis="403px" data-flex-grow="168" height="1712" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc02.png" srcset="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc02_hu_73967f3d267401d1.png 800w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc02_hu_20f9bf62cc96b32b.png 1600w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc02_hu_bb9f0826e3285485.png 2400w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc02.png 2880w" width="2880"&gt;
&lt;img alt="作成したダッシュボード" class="gallery-image" data-flex-basis="403px" data-flex-grow="168" height="1713" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc03.png" srcset="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc03_hu_21d4a6f23469ed98.png 800w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc03_hu_ba4db3974c5eb389.png 1600w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc03_hu_e23a5ab1c0a8da56.png 2400w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc03.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;この状態で3台ある&lt;code&gt;Prometheus&lt;/code&gt;を一部落としてみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Prometheusを2台落とす&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-compose stop prometheus-01 prometheus-02
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-compose ps
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Name Command State Ports
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;----------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;alertmanager /bin/alertmanager --config ... Up 9093/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grafana /run.sh Up 3000/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nginx /docker-entrypoint.sh ngin ... Up 0.0.0.0:80-&amp;gt;80/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;prometheus-01 /bin/prometheus --config.f ... Exit &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;prometheus-02 /bin/prometheus --config.f ... Exit &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;prometheus-03 /bin/prometheus --config.f ... Up 9090/tcp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;1台目と2台目の&lt;code&gt;Prometheus&lt;/code&gt;を落としたので, 3台目の&lt;code&gt;Prometheus&lt;/code&gt;でInstanceDownのアラートが発火する.&lt;/p&gt;
&lt;p&gt;&lt;img alt="1台目と2台目のPrometheusが落ちた" class="gallery-image" data-flex-basis="403px" data-flex-grow="168" height="1713" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc04.png" srcset="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc04_hu_a2cf4988358c6a93.png 800w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc04_hu_c8635ec014835607.png 1600w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc04_hu_628bccc4258831cc.png 2400w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc04.png 2880w" width="2880"&gt;
&lt;img alt="アラート発火" class="gallery-image" data-flex-basis="403px" data-flex-grow="168" height="1713" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc05.png" srcset="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc05_hu_967a1ae33a39896c.png 800w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc05_hu_160bfbb01ec484c9.png 1600w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc05_hu_40d18ca177084a6d.png 2400w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc05.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;Alertmanagerが反応し, アラートの通知が届く.&lt;br&gt;
(通知は&lt;a class="link" href="https://uzimihsr.github.io/post/2020-01-27-alertmanager-gmail/" target="_blank" rel="noopener"
 &gt;AlertmanagerからGmail経由で送る&lt;/a&gt;設定にしている)&lt;/p&gt;
&lt;p&gt;&lt;img alt="アラート対応" class="gallery-image" data-flex-basis="403px" data-flex-grow="167" height="1715" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc06.png" srcset="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc06_hu_b9b72ae0f72ac497.png 800w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc06_hu_fb252ce306da908e.png 1600w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc06_hu_fe52777423e35c16.png 2400w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc06.png 2880w" width="2880"&gt;
&lt;img alt="通知" class="gallery-image" data-flex-basis="435px" data-flex-grow="181" height="1587" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc07.png" srcset="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc07_hu_e5faf094aeacd13b.png 800w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc07_hu_917b36af91352af.png 1600w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc07_hu_1616ab57afa0a5aa.png 2400w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc07.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;冗長構成にしたおかげで複数台用意した&lt;code&gt;Prometheus&lt;/code&gt;が一部落ちてもメトリクスは継続して収集されていることと,&lt;br&gt;
相互監視の設定により一部が落ちた場合にも残りの&lt;code&gt;Prometheus&lt;/code&gt;でアラートが発火して検知できることが確認できた.&lt;/p&gt;
&lt;p&gt;今度は&lt;code&gt;Alertmanager&lt;/code&gt;で複数の&lt;code&gt;Prometheus&lt;/code&gt;から送られた同じアラートが重複排除されることを確かめるため, 3台目の&lt;code&gt;Prometheus&lt;/code&gt;だけを落としてみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Prometheusを復旧させる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-compose start prometheus-01 prometheus-02
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 3台目だけを落とす&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-compose stop prometheus-03
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-compose ps
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Name Command State Ports
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;----------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;alertmanager /bin/alertmanager --config ... Up 9093/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grafana /run.sh Up 3000/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nginx /docker-entrypoint.sh ngin ... Up 0.0.0.0:80-&amp;gt;80/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;prometheus-01 /bin/prometheus --config.f ... Up 9090/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;prometheus-02 /bin/prometheus --config.f ... Up 9090/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;prometheus-03 /bin/prometheus --config.f ... Exit &lt;span class="m"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;今度は3台目の&lt;code&gt;Prometheus&lt;/code&gt;が落ちたので, 1台目と2台目の&lt;code&gt;Prometheus&lt;/code&gt;で同じInstanceDownのアラートが発生する.&lt;/p&gt;
&lt;p&gt;&lt;img alt="3台目のPrometheusが落ちた" class="gallery-image" data-flex-basis="403px" data-flex-grow="167" height="1715" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc08.png" srcset="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc08_hu_64dda2b17476865f.png 800w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc08_hu_387eb5b04298c1fd.png 1600w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc08_hu_bd869ed0531654b2.png 2400w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc08.png 2880w" width="2880"&gt;
&lt;img alt="1台目と2台目のPrometheusでそれぞれアラートが発火" class="gallery-image" data-flex-basis="403px" data-flex-grow="168" height="1714" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc09.png" srcset="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc09_hu_27dbb19e162921b4.png 800w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc09_hu_63708af4fe309c20.png 1600w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc09_hu_2b1ea18c131fefa8.png 2400w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc09.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;ただし&lt;code&gt;Alertmanager&lt;/code&gt;側で重複が排除されるようになっているので, アラートは1件として扱われて通知も1件のみ届く.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Alertmanager上のアラートは1件" class="gallery-image" data-flex-basis="403px" data-flex-grow="168" height="1713" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc10.png" srcset="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc10_hu_89600e2636f77c79.png 800w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc10_hu_ef9a12c69aab791e.png 1600w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc10_hu_3efa23be83213e4e.png 2400w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc10.png 2880w" width="2880"&gt;
&lt;img alt="通知も1件のみ" class="gallery-image" data-flex-basis="436px" data-flex-grow="181" height="1584" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc11.png" srcset="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc11_hu_11560a5f8c5926cc.png 800w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc11_hu_99dba7c0ad9b6071.png 1600w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc11_hu_374397c2a88073cf.png 2400w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc11.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;以上で複数の&lt;code&gt;Prometheus&lt;/code&gt;で同じアラートが発火した場合でも&lt;code&gt;Alertmanager&lt;/code&gt;で重複排除されることが確認できた.&lt;/p&gt;
&lt;h3 id="alertmanagerも冗長化する"&gt;Alertmanagerも冗長化する
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Prometheus&lt;/code&gt;は冗長化できたが, &lt;code&gt;Alertmanager&lt;/code&gt;だって絶対落ちないとは限らないのでこれも冗長化したい.&lt;/p&gt;
&lt;p&gt;ただし&lt;code&gt;Alertmanager&lt;/code&gt;の場合は実際に通知を送る機能があるため, &lt;code&gt;Prometheus&lt;/code&gt;のように単純に同じものを複数用意するのはあまり良い方法ではなさそう.&lt;br&gt;
(1つのアラートに対して複数の&lt;code&gt;Alertmanager&lt;/code&gt;がそれぞれ通知を送ってしまう)&lt;/p&gt;
&lt;p&gt;このため, 複数の&lt;code&gt;Alertmanager&lt;/code&gt;を同時に動かす場合は互いの状況を知るためにメッシュを構成する&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;難しそうに思えるが&lt;code&gt;Alertmanager&lt;/code&gt;の冗長化機能はあらかじめ有効化されているので, 実行時引数&lt;code&gt;--cluster.peer&lt;/code&gt;で同時に動かす対象のホスト名を指定してやれば良い.&lt;br&gt;
(相互の確認に使うポートは&lt;strong&gt;9093&lt;/strong&gt;でなく&lt;strong&gt;9094&lt;/strong&gt;であることに注意)&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/2fc77490960ab361c971a22fccb70db2.js"&gt;&lt;/script&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Prometheus&lt;/code&gt; x3
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;prometheus.yml&lt;/code&gt; : 監視対象とアラートを送る対象に複数の&lt;code&gt;Alertmanager&lt;/code&gt;を追加する(必須)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rules.yml&lt;/code&gt; : そのまま&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Alertmanager&lt;/code&gt; x3
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;alertmanager.yml&lt;/code&gt; : そのまま&lt;/li&gt;
&lt;li&gt;実行時引数&lt;code&gt;--cluster.peer&lt;/code&gt;で他の&lt;code&gt;Alertmanager&lt;/code&gt;を指定(必須)&lt;/li&gt;
&lt;li&gt;動作確認用に9093番ポートを疎通可能にしておく(やらなくても良い)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Grafana&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;grafana.ini&lt;/code&gt; : そのまま&lt;/li&gt;
&lt;li&gt;&lt;code&gt;datasource.yaml&lt;/code&gt; : そのまま&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nginx&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;default.conf&lt;/code&gt; : 複数の&lt;code&gt;Alertmanager&lt;/code&gt;のロードバランシング設定を追加(やらなくても良い)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;prometheus.yml&lt;/code&gt;でアラートの送信先を指定する際は&lt;code&gt;nginx&lt;/code&gt;で負荷分散している&lt;code&gt;Alertmanager&lt;/code&gt;のエンドポイント(&lt;code&gt;/alertmanager&lt;/code&gt;)を指定したくなるが,&lt;br&gt;
公式FAQによると「&lt;code&gt;Prometheus&lt;/code&gt;からはすべての&lt;code&gt;Alertmanager&lt;/code&gt;にアラートを送れ」とあるので今回はそれに従っている.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/d7b879709025b12e6a07c4b2f6b723b5.js"&gt;&lt;/script&gt;
&lt;script src="https://gist.github.com/uzimihsr/4afbba88a2a2003e1b3d4bedfd65ebb1.js"&gt;&lt;/script&gt;
&lt;p&gt;設定ファイルが準備できたら再度コンテナを立ち上げる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ディレクトリ構成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ tree .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── deployment
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   ├── alertmanager
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   │   └── alertmanager.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   ├── grafana
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   │   ├── datasource.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   │   └── grafana.ini
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   ├── nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   │   └── default.conf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   └── prometheus
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   ├── prometheus.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   └── rules.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── docker-compose.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# コンテナ起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-compose up -d --force-recreate --remove-orphans
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 今回は動作確認用にlocalhostから直接Alertmanagerにつながるようにしている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-compose ps
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Name Command State Ports
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;alertmanager-01 /bin/alertmanager --config ... Up 0.0.0.0:8093-&amp;gt;9093/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;alertmanager-02 /bin/alertmanager --config ... Up 0.0.0.0:8094-&amp;gt;9093/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;alertmanager-03 /bin/alertmanager --config ... Up 0.0.0.0:8095-&amp;gt;9093/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grafana /run.sh Up 3000/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nginx /docker-entrypoint.sh ngin ... Up 0.0.0.0:80-&amp;gt;80/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;prometheus-01 /bin/prometheus --config.f ... Up 9090/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;prometheus-02 /bin/prometheus --config.f ... Up 9090/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;prometheus-03 /bin/prometheus --config.f ... Up 9090/tcp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;まずはそれぞれの&lt;code&gt;Alertmanager&lt;/code&gt;を開いてメッシュが有効になっていることを確認する.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;alertmanager-01 : &lt;a class="link" href="http://localhost:8093/#/status" target="_blank" rel="noopener"
 &gt;http://localhost:8093/#/status&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;alertmanager-02 : &lt;a class="link" href="http://localhost:8094/#/status" target="_blank" rel="noopener"
 &gt;http://localhost:8094/#/status&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;alertmanager-03 : &lt;a class="link" href="http://localhost:8095/#/status" target="_blank" rel="noopener"
 &gt;http://localhost:8095/#/status&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;Cluster Status&lt;/code&gt;を見るとそれぞれの&lt;code&gt;Name&lt;/code&gt;を互いに&lt;code&gt;Peers&lt;/code&gt;として認識していることがわかる.&lt;/p&gt;
&lt;p&gt;&lt;img alt="alertmanager-01" class="gallery-image" data-flex-basis="403px" data-flex-grow="168" height="1713" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc12.png" srcset="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc12_hu_395bc8e588523f15.png 800w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc12_hu_a49c14acc1de62de.png 1600w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc12_hu_1143f5de37472a8d.png 2400w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc12.png 2880w" width="2880"&gt;
&lt;img alt="alertmanager-02" class="gallery-image" data-flex-basis="403px" data-flex-grow="168" height="1714" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc13.png" srcset="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc13_hu_3aa83a4950b930df.png 800w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc13_hu_d4a3f158acf3f215.png 1600w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc13_hu_50c7de2c63500607.png 2400w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc13.png 2880w" width="2880"&gt;
&lt;img alt="alertmanager-03" class="gallery-image" data-flex-basis="402px" data-flex-grow="167" height="1716" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc14.png" srcset="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc14_hu_9cce29cc9fc7a895.png 800w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc14_hu_6bde00192bd995d9.png 1600w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc14_hu_4f2223ab35e4d131.png 2400w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc14.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;この状態で試しに1台目の&lt;code&gt;Alertmanager&lt;/code&gt;で&lt;code&gt;Silence&lt;/code&gt;(アラートを一時的に無視する設定)を作成してみる&lt;sup id="fnref:4"&gt;&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref"&gt;4&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="alertmanager-01で適当にSilenceを作成" class="gallery-image" data-flex-basis="403px" data-flex-grow="167" height="1715" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc15.png" srcset="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc15_hu_dceeed9988f01e25.png 800w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc15_hu_250bec53c59f9428.png 1600w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc15_hu_20769e09afeca436.png 2400w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc15.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;すると2台目と3台目の&lt;code&gt;Alertmanager&lt;/code&gt;にも同じ&lt;code&gt;Silence&lt;/code&gt;が勝手に作成されており, これで3台の&lt;code&gt;Alertmanager&lt;/code&gt;がメッシュとして正しく動作していることがわかる.&lt;/p&gt;
&lt;p&gt;&lt;img alt="alertmanager-01" class="gallery-image" data-flex-basis="403px" data-flex-grow="168" height="1714" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc16.png" srcset="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc16_hu_cda0e674203a6ee3.png 800w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc16_hu_af8d40261279773a.png 1600w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc16_hu_d12aeeeaeb26bd18.png 2400w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc16.png 2880w" width="2880"&gt;
&lt;img alt="alertmanager-02" class="gallery-image" data-flex-basis="403px" data-flex-grow="167" height="1715" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc17.png" srcset="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc17_hu_303ee97ab213a9b4.png 800w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc17_hu_dc6a6b99aea48cf4.png 1600w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc17_hu_f32a1061680e8450.png 2400w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc17.png 2880w" width="2880"&gt;
&lt;img alt="alertmanager-03" class="gallery-image" data-flex-basis="403px" data-flex-grow="168" height="1713" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc18.png" srcset="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc18_hu_5040a4c8583f8f9.png 800w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc18_hu_1903f30370803647.png 1600w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc18_hu_8d6d17fae6610d4.png 2400w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc18.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;最後に&lt;code&gt;Alertmanager&lt;/code&gt;の動作確認のため, &lt;code&gt;Grafana&lt;/code&gt;を落としてInstanceDownのアラートを発火させてみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Grafanaを落とす&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-compose stop grafana
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-compose ps
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Name Command State Ports
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;----------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;alertmanager-01 /bin/alertmanager --config ... Up 0.0.0.0:8093-&amp;gt;9093/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;alertmanager-02 /bin/alertmanager --config ... Up 0.0.0.0:8094-&amp;gt;9093/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;alertmanager-03 /bin/alertmanager --config ... Up 0.0.0.0:8095-&amp;gt;9093/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grafana /run.sh Exit &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nginx /docker-entrypoint.sh ngin ... Up 0.0.0.0:80-&amp;gt;80/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;prometheus-01 /bin/prometheus --config.f ... Up 9090/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;prometheus-02 /bin/prometheus --config.f ... Up 9090/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;prometheus-03 /bin/prometheus --config.f ... Up 9090/tcp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;今までと同じくupが0になり, &lt;code&gt;Prometheus&lt;/code&gt;でアラートが発火する.&lt;br&gt;
&lt;img alt="upメトリクスが変化" class="gallery-image" data-flex-basis="403px" data-flex-grow="168" height="1713" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc19.png" srcset="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc19_hu_9587f44c3f96087d.png 800w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc19_hu_5d1e22084ed5c948.png 1600w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc19_hu_2e704f22805b508e.png 2400w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc19.png 2880w" width="2880"&gt;
&lt;img alt="アラート発火" class="gallery-image" data-flex-basis="403px" data-flex-grow="168" height="1714" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc20.png" srcset="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc20_hu_dde60c2fc93f3a7f.png 800w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc20_hu_758e08e0aadaca86.png 1600w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc20_hu_748ed86e1e65056a.png 2400w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc20.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Alertmanager&lt;/code&gt;側でもアラートを受け取っているが,&lt;br&gt;
先程確認したとおり3台の&lt;code&gt;Alertmanager&lt;/code&gt;はメッシュとして動作しているのでそれぞれが動作して3回通知が送られるということはなく通知は1件のみ届く.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Alertmanager" class="gallery-image" data-flex-basis="403px" data-flex-grow="168" height="1714" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc21.png" srcset="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc21_hu_c1672ddb5bc2c8d6.png 800w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc21_hu_9de7e0943fd66b30.png 1600w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc21_hu_946c85eb67617d8b.png 2400w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc21.png 2880w" width="2880"&gt;
&lt;img alt="通知は1件だけ届く" class="gallery-image" data-flex-basis="384px" data-flex-grow="160" height="1800" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc22.png" srcset="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc22_hu_15cdf5e92c6805e2.png 800w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc22_hu_bcf882aae9982da3.png 1600w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc22_hu_c24961ec6930d2c2.png 2400w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sc22.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;やったぜ.&lt;br&gt;
&lt;code&gt;Prometheus&lt;/code&gt;だけでなく&lt;code&gt;Alertmanager&lt;/code&gt;も冗長構成で動かすことができた.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Prometheus&lt;/code&gt;と&lt;code&gt;Grafana&lt;/code&gt;を冗長構成で動かしてみた.&lt;/p&gt;
&lt;p&gt;今回は&lt;code&gt;Grafana&lt;/code&gt;の冗長化はしなかったけど, 落ちたところでグラフが見られなくなるくらいしか困ることがないのでやらなくて正解だったかも.&lt;br&gt;
(やったとしても&lt;code&gt;nginx&lt;/code&gt;の下に複数台ぶらさげるだけになりそう)&lt;/p&gt;
&lt;p&gt;今回は&lt;code&gt;Docker Compose&lt;/code&gt;で試してみたけど, 実際にそれぞれ別のサーバーで動かす場合もコンテナ名で名前解決している部分をホスト名に変えてやれば同様の動作になるはず.&lt;br&gt;
お金と時間に余裕があればVMとかで試してみたい(たぶんやらない).&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="トンネルの中で落ち着くねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sotochan_hu_9f23b3f4fd1bdf9d.jpg 800w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sotochan_hu_acee51dcfa0cfa5.jpg 1600w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sotochan_hu_f0538787c15c3052.jpg 2400w, https://blog.uzimihsr.com/post/2021-02-07-prometheus-alertmanager-high-availability/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a class="link" href="https://prometheus.io/docs/introduction/faq/#can-prometheus-be-made-highly-available" target="_blank" rel="noopener"
 &gt;https://prometheus.io/docs/introduction/faq/#can-prometheus-be-made-highly-available&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;a class="link" href="https://nginx.org/en/docs/http/ngx_http_upstream_module.html" target="_blank" rel="noopener"
 &gt;https://nginx.org/en/docs/http/ngx_http_upstream_module.html&lt;/a&gt;&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/prometheus/alertmanager#high-availability" target="_blank" rel="noopener"
 &gt;https://github.com/prometheus/alertmanager#high-availability&lt;/a&gt;&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:4"&gt;
&lt;p&gt;&lt;a class="link" href="https://www.robustperception.io/high-availability-prometheus-alerting-and-notification" target="_blank" rel="noopener"
 &gt;https://www.robustperception.io/high-availability-prometheus-alerting-and-notification&lt;/a&gt;&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>自作Exporter+Prometheus+Alertmanager+GrafanaをまとめてDocker Composeで動かす</title><link>https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/</link><pubDate>Fri, 05 Feb 2021 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sotochan.jpg" alt="Featured image of post 自作Exporter+Prometheus+Alertmanager+GrafanaをまとめてDocker Composeで動かす" /&gt;&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;自作Exporter, &lt;code&gt;Prometheus&lt;/code&gt;, &lt;code&gt;Alertmanager&lt;/code&gt;, &lt;code&gt;Grafana&lt;/code&gt;をまとめて&lt;code&gt;Docker Compose&lt;/code&gt;で動かした&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nginx&lt;/code&gt;コンテナを追加してリバースプロキシした&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;Prometheus&lt;/code&gt;用のExporterを自作するときに動作確認の時点で&lt;code&gt;Grafana&lt;/code&gt;のグラフが見られたり&lt;code&gt;Alertmanager&lt;/code&gt;で通知されるメッセージとかが確認できるとメトリクスやラベルの設計がしやすい(気がする)ので,&lt;br&gt;
それらが全部入りの環境を&lt;code&gt;Docker Compose&lt;/code&gt;で作ってみた.&lt;/p&gt;
&lt;p&gt;&lt;img alt="構成" class="gallery-image" data-flex-basis="400px" data-flex-grow="167" height="1054" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/component.png" srcset="https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/component_hu_33682b3a9caa1985.png 800w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/component_hu_9e39f56f91c97e3e.png 1600w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/component.png 1761w" width="1761"&gt;&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/9163171af48323662807d8db300c1d99.js"&gt;&lt;/script&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/uzimihsr/example-exporter/tree/ff85b3c8cea89d630ae308a8ea1b45d70973e7c8" target="_blank" rel="noopener"
 &gt;その他もろもろの設定ファイル&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Mojave 10.14&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/editions/community/docker-ce-desktop-mac" target="_blank" rel="noopener"
 &gt;Docker Desktop for Mac&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Version 3.1.0&lt;/li&gt;
&lt;li&gt;Docker Engine Version 20.10.2&lt;/li&gt;
&lt;li&gt;docker-compose version 1.27.4&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/prometheus/prometheus" target="_blank" rel="noopener"
 &gt;Prometheus&lt;/a&gt; (Docker)
&lt;ul&gt;
&lt;li&gt;version &lt;a class="link" href="https://hub.docker.com/layers/prom/prometheus/v2.24.1/images/sha256-f4a858861e05c8611cdb5867a07e48742b8295400a5993ac05ad1ee67e6d5696?context=explore" target="_blank" rel="noopener"
 &gt;2.24.1&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/prometheus/alertmanager" target="_blank" rel="noopener"
 &gt;Alertmanager&lt;/a&gt; (Docker)
&lt;ul&gt;
&lt;li&gt;version &lt;a class="link" href="https://hub.docker.com/layers/prom/alertmanager/v0.21.0/images/sha256-913293083cb14085bfc01018bb30d1dcbbc9ed197ae21ef2ca917b0d29265198?context=explore" target="_blank" rel="noopener"
 &gt;0.21.0&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/grafana/grafana" target="_blank" rel="noopener"
 &gt;Grafana&lt;/a&gt; (Docker)
&lt;ul&gt;
&lt;li&gt;version &lt;a class="link" href="https://hub.docker.com/layers/grafana/grafana/7.3.7/images/sha256-f140fde5ba622745926b1e390b6ff335c1a0b7a1126cd4211600534f922ef4c0?context=explore" target="_blank" rel="noopener"
 &gt;7.3.7&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/nginx/nginx" target="_blank" rel="noopener"
 &gt;nginx&lt;/a&gt; (Docker)
&lt;ul&gt;
&lt;li&gt;version &lt;a class="link" href="https://hub.docker.com/layers/nginx/library/nginx/1.18.0/images/sha256-6907ea1bf7f121ae60f040dbca1ac676f42157face02d769cb8e39abdcd9b4fe?context=explore" target="_blank" rel="noopener"
 &gt;1.18.0&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/uzimihsr/example-exporter" target="_blank" rel="noopener"
 &gt;自作Exporter&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;2112番ポートで起動できて&lt;code&gt;Docker&lt;/code&gt;コンテナ化できるものなら何でも良い&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%a8%e3%82%8a%e3%81%82%e3%81%88%e3%81%9a%e8%b5%b7%e5%8b%95%e3%81%99%e3%82%8b" &gt;とりあえず起動する&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%aa%e3%83%90%e3%83%bc%e3%82%b9%e3%83%97%e3%83%ad%e3%82%ad%e3%82%b7%e3%81%99%e3%82%8b" &gt;リバースプロキシする&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="とりあえず起動する"&gt;とりあえず起動する
&lt;/h3&gt;&lt;p&gt;それぞれ&lt;code&gt;Docker image&lt;/code&gt;が公式で提供されているのでそれをそのまま起動すれば良さそう.&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2020-09-17-prometheus-exporter/" target="_blank" rel="noopener"
 &gt;自作Exporterの動作確認をしたとき&lt;/a&gt;と同様に適当に&lt;code&gt;docker-compose.yml&lt;/code&gt;を書いてみる.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/278f4905ee1265241f0a52690ae90519.js"&gt;&lt;/script&gt;
&lt;p&gt;重要なのは以下の設定ファイルをそれぞれのコンテナにマウントしていること.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Prometheus&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;自作Exporterなどをスクレイプするための設定(&lt;code&gt;prometheus.yml&lt;/code&gt;)
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Docker Compose&lt;/code&gt;で起動しているので他のコンテナについてはすべてコンテナ名で名前解決できる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;アラートルール(&lt;code&gt;rules.yml&lt;/code&gt;)
&lt;ul&gt;
&lt;li&gt;任意のルールで良い&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Alertmanager&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;アラート通知設定(&lt;code&gt;alertmanager.yml&lt;/code&gt;)
&lt;ul&gt;
&lt;li&gt;任意の設定で良い&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Grafana&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;基本設定(&lt;code&gt;grafana.ini&lt;/code&gt;)
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2020-05-08-grafana-anonymous-authentication/" target="_blank" rel="noopener"
 &gt;ログイン不要の設定&lt;/a&gt;をしておく&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Data Source設定(&lt;code&gt;datasource.yaml&lt;/code&gt;)
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Prometheus&lt;/code&gt;コンテナを指定する&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Dashboard設定(&lt;code&gt;dashboard.yaml&lt;/code&gt;, &lt;code&gt;dashboard.json&lt;/code&gt;)
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;dashboard.json&lt;/code&gt;は後から作っても良い&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;script src="https://gist.github.com/uzimihsr/44c1b3989b8adfa4097cf59730a83206.js"&gt;&lt;/script&gt;
&lt;p&gt;(&lt;code&gt;rules.yml&lt;/code&gt;, &lt;code&gt;alertmanager.yml&lt;/code&gt;は何でも良いので&lt;a class="link" href="https://uzimihsr.github.io/post/2020-01-27-alertmanager-gmail/" target="_blank" rel="noopener"
 &gt;前回&lt;/a&gt;のものを流用)&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/uzimihsr/example-exporter/blob/ff85b3c8cea89d630ae308a8ea1b45d70973e7c8/deployment/prometheus/rules.yml" target="_blank" rel="noopener"
 &gt;rules.yml&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/uzimihsr/example-exporter/blob/ff85b3c8cea89d630ae308a8ea1b45d70973e7c8/deployment/alertmanager/alertmanager.yml" target="_blank" rel="noopener"
 &gt;alertmanager.yml&lt;/a&gt;&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/4c9cc5c40f8febb34710d8ac9ea6a57d.js"&gt;&lt;/script&gt;
&lt;script src="https://gist.github.com/uzimihsr/0a6d2da205776d15b7e1d5e1c6314b42.js"&gt;&lt;/script&gt;
&lt;script src="https://gist.github.com/uzimihsr/f66ff6f3c2c3814e2903a0b6b6be2d6b.js"&gt;&lt;/script&gt;
&lt;p&gt;(&lt;code&gt;dashboard.json&lt;/code&gt;はあらかじめ作成済みのものがなければこの後作成する)&lt;/p&gt;
&lt;p&gt;あとはこれらのファイルが以下のように配置されている状態で&lt;code&gt;Docker Compose&lt;/code&gt;でコンテナを立ち上げる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ローカルでビルドしない場合はDockerfileとGo関連のファイルは不要&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ tree .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── Dockerfile
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── deployment
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   ├── alertmanager
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   │   └── alertmanager.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   ├── grafana
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   │   ├── dashboard.json
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   │   ├── dashboard.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   │   ├── datasource.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   │   └── grafana.ini
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   └── prometheus
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   ├── prometheus.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   └── rules.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── docker-compose.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── go.mod
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── go.sum
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── main.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# コンテナを起動(コードを編集したなどの理由で再度ビルドしたい場合はさらに--buildを付与する)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-compose up -d --force-recreate
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-compose ps
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Name Command State Ports
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;alertmanager /bin/alertmanager --config ... Up 0.0.0.0:9093-&amp;gt;9093/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;exporter ./app Up 0.0.0.0:2112-&amp;gt;2112/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grafana /run.sh Up 0.0.0.0:3000-&amp;gt;3000/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;prometheus /bin/prometheus --config.f ... Up 0.0.0.0:9090-&amp;gt;9090/tcp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;あとはそれぞれのエンドポイントで動作確認する.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;自作Exporter
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://localhost:2112/metrics" target="_blank" rel="noopener"
 &gt;http://localhost:2112/metrics&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Prometheus&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://localhost:9090/" target="_blank" rel="noopener"
 &gt;http://localhost:9090/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Alertmanager&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://localhost:9093/" target="_blank" rel="noopener"
 &gt;http://localhost:9093/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Grafana&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://localhost:3000/" target="_blank" rel="noopener"
 &gt;http://localhost:3000/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="自作Exporter" class="gallery-image" data-flex-basis="2153px" data-flex-grow="897" height="321" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc01.png" srcset="https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc01_hu_717a7ebb2830207a.png 800w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc01_hu_517baea07dee3e93.png 1600w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc01_hu_88b48cca7deb81e.png 2400w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc01.png 2880w" width="2880"&gt;&lt;br&gt;
&lt;img alt="Prometheus" class="gallery-image" data-flex-basis="3339px" data-flex-grow="1391" height="207" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc02.png" srcset="https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc02_hu_fcb42e6841a25b4c.png 800w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc02_hu_44054b5cb9d0d9fa.png 1600w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc02_hu_46f32d8b9c770a24.png 2400w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc02.png 2880w" width="2880"&gt;&lt;br&gt;
&lt;img alt="Alertmanager" class="gallery-image" data-flex-basis="3005px" data-flex-grow="1252" height="230" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc03.png" srcset="https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc03_hu_b73a15ab8c0e6372.png 800w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc03_hu_9080a5ba2ca9a3f1.png 1600w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc03_hu_d329e7b9c5f7440e.png 2400w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc03.png 2880w" width="2880"&gt;&lt;br&gt;
&lt;img alt="Grafana" class="gallery-image" data-flex-basis="3490px" data-flex-grow="1454" height="198" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc04.png" srcset="https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc04_hu_111f689a58cfc5bc.png 800w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc04_hu_fb12c6a5ddc300e5.png 1600w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc04_hu_a456e87cbe656a58.png 2400w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc04.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;dashboard.json&lt;/code&gt;が未作成の場合はここで動作確認も兼ねて&lt;code&gt;Grafana&lt;/code&gt;上でダッシュボード(自作Exporterのメトリクスがグラフ化できれば何でも良い)を作成し, &lt;code&gt;Share&lt;/code&gt;➔&lt;code&gt;Export&lt;/code&gt;➔&lt;code&gt;Save to file&lt;/code&gt;から&lt;code&gt;JSON&lt;/code&gt;をダウンロードして以降はそれを使うようにする.&lt;/p&gt;
&lt;p&gt;設定が正しく効いていれば予め&lt;code&gt;Prometheus&lt;/code&gt;が&lt;code&gt;Data Source&lt;/code&gt;として登録されていて, 全コンテナのメトリクスがスクレイプできていることも確認できる.&lt;/p&gt;
&lt;p&gt;&lt;img alt="動作確認" class="gallery-image" data-flex-basis="384px" data-flex-grow="160" height="1800" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc05.png" srcset="https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc05_hu_5dd7d69c510dcbb5.png 800w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc05_hu_99a04e6af6a70f31.png 1600w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc05_hu_32773951b1e6984e.png 2400w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc05.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;h3 id="リバースプロキシする"&gt;リバースプロキシする
&lt;/h3&gt;&lt;p&gt;このままでもいいんだけどせっかくなので&lt;code&gt;nginx&lt;/code&gt;で&lt;a class="link" href="https://uzimihsr.github.io/post/2020-01-29-nginx/" target="_blank" rel="noopener"
 &gt;リバースプロキシ&lt;/a&gt;する.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt;に&lt;code&gt;nginx&lt;/code&gt;コンテナを追加して, 以前やったときと同様の設定ファイルを作成してマウントする.&lt;/p&gt;
&lt;p&gt;(リバースプロキシしているので, &lt;code&gt;nginx&lt;/code&gt;以外のそれぞれのコンテナのポートは閉じておく)&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/9163171af48323662807d8db300c1d99.js"&gt;&lt;/script&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Prometheus&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;prometheus.yml&lt;/code&gt;, &lt;code&gt;rules.yml&lt;/code&gt;: そのまま&lt;/li&gt;
&lt;li&gt;command(CMD)にリバースプロキシ用の設定&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;を追加&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Alertmanager&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;alertmanager.yml&lt;/code&gt;: そのまま&lt;/li&gt;
&lt;li&gt;command(CMD)にリバースプロキシ用の設定を追加&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Grafana&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;datasource.yaml&lt;/code&gt;, &lt;code&gt;dashboard.yaml&lt;/code&gt;, &lt;code&gt;dashboard.json&lt;/code&gt; : そのまま&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grafana.ini&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;リバースプロキシ用の設定&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;を追加&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nginx&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;リバースプロキシ設定(&lt;code&gt;default.conf&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;リンク用ページ(&lt;code&gt;index.html&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;script src="https://gist.github.com/uzimihsr/82e4b56dd6fc6eebcc46640319ec9e1d.js"&gt;&lt;/script&gt;
&lt;script src="https://gist.github.com/uzimihsr/6d9b5119345e653859f2af55ac8e47bc.js"&gt;&lt;/script&gt;
&lt;script src="https://gist.github.com/uzimihsr/61e5fc764403d3481b55ab909288c302.js"&gt;&lt;/script&gt;
&lt;p&gt;再度コンテナを起動する.&lt;br&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ tree .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── Dockerfile
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── deployment
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   ├── alertmanager
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   │   └── alertmanager.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   ├── grafana
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   │   ├── dashboard.json
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   │   ├── dashboard.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   │   ├── datasource.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   │   └── grafana.ini
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   ├── nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   │   ├── default.conf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   │   └── index.html
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   └── prometheus
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   ├── prometheus.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   └── rules.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── docker-compose.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── go.mod
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── go.sum
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── main.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-compose up -d --force-recreate
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-compose ps
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Name Command State Ports
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;--------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;alertmanager /bin/alertmanager --config ... Up 9093/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;exporter ./app Up
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grafana /run.sh Up 3000/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nginx /docker-entrypoint.sh ngin ... Up 0.0.0.0:80-&amp;gt;80/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;prometheus /bin/prometheus --config.f ... Up 9090/tcp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;ここまでの設定に問題がなければそれぞれのパスでコンテナの動作確認ができる.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;自作Exporter
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://localhost/exporter/metrics" target="_blank" rel="noopener"
 &gt;http://localhost/exporter/metrics&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Prometheus&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://localhost/prometheus/" target="_blank" rel="noopener"
 &gt;http://localhost/prometheus/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Alertmanager&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://localhost/alertmanager/" target="_blank" rel="noopener"
 &gt;http://localhost/alertmanager/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Grafana&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://localhost/grafana/" target="_blank" rel="noopener"
 &gt;http://localhost/grafana/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;もしくは, &lt;a class="link" href="http://localhost/" target="_blank" rel="noopener"
 &gt;http://localhost/&lt;/a&gt;でリンクを張った&lt;code&gt;HTML&lt;/code&gt;(&lt;code&gt;index.html&lt;/code&gt;)が表示できるのでそこから飛んでも良い.&lt;/p&gt;
&lt;p&gt;&lt;img alt="動作確認" class="gallery-image" data-flex-basis="1393px" data-flex-grow="580" height="496" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc06.png" srcset="https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc06_hu_78da21c88931acb4.png 800w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc06_hu_85cbed7d38df0ecb.png 1600w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc06_hu_de925d023006949b.png 2400w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc06.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;最後に一応&lt;code&gt;Alertmanager&lt;/code&gt;の動作確認をする.&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/uzimihsr/example-exporter/blob/ff85b3c8cea89d630ae308a8ea1b45d70973e7c8/deployment/prometheus/rules.yml" target="_blank" rel="noopener"
 &gt;rules.yml&lt;/a&gt;で&lt;code&gt;InstanceDown&lt;/code&gt;(&lt;strong&gt;up&lt;/strong&gt;が0になるだけで発火)のアラートルールを設定しているので, 試しに自作Exporterのコンテナを落としてみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-compose stop exporter
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-compose ps
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Name Command State Ports
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;alertmanager /bin/alertmanager --config ... Up 9093/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;exporter ./app Exit &lt;span class="m"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grafana /run.sh Up 3000/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nginx /docker-entrypoint.sh ngin ... Up 0.0.0.0:80-&amp;gt;80/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;prometheus /bin/prometheus --config.f ... Up 9090/tcp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;それぞれのコンテナでメトリクスの変化に対応した処理が行われていることが確認できる.&lt;/p&gt;
&lt;p&gt;&lt;img alt="グラフの値(up)が変化" class="gallery-image" data-flex-basis="403px" data-flex-grow="167" height="1715" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc07.png" srcset="https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc07_hu_7f479803fd3c5c9c.png 800w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc07_hu_9c83ad4e2f3db419.png 1600w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc07_hu_d3ed66426804d8a1.png 2400w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc07.png 2880w" width="2880"&gt;&lt;br&gt;
&lt;img alt="アラートが発火" class="gallery-image" data-flex-basis="781px" data-flex-grow="325" height="884" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc08.png" srcset="https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc08_hu_87594aa84b418f6f.png 800w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc08_hu_b931dc5c6585bcd1.png 1600w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc08_hu_8eb95317cb64af07.png 2400w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc08.png 2880w" width="2880"&gt;&lt;br&gt;
&lt;img alt="アラートを通知" class="gallery-image" data-flex-basis="652px" data-flex-grow="271" height="1059" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc09.png" srcset="https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc09_hu_e3da7313fa492bc.png 800w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc09_hu_fcafec423052b1e.png 1600w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc09_hu_7f05b2ca43cc397f.png 2400w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc09.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;アラートは&lt;a class="link" href="https://uzimihsr.github.io/post/2020-01-27-alertmanager-gmail/" target="_blank" rel="noopener"
 &gt;AlertmanagerからGmail経由で送る&lt;/a&gt;設定にしているのでメールが届くことも確認できる.&lt;/p&gt;
&lt;p&gt;&lt;img alt="届いたメール" class="gallery-image" data-flex-basis="512px" data-flex-grow="213" height="1350" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc10.png" srcset="https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc10_hu_bcc62302d11ca3d.png 800w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc10_hu_d786fe4f01968ae1.png 1600w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc10_hu_292e1f44bf73ab46.png 2400w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sc10.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;やったぜ.&lt;/p&gt;
&lt;p&gt;自作Exporterと&lt;code&gt;Prometheus&lt;/code&gt;, &lt;code&gt;Alertmanager&lt;/code&gt;, &lt;code&gt;Grafana&lt;/code&gt;を同時に動かして動作確認することができた.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;終わってみれば大したことはないんだけど, 一回この構成をつくっておくと自作Exporterの開発が楽しくなる(メトリクスがすぐ可視化されアラートの動作確認までできる)のでやってよかったと思う.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Docker Compose&lt;/code&gt;の練習にもなってよかった.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="しっぽは体に巻き付ける派" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sotochan_hu_3df4c9fbb78108d3.jpg 800w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sotochan_hu_79d16af502ae94ae.jpg 1600w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sotochan_hu_91e0c3cc271c5065.jpg 2400w, https://blog.uzimihsr.com/post/2021-02-05-run-prometheus-and-grafana-on-docker/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a class="link" href="https://prometheus.io/docs/guides/basic-auth/#nginx-configuration" target="_blank" rel="noopener"
 &gt;https://prometheus.io/docs/guides/basic-auth/#nginx-configuration&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;a class="link" href="https://grafana.com/tutorials/run-grafana-behind-a-proxy/" target="_blank" rel="noopener"
 &gt;https://grafana.com/tutorials/run-grafana-behind-a-proxy/&lt;/a&gt;&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>1月のそとちゃんまとめ(2021)</title><link>https://blog.uzimihsr.com/post/2021-02-02-sotochan/</link><pubDate>Tue, 02 Feb 2021 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2021-02-02-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan.jpg" alt="Featured image of post 1月のそとちゃんまとめ(2021)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e8%85%b9%e3%81%ae%e4%b8%8a%e3%81%ab%e3%81%ad%e3%81%93" &gt;腹の上にねこ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%88%e3%83%b3%e3%83%8d%e3%83%ab" &gt;トンネル&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%ad%e3%81%9a%e3%81%bf" &gt;ねずみ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%bd%e3%83%95%e3%82%a1" &gt;ソファ&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="腹の上にねこ"&gt;腹の上にねこ
&lt;/h3&gt;&lt;p&gt;俺のお腹の上に乗るのが癖になったらしい.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;腹の上に乗るの完全に癖になってる &lt;a href="https://t.co/9bKr8zVZo0"&gt;pic.twitter.com/9bKr8zVZo0&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1351159561986727943?ref_src=twsrc%5Etfw"&gt;January 18, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;前から俺が寝っ転がってるとたまに乗ってくることはあったんだけど,&lt;br&gt;
そのタイミングでたくさん撫でたりおやつをあげたりしてたら習慣化した.&lt;/p&gt;
&lt;p&gt;やっぱりねこは良いことがあるとちゃんと覚えるみたい. かしこい.😊&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;人の腹をベッドだと思っている &lt;a href="https://t.co/8vAcFHhgmK"&gt;pic.twitter.com/8vAcFHhgmK&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1353667272888381441?ref_src=twsrc%5Etfw"&gt;January 25, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;俺がソファとかベッドに寝っ転がるとそとちゃんが乗ってきて,&lt;br&gt;
そのまま俺の顔に頭を向けたりおしりを向けたり何回か向きを変えてベストポジションを探す.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ねこのすりすりこうげき &lt;a href="https://t.co/eBX2X6bvwL"&gt;pic.twitter.com/eBX2X6bvwL&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1347871050772619264?ref_src=twsrc%5Etfw"&gt;January 9, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;おしり &lt;a href="https://t.co/kLcfzk1JOX"&gt;pic.twitter.com/kLcfzk1JOX&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1348115407240978435?ref_src=twsrc%5Etfw"&gt;January 10, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;そしてそのまま1時間くらい動かずに撫でられるのがお決まりのパターン.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;こうなってからが長い &lt;a href="https://t.co/DL6ReXMZet"&gt;pic.twitter.com/DL6ReXMZet&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1350038725653270529?ref_src=twsrc%5Etfw"&gt;January 15, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;そとちゃんが満足するまで俺が勝手に起きることは許されない!😱&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;おしりぽんぽんされてゴロゴロ言ってるし気持ちいいはずなのに怖い顔なの難しすぎ &lt;a href="https://t.co/G7Me4xKayS"&gt;pic.twitter.com/G7Me4xKayS&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1351115846425456641?ref_src=twsrc%5Etfw"&gt;January 18, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;でもねこが腹の上に乗るとやわらかくてあったかくて気持ち良いしめんどくさいことを全部忘れられるのでとても良い.&lt;/p&gt;
&lt;h3 id="トンネル"&gt;トンネル
&lt;/h3&gt;&lt;p&gt;普段と違うペットショップに行く機会があって, たまたま目についたねこ用トンネルを買ってみた.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;トンネルがうちにきた &lt;a href="https://t.co/q5hRboMbim"&gt;pic.twitter.com/q5hRboMbim&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1346412630647267328?ref_src=twsrc%5Etfw"&gt;January 5, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;&lt;a class="link" href="https://www.necoichi.co.jp/Products/detail/id=6325" target="_blank" rel="noopener"
 &gt;キャットトンネル　木目柄&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;えらく気に入ったらしく, 毎日飽きずに遊んでいる.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;はしゃいでる &lt;a href="https://t.co/j3esWctCdf"&gt;pic.twitter.com/j3esWctCdf&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1354614234391273472?ref_src=twsrc%5Etfw"&gt;January 28, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;だいたい前足と頭だけ突っ込んだ状態で待機しているので, あとは横穴か向かいの出口からおもちゃを投げ込んであげると大はしゃぎであそぶ.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ちくわみたいでいいね〜 &lt;a href="https://t.co/6rYEBApoaV"&gt;pic.twitter.com/6rYEBApoaV&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1346416121033891840?ref_src=twsrc%5Etfw"&gt;January 5, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;おしり &lt;a href="https://t.co/cqBzzk8aF7"&gt;pic.twitter.com/cqBzzk8aF7&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1355292215015165954?ref_src=twsrc%5Etfw"&gt;January 29, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;買ってよかった.&lt;/p&gt;
&lt;h3 id="ねずみ"&gt;ねずみ
&lt;/h3&gt;&lt;p&gt;そとちゃんお気に入りの&lt;a class="link" href="https://uzimihsr.github.io/post/2020-10-07-sotochan/#%e3%81%ad%e3%81%9a%e3%81%bf%e3%81%ae%e3%81%8a%e3%82%82%e3%81%a1%e3%82%83" target="_blank" rel="noopener"
 &gt;ねずみのおもちゃ&lt;/a&gt;だけど, 流石に遊びすぎてボロボロになってきた&amp;hellip;&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ねずみの毛がハゲてきた &lt;a href="https://t.co/23lSq8Yq1g"&gt;pic.twitter.com/23lSq8Yq1g&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1352261733449023490?ref_src=twsrc%5Etfw"&gt;January 21, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;&lt;img alt="そとちゃんが遊びまくったねずみ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan-01.jpg" srcset="https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan-01_hu_ea76ca2942e4a37c.jpg 800w, https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan-01_hu_2b364c5f4b2c325d.jpg 1600w, https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan-01_hu_6c2c4e6e38f7fe57.jpg 2400w, https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan-01.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;非売品だと思ってたので代わりが見つからず困ってたんだけど, 偶然にもトンネルを買ったのと同じお店で遂にそれっぽいおもちゃを見つけた.&lt;/p&gt;
&lt;p&gt;&lt;img alt="新旧ねずみのおもちゃ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan-02.jpg" srcset="https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan-02_hu_cb5449be814445ec.jpg 800w, https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan-02_hu_707546c3253c84fa.jpg 1600w, https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan-02_hu_139230cabedf63e1.jpg 2400w, https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan-02.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://www.doggyman.com/?p=showroom&amp;amp;keywords=%E3%83%8D%E3%82%BA%E3%83%9F%E3%81%94%E3%81%A3%E3%81%93&amp;amp;id=605" target="_blank" rel="noopener"
 &gt;ネズミごっこ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;毛の色も同じで, 目鼻耳のパーツの色も同じだから流石に同じものだと信じたい.&lt;br&gt;
(しっぽは遊んでるうちに切れた)&lt;/p&gt;
&lt;p&gt;&amp;hellip;が, 転がしたときの音が微妙に違うのでまだ遊んだり遊ばなかったりする.🤔&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ねずみドリブル &lt;a href="https://t.co/c3u5PI29tr"&gt;pic.twitter.com/c3u5PI29tr&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1344635445846556673?ref_src=twsrc%5Etfw"&gt;December 31, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;(↑の動画のシャカシャカ鳴ってるねずみは古いやつ, 新しいのはもっとカラカラ鳴る)&lt;/p&gt;
&lt;p&gt;ねこのこだわりは難しい&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="ねずみとそとちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan-03.jpg" srcset="https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan-03_hu_4eb72f443f3245c4.jpg 800w, https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan-03_hu_a8ae3d5833c9109d.jpg 1600w, https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan-03_hu_cb82bad31799c195.jpg 2400w, https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan-03.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;h3 id="ソファ"&gt;ソファ
&lt;/h3&gt;&lt;p&gt;😭&lt;/p&gt;
&lt;p&gt;&lt;img alt="我が家のソファ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan-04.jpg" srcset="https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan-04_hu_45dd50887d6a652d.jpg 800w, https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan-04_hu_81b6b07a8dd5f758.jpg 1600w, https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan-04_hu_d046c208f86b0cc8.jpg 2400w, https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan-04.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;😭😭&lt;/p&gt;
&lt;p&gt;&lt;img alt="ソファだったもの" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan-05.jpg" srcset="https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan-05_hu_9e47cb2b78a02a8.jpg 800w, https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan-05_hu_596234b3806827e6.jpg 1600w, https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan-05_hu_a33f75ddeb89702.jpg 2400w, https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan-05.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;😭😭😭&lt;/p&gt;
&lt;p&gt;&lt;img alt="そとちゃんのつめとぎ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan-06.jpg" srcset="https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan-06_hu_9bb15dd6cc6d5bb2.jpg 800w, https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan-06_hu_1e29ed7a2a404343.jpg 1600w, https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan-06_hu_a7ca2bf00d69f7c7.jpg 2400w, https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan-06.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;😭😭😭😭&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;その気になればいつでもバリバリしてやるぞという顔 &lt;a href="https://t.co/zyeU2lBaDX"&gt;pic.twitter.com/zyeU2lBaDX&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1354434127894700041?ref_src=twsrc%5Etfw"&gt;January 27, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;1月はそとちゃんとたくさん&lt;del&gt;遊んであげられて&lt;/del&gt;遊ばせていただけてよかった.&lt;/p&gt;
&lt;p&gt;今月みたいに普段と違うペットショップにいけるとおもちゃのレパートリーも広がるので, 出かけるたびに気にかけるようにしたい.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="おもちゃで目線をつられたそとちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan_hu_e6146eb5bb84f162.jpg 800w, https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan_hu_8ab20ed2f18b79a5.jpg 1600w, https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan_hu_43af56f5b29e0224.jpg 2400w, https://blog.uzimihsr.com/post/2021-02-02-sotochan/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>promtool/amtoolでPrometheus/Alertmanagerの設定をチェックする</title><link>https://blog.uzimihsr.com/post/2021-01-28-promtool-amtool-check-config/</link><pubDate>Thu, 28 Jan 2021 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2021-01-28-promtool-amtool-check-config/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2021-01-28-promtool-amtool-check-config/sotochan.jpg" alt="Featured image of post promtool/amtoolでPrometheus/Alertmanagerの設定をチェックする" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;promtool&lt;/code&gt;と&lt;code&gt;amtool&lt;/code&gt;を使うと&lt;code&gt;Prometheus&lt;/code&gt;の設定とアラートルール, &lt;code&gt;Alertmanager&lt;/code&gt;の設定をそれぞれ反映前にチェックすることができる.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Docker&lt;/code&gt;上でも動かせるので&lt;code&gt;CI&lt;/code&gt;にも組み込めそう.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Prometheus設定ファイルのチェック&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ promtool check config prometheus.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Docker版&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run --rm -v&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt;&lt;span class="s2"&gt;/prometheus.yml:/prometheus-config/prometheus.yml&amp;#34;&lt;/span&gt; --entrypoint&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;promtool&amp;#34;&lt;/span&gt; prom/prometheus check config /prometheus-config/prometheus.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# アラートルールファイルのチェック&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ promtool check rules rules.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Docker版&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run --rm -v&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt;&lt;span class="s2"&gt;/rules.yml:/prometheus-config/rules.yml&amp;#34;&lt;/span&gt; --entrypoint&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;promtool&amp;#34;&lt;/span&gt; prom/prometheus check rules /prometheus-config/rules.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Alertmanager設定ファイルのチェック&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ amtool check-config alertmanager.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Docker版&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run --rm -v&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt;&lt;span class="s2"&gt;/alertmanager.yml:/prometheus-config/alertmanager.yml&amp;#34;&lt;/span&gt; --entrypoint&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;amtool&amp;#34;&lt;/span&gt; prom/alertmanager check-config /prometheus-config/alertmanager.yml&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Mojave 10.14&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/editions/community/docker-ce-desktop-mac" target="_blank" rel="noopener"
 &gt;Docker Desktop for Mac&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Version 3.1.0&lt;/li&gt;
&lt;li&gt;Docker Engine Version 20.10.2&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/prometheus/prometheus" target="_blank" rel="noopener"
 &gt;Prometheus&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;version &lt;a class="link" href="https://hub.docker.com/layers/prom/prometheus/v2.24.1/images/sha256-f4a858861e05c8611cdb5867a07e48742b8295400a5993ac05ad1ee67e6d5696?context=explore" target="_blank" rel="noopener"
 &gt;2.24.1&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/prometheus/prometheus/tree/master/cmd/promtool" target="_blank" rel="noopener"
 &gt;promtool&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;version 0.21.0&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/prometheus/alertmanager" target="_blank" rel="noopener"
 &gt;Alertmanager&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;version &lt;a class="link" href="https://hub.docker.com/layers/prom/alertmanager/v0.21.0/images/sha256-913293083cb14085bfc01018bb30d1dcbbc9ed197ae21ef2ca917b0d29265198?context=explore" target="_blank" rel="noopener"
 &gt;0.21.0&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/prometheus/alertmanager/tree/master/cmd/amtool" target="_blank" rel="noopener"
 &gt;amtool&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;version 0.20.0&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="もくじ"&gt;もくじ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#promtool%e3%81%a8amtool" &gt;promtoolとamtool&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#docker%e3%81%a7%e8%b5%b7%e5%8b%95%e3%81%99%e3%82%8b" &gt;Dockerで起動する&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="promtoolとamtool"&gt;promtoolとamtool
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;promtool&lt;/code&gt;は&lt;code&gt;Prometheus&lt;/code&gt;に付属している設定ファイルやアラートルールファイルの検証ツール&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Prometheus&lt;/code&gt;がインストールされていればすぐに使うことができる.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;amtool&lt;/code&gt;は&lt;code&gt;promtool&lt;/code&gt;の&lt;code&gt;Alertmanager&lt;/code&gt;版といった感じ.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# prometheus設定ファイル(prometheus.yml)とアラートルールファイル(rules.yml)を準備&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;prometheus.yml rules.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# prometheus.ymlの内容をチェック&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# prometheus.ymlでルールファイルを参照している場合はその対象もチェックしてくれる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ promtool check config prometheus.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Checking prometheus.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; SUCCESS: &lt;span class="m"&gt;1&lt;/span&gt; rule files found
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Checking rules.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; SUCCESS: &lt;span class="m"&gt;1&lt;/span&gt; rules found
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# rulesだけのチェックも可能&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ promtool check rules rules.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Checking rules.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; SUCCESS: &lt;span class="m"&gt;1&lt;/span&gt; rules found
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# alertmanager設定ファイルも同様にチェックできる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ amtool check-config alertmanager.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Checking &lt;span class="s1"&gt;&amp;#39;alertmanager.yml&amp;#39;&lt;/span&gt; SUCCESS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Found:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - global config
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - route
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - &lt;span class="m"&gt;1&lt;/span&gt; inhibit rules
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - &lt;span class="m"&gt;1&lt;/span&gt; receivers
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - &lt;span class="m"&gt;0&lt;/span&gt; templates&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;これを使えば&lt;code&gt;Prometheus&lt;/code&gt;や&lt;code&gt;Alertmanager&lt;/code&gt;の設定反映前に構文エラーをチェックすることができて便利.&lt;/p&gt;
&lt;p&gt;試しにわざと間違った&lt;code&gt;Prometheus&lt;/code&gt;設定ファイルとアラートルールファイル, &lt;code&gt;Alertmanager&lt;/code&gt;設定ファイルをチェックしてみる.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/3e401a6bbca400570af5e5c0aef52e96.js"&gt;&lt;/script&gt;
&lt;script src="https://gist.github.com/uzimihsr/232d6d3f62e5545885924eea38955884.js"&gt;&lt;/script&gt;
&lt;script src="https://gist.github.com/uzimihsr/e86ec5423e9bb6c70f571b869d9134df.js"&gt;&lt;/script&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 間違ったprometheus設定ファイル(prometheus.yml)をチェックする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ promtool check config prometheus-error.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Checking prometheus-error.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; FAILED: parsing YAML file prometheus-error.yml: yaml: unmarshal errors:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; line 13: field target not found in &lt;span class="nb"&gt;type&lt;/span&gt; struct &lt;span class="o"&gt;{&lt;/span&gt; Targets &lt;span class="o"&gt;[]&lt;/span&gt;string &lt;span class="s2"&gt;&amp;#34;yaml:\&amp;#34;targets\&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; Labels model.LabelSet &lt;span class="s2"&gt;&amp;#34;yaml:\&amp;#34;labels\&amp;#34;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 間違ったアラートルールファイルをチェックする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ promtool check rules rules-error.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Checking rules-error.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; FAILED:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rules-error.yml: group &lt;span class="s2"&gt;&amp;#34;instance&amp;#34;&lt;/span&gt;, rule 0, &lt;span class="s2"&gt;&amp;#34;InstanceDown&amp;#34;&lt;/span&gt;: could not parse expression: 1:4: parse error: could not parse remaining input &lt;span class="s2"&gt;&amp;#34;= 0&amp;#34;&lt;/span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 間違ったAlertmanager設定ファイルをチェックする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ amtool check-config alertmanager-error.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Checking &lt;span class="s1"&gt;&amp;#39;alertmanager-error.yml&amp;#39;&lt;/span&gt; FAILED: yaml: unmarshal errors:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; line 7: field receiver not found in &lt;span class="nb"&gt;type&lt;/span&gt; config.plain
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;amtool: error: failed to validate &lt;span class="m"&gt;1&lt;/span&gt; file&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;ちゃんとエラー箇所とエラーの内容が表示された.&lt;/p&gt;
&lt;p&gt;べんり.😊&lt;/p&gt;
&lt;h3 id="dockerで起動する"&gt;Dockerで起動する
&lt;/h3&gt;&lt;p&gt;便利な&lt;code&gt;promtool&lt;/code&gt;と&lt;code&gt;amtool&lt;/code&gt;だけど, &lt;code&gt;Prometheus&lt;/code&gt;や&lt;code&gt;Alertmanager&lt;/code&gt;がインストールされていない環境ではなかなか使いづらい.&lt;/p&gt;
&lt;p&gt;(実務で&lt;code&gt;Prometheus&lt;/code&gt;/&lt;code&gt;Alertmanager&lt;/code&gt;の設定を直接手でいじることはあんまりなくて, リポジトリ上で設定ファイルを管理して&lt;code&gt;CI/CD&lt;/code&gt;することが多い. と思う.)&lt;/p&gt;
&lt;p&gt;ということで&lt;code&gt;Docker&lt;/code&gt;を使って&lt;code&gt;Prometheus&lt;/code&gt;がインストールされていない環境でも&lt;code&gt;promtool&lt;/code&gt;を使えないか試してみる. 　&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Dockerでもできそう&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run --rm --entrypoint&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;promtool&amp;#34;&lt;/span&gt; prom/prometheus --version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;promtool, version 2.24.1 &lt;span class="o"&gt;(&lt;/span&gt;branch: HEAD, revision: e4487274853c587717006eeda8804e597d120340&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; build user: root@0b5231a0de0f
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; build date: 20210120-00:09:36
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; go version: go1.15.6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; platform: linux/amd64
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run --rm --entrypoint&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;amtool&amp;#34;&lt;/span&gt; prom/alertmanager --version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;amtool, version 0.21.0 &lt;span class="o"&gt;(&lt;/span&gt;branch: HEAD, revision: 4c6c03ebfe21009c546e4d1e9b92c371d67c021d&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; build user: root@dee35927357f
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; build date: 20200617-08:54:02
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; go version: go1.14.4&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;コマンドは実行可能みたいなので, あとは&lt;code&gt;Docker&lt;/code&gt;コンテナ起動時のオプションで設定ファイルをマウントすれば良さそう.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;alertmanager-error.yml prometheus-error.yml rules-error.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Dockerでもできた&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run --rm -v&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt;&lt;span class="s2"&gt;:/prometheus-config&amp;#34;&lt;/span&gt; --entrypoint&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;promtool&amp;#34;&lt;/span&gt; prom/prometheus check config /prometheus-config/prometheus-error.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Checking /prometheus-config/prometheus-error.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; FAILED: parsing YAML file /prometheus-config/prometheus-error.yml: yaml: unmarshal errors:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; line 13: field target not found in &lt;span class="nb"&gt;type&lt;/span&gt; struct &lt;span class="o"&gt;{&lt;/span&gt; Targets &lt;span class="o"&gt;[]&lt;/span&gt;string &lt;span class="s2"&gt;&amp;#34;yaml:\&amp;#34;targets\&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; Labels model.LabelSet &lt;span class="s2"&gt;&amp;#34;yaml:\&amp;#34;labels\&amp;#34;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run --rm -v&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt;&lt;span class="s2"&gt;:/prometheus-config&amp;#34;&lt;/span&gt; --entrypoint&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;promtool&amp;#34;&lt;/span&gt; prom/prometheus check rules /prometheus-config/rules-error.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Checking /prometheus-config/rules-error.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; FAILED:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/prometheus-config/rules-error.yml: 5:13: group &lt;span class="s2"&gt;&amp;#34;instance&amp;#34;&lt;/span&gt;, rule 1, &lt;span class="s2"&gt;&amp;#34;InstanceDown&amp;#34;&lt;/span&gt;: could not parse expression: 1:4: parse error: unexpected &lt;span class="s2"&gt;&amp;#34;=&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run --rm -v&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt;&lt;span class="s2"&gt;:/prometheus-config&amp;#34;&lt;/span&gt; --entrypoint&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;amtool&amp;#34;&lt;/span&gt; prom/alertmanager check-config /prometheus-config/alertmanager-error.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Checking &lt;span class="s1"&gt;&amp;#39;/prometheus-config/alertmanager-error.yml&amp;#39;&lt;/span&gt;amtool: error: failed to validate &lt;span class="m"&gt;1&lt;/span&gt; file&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; FAILED: yaml: unmarshal errors:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; line 7: field receiver not found in &lt;span class="nb"&gt;type&lt;/span&gt; config.plain
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# エラー時はちゃんと終了ステータスがnot 0になっている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;やったぜ.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Prometheus&lt;/code&gt;や&lt;code&gt;Alertmanager&lt;/code&gt;がインストールされていない環境でも&lt;code&gt;Docker&lt;/code&gt;上で&lt;code&gt;promtool&lt;/code&gt;と&lt;code&gt;amtool&lt;/code&gt;を使って設定ファイルの検証ができた.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;promtool&lt;/code&gt;と&lt;code&gt;amtool&lt;/code&gt;を触ってみて, &lt;code&gt;Docker&lt;/code&gt;で起動するところまで試した.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Docker image&lt;/code&gt;さえあれば起動できるので, あとは細かい設定さえすれば&lt;code&gt;GitHub Actions&lt;/code&gt;とかの&lt;code&gt;CI&lt;/code&gt;ツールで設定ファイルのチェックができると思う.&lt;/p&gt;
&lt;p&gt;今回は&lt;code&gt;promtool&lt;/code&gt;で設定ファイルのチェックしか試してないけど, 他にもアラートルールのユニットテストなんかもできるみたい&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;なので余裕があったらそっちも触ってみたい.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="ソファの上で誇らしげなねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-01-28-promtool-amtool-check-config/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2021-01-28-promtool-amtool-check-config/sotochan_hu_76e748457dbc43fe.jpg 800w, https://blog.uzimihsr.com/post/2021-01-28-promtool-amtool-check-config/sotochan_hu_671be4f18816cdac.jpg 1600w, https://blog.uzimihsr.com/post/2021-01-28-promtool-amtool-check-config/sotochan_hu_d5773af7a4c4bda2.jpg 2400w, https://blog.uzimihsr.com/post/2021-01-28-promtool-amtool-check-config/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a class="link" href="https://www.robustperception.io/how-to-check-your-prometheus-yml-is-valid" target="_blank" rel="noopener"
 &gt;https://www.robustperception.io/how-to-check-your-prometheus-yml-is-valid&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;a class="link" href="https://prometheus.io/docs/prometheus/latest/configuration/unit_testing_rules/" target="_blank" rel="noopener"
 &gt;https://prometheus.io/docs/prometheus/latest/configuration/unit_testing_rules/&lt;/a&gt;&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Kubernetes Podのcommandに/bin/shを使うときは終了ステータスの扱いに気をつけようという話</title><link>https://blog.uzimihsr.com/post/2021-01-24-sh-status/</link><pubDate>Sun, 24 Jan 2021 17:58:02 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2021-01-24-sh-status/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2021-01-24-sh-status/sotochan.jpg" alt="Featured image of post Kubernetes Podのcommandに/bin/shを使うときは終了ステータスの扱いに気をつけようという話" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Pod&lt;/code&gt;終了時の&lt;code&gt;phase&lt;/code&gt;はコンテナの&lt;code&gt;command&lt;/code&gt;と&lt;code&gt;args&lt;/code&gt;で指定されたメインプロセスの終了ステータスで判定されるので,&lt;/p&gt;
&lt;p&gt;&lt;code&gt;command&lt;/code&gt;に&lt;code&gt;/bin/sh -c&lt;/code&gt;を指定し, &lt;code&gt;args&lt;/code&gt;にコマンドを羅列するような場合は子プロセスの終了ステータスの扱いに気をつけないとエラーが発生しているのに異常終了しないことがある.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;set -e&lt;/code&gt;や&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;, &lt;code&gt;$?&lt;/code&gt;を適宜使い分けるのが大切.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# falseコマンドで終了ステータス=1が返っているがハンドリングされていないので最後まで実行される&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ /bin/sh -c &lt;span class="s1"&gt;&amp;#39;echo &amp;#34;abc&amp;#34;; false; echo &amp;#34;def&amp;#34;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;abc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;def
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# set -eで途中0以外の終了ステータスが発生したらそこでプロセスを止める&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ /bin/sh -c &lt;span class="s1"&gt;&amp;#39;set -e; echo &amp;#34;abc&amp;#34;; false; echo &amp;#34;def&amp;#34;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;abc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# $?で終了ステータスを扱うことでも止められる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ /bin/sh -c &lt;span class="s1"&gt;&amp;#39;echo &amp;#34;abc&amp;#34;; false; result=$?; if [ $result -ne 0 ]; then exit $result; fi; echo &amp;#34;def&amp;#34;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;abc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# &amp;amp;&amp;amp;を使って前のコマンドが正常に終了したときだけ次のコマンドを実行させる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ /bin/sh -c &lt;span class="s1"&gt;&amp;#39;echo &amp;#34;abc&amp;#34; &amp;amp;&amp;amp; false &amp;amp;&amp;amp; echo &amp;#34;def&amp;#34;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;abc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Mojave 10.14&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/editions/community/docker-ce-desktop-mac" target="_blank" rel="noopener"
 &gt;Docker Desktop for Mac&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Version 2.5.0.0&lt;/li&gt;
&lt;li&gt;Docker version 19.03.13&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/kubernetes-sigs/kind/" target="_blank" rel="noopener"
 &gt;kind&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;v0.9.0 go1.15.5 darwin/amd64&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/kubernetes/kubectl" target="_blank" rel="noopener"
 &gt;kubectl&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Client Version: v1.19.3&lt;/li&gt;
&lt;li&gt;Server Version: v1.19.1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="もくじ"&gt;もくじ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%84%e3%82%8a%e3%81%8c%e3%81%a1%e3%81%aa%e3%82%b1%e3%83%bc%e3%82%b9" &gt;やりがちなケース&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%aa%e3%82%93%e3%81%a7" &gt;なんで?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e8%a9%a6%e3%81%97%e3%81%a6%e3%81%bf%e3%82%8b" &gt;試してみる&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="やりがちなケース"&gt;やりがちなケース
&lt;/h3&gt;&lt;p&gt;自分もたまにやりがちなんだけど, こんな感じで&lt;code&gt;command&lt;/code&gt;を&lt;code&gt;/bin/sh -c&lt;/code&gt;, &lt;code&gt;args&lt;/code&gt;に&lt;code&gt;sh&lt;/code&gt;で実行したいコマンドを羅列するようなものを作ることがある.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/cb531a65ae0bc47fed4fc6f6d3f1f0ae.js"&gt;&lt;/script&gt;
&lt;p&gt;一見特に問題ないようにみえるけど, 次のようなものになるとたまに困ることがある.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/2c70023cf05a2ad8aa493df0b493a876.js"&gt;&lt;/script&gt;
&lt;p&gt;この&lt;code&gt;Job&lt;/code&gt;は途中で未定義の&lt;strong&gt;yourcoolcmd&lt;/strong&gt;を呼び出そうとしているので, 途中で失敗する(&amp;ldquo;def&amp;quot;はechoされない).&lt;/p&gt;
&lt;p&gt;&amp;hellip;と思いきや, 実際に動かしてみると&lt;code&gt;Job&lt;/code&gt;は最後まで実行されて正常終了してしまう.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# JobのPodが正常終了している&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f job-01.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get job example-job-command-not-found
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME COMPLETIONS DURATION AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;example-job-command-not-found 1/1 7s 3m42s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pod -l job-name&lt;span class="o"&gt;=&lt;/span&gt;example-job-command-not-found
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;example-job-command-not-found-j2dbv 0/1 Completed &lt;span class="m"&gt;0&lt;/span&gt; 3m20s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# not foundのエラーはちゃんと発生しているのに最後(echo &amp;#34;def&amp;#34;)まで実行されている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl logs example-job-command-not-found-j2dbv
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;abc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/bin/sh: yourcoolcmd: not found
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;def&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;コマンドの結果がなにかおかしかったら異常終了してほしいようなときにこの挙動は少し困ってしまう.&lt;/p&gt;
&lt;h3 id="なんで"&gt;なんで?
&lt;/h3&gt;&lt;p&gt;結論から言うと, 原因は先の&lt;code&gt;Job&lt;/code&gt;(というか&lt;code&gt;Pod&lt;/code&gt;)で起動したコンテナのプロセス&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/bin/sh -c &amp;#39;echo &amp;#34;abc&amp;#34;; yourcoolcmd; echo &amp;#34;def&amp;#34;&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;が異常終了していなかった(終了ステータスが0だった)ため.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# exitCodeが0(正常終了)になっている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pod example-job-command-not-found-j2dbv -o yaml &lt;span class="p"&gt;|&lt;/span&gt; yq r - &lt;span class="s2"&gt;&amp;#34;status&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;containerStatuses:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - containerID: containerd://36c7d09a5f262ff2c18bb328f006059c87aafb8414ae293517eca3ec1e75844f
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; image: docker.io/library/busybox:latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; imageID: docker.io/library/busybox@sha256:c5439d7db88ab5423999530349d327b04279ad3161d7596d2126dfb5b02bfd1f
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; lastState: &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: busybox
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ready: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; restartCount: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; started: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; state:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; terminated:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; containerID: containerd://36c7d09a5f262ff2c18bb328f006059c87aafb8414ae293517eca3ec1e75844f
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; exitCode: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; finishedAt: &lt;span class="s2"&gt;&amp;#34;2021-01-24T07:40:28Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; reason: Completed
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; startedAt: &lt;span class="s2"&gt;&amp;#34;2021-01-24T07:40:28Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;phase: Succeeded
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;まず大前提として, コンテナが終了したときの&lt;code&gt;Pod&lt;/code&gt;のステータス(&lt;code&gt;phase&lt;/code&gt;)は次のどちらかの状態になる&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Succeeded&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;Pod内のすべてのコンテナが正常に終了した&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Failed&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;Pod内のすべてのコンテナが終了し、少なくとも1つのコンテナが異常終了した(コンテナが0以外のステータスで終了したか、システムによって終了された)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;Failed&lt;/code&gt;の条件の&lt;strong&gt;コンテナが0以外のステータスで終了した&lt;/strong&gt;というのが重要.&lt;/p&gt;
&lt;p&gt;先程の&lt;code&gt;Pod&lt;/code&gt;のコンテナで&lt;code&gt;args&lt;/code&gt;に指定したコマンド&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;echo &amp;#34;abc&amp;#34;
yourcoolcmd
echo &amp;#34;def&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;はそれぞれ&lt;code&gt;/bin/sh -c echo ...&lt;/code&gt;というプロセスの子プロセスとして起動される.&lt;/p&gt;
&lt;p&gt;試しにMac上で同じコマンドを実行してみるとよくわかるが, たとえ途中のコマンド(&lt;code&gt;yourcoolcmd&lt;/code&gt;)が失敗しても親プロセスが止まらず最後のコマンド(&lt;code&gt;echo &amp;quot;def&amp;quot;&lt;/code&gt;)が正常に終了しているので&lt;code&gt;/bin/sh -c echo ...&lt;/code&gt;の終了ステータスは0(正常終了)になる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 途中の子プロセスが異常終了しても親プロセスが最後まで実行されている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ /bin/sh -c &lt;span class="s1"&gt;&amp;#39;echo &amp;#34;abc&amp;#34;; yourcoolcmd; echo &amp;#34;def&amp;#34;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;abc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/bin/sh: yourcoolcmd: &lt;span class="nb"&gt;command&lt;/span&gt; not found
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;def
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;したがって, &lt;code&gt;Pod&lt;/code&gt;の&lt;code&gt;command&lt;/code&gt;と&lt;code&gt;args&lt;/code&gt;で指定されたプロセスの終了ステータスが0になってしまうので,&lt;br&gt;
&lt;code&gt;Pod&lt;/code&gt;の&lt;code&gt;phase&lt;/code&gt;が&lt;code&gt;Succeeded&lt;/code&gt;となり&lt;code&gt;Job&lt;/code&gt;も成功扱いになっている(たぶん).&lt;/p&gt;
&lt;p&gt;これを防ぐためには, それぞれの終了ステータス(&lt;code&gt;$?&lt;/code&gt;)を観てエラーハンドリングするか, &lt;code&gt;set -e&lt;/code&gt;もしくは&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;を使うのが良い.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 終了ステータス($?)を観てエラーハンドリングする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ /bin/sh -c &lt;span class="s1"&gt;&amp;#39;echo &amp;#34;abc&amp;#34;; yourcoolcmd; if [ $? -ne 0 ]; then exit 1; fi; echo &amp;#34;def&amp;#34;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;abc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/bin/sh: yourcoolcmd: &lt;span class="nb"&gt;command&lt;/span&gt; not found
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# set -eを使う&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 途中で0以外の終了ステータスが発生したときにそこで終了する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ /bin/sh -c &lt;span class="s1"&gt;&amp;#39;set -e; echo &amp;#34;abc&amp;#34;; yourcoolcmd; echo &amp;#34;def&amp;#34;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;abc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/bin/sh: yourcoolcmd: &lt;span class="nb"&gt;command&lt;/span&gt; not found
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;127&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# &amp;amp;&amp;amp;を使う&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 前のコマンドが正常終了しない場合は次のコマンドが実行されない&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ /bin/sh -c &lt;span class="s1"&gt;&amp;#39;echo &amp;#34;abc&amp;#34; &amp;amp;&amp;amp; yourcoolcmd &amp;amp;&amp;amp; echo &amp;#34;def&amp;#34;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;abc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/bin/sh: yourcoolcmd: &lt;span class="nb"&gt;command&lt;/span&gt; not found
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;127&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="試してみる"&gt;試してみる
&lt;/h3&gt;&lt;p&gt;原因がなんとなくわかったので,&lt;br&gt;
さっきの&lt;code&gt;Job&lt;/code&gt;をちゃんと0以外の終了ステータスで終わるようにした.&lt;br&gt;
(バッチ処理を想定して&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;を使っているが, もちろん用途に応じて適宜&lt;code&gt;set -e&lt;/code&gt;とか&lt;code&gt;$?&lt;/code&gt;を使い分けるべき.)&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/a65bce66a4217df84258dbcd088477b6.js"&gt;&lt;/script&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# JobがBackoffLimitExceededで終了している&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f job-02.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get job example-job-command-not-found-2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME COMPLETIONS DURATION AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;example-job-command-not-found-2 0/1 2m14s 2m14s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get job example-job-command-not-found-2 -o yaml &lt;span class="p"&gt;|&lt;/span&gt; yq r - &lt;span class="s2"&gt;&amp;#34;status&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;conditions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - lastProbeTime: &lt;span class="s2"&gt;&amp;#34;2021-01-24T09:10:53Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; lastTransitionTime: &lt;span class="s2"&gt;&amp;#34;2021-01-24T09:10:53Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; message: Job has reached the specified backoff limit
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; reason: BackoffLimitExceeded
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; status: &lt;span class="s2"&gt;&amp;#34;True&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; type: Failed
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;failed: &lt;span class="m"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;startTime: &lt;span class="s2"&gt;&amp;#34;2021-01-24T09:10:40Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podのコンテナがちゃんと0以外の終了ステータス(exitCode)で終了している&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pod -l job-name&lt;span class="o"&gt;=&lt;/span&gt;example-job-command-not-found-2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;example-job-command-not-found-2-bq4bl 0/1 Error &lt;span class="m"&gt;0&lt;/span&gt; 3m16s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;example-job-command-not-found-2-jkdcw 0/1 Error &lt;span class="m"&gt;0&lt;/span&gt; 3m13s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pod example-job-command-not-found-2-bq4bl -o yaml &lt;span class="p"&gt;|&lt;/span&gt; yq r - &lt;span class="s2"&gt;&amp;#34;status&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;containerStatuses:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - containerID: containerd://09caecce3d813e48cacd53f90eefd5e4f18b7565af7c9351c7fef47dbe397834
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; image: docker.io/library/busybox:latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; imageID: docker.io/library/busybox@sha256:c5439d7db88ab5423999530349d327b04279ad3161d7596d2126dfb5b02bfd1f
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; lastState: &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: busybox
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ready: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; restartCount: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; started: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; state:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; terminated:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; containerID: containerd://09caecce3d813e48cacd53f90eefd5e4f18b7565af7c9351c7fef47dbe397834
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; exitCode: &lt;span class="m"&gt;127&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; finishedAt: &lt;span class="s2"&gt;&amp;#34;2021-01-24T09:10:42Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; reason: Error
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; startedAt: &lt;span class="s2"&gt;&amp;#34;2021-01-24T09:10:42Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;phase: Failed
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl logs example-job-command-not-found-2-bq4bl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;abc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/bin/sh: yourcoolcmd: not found&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;ちゃんとPodの終了ステータスが0以外となり, &lt;code&gt;Job&lt;/code&gt;が失敗扱いになったことを確認できた.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Kubernetes&lt;/code&gt;というよりはシェルスクリプトの基本のおさらいになってしまったが, たまにやってしまうので戒めとして書いた.&lt;/p&gt;
&lt;p&gt;終了ステータスの扱いは大切.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="俺によっかかって寝るねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="2316" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2021-01-24-sh-status/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2021-01-24-sh-status/sotochan_hu_d7c5cb38bc21287f.jpg 800w, https://blog.uzimihsr.com/post/2021-01-24-sh-status/sotochan_hu_ed687bfbcf25cc58.jpg 1600w, https://blog.uzimihsr.com/post/2021-01-24-sh-status/sotochan_hu_8a924b2f9dbfe146.jpg 2400w, https://blog.uzimihsr.com/post/2021-01-24-sh-status/sotochan.jpg 3088w" width="3088"&gt;&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a class="link" href="https://kubernetes.io/ja/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase" target="_blank" rel="noopener"
 &gt;https://kubernetes.io/ja/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>12月のそとちゃんまとめ(2020)</title><link>https://blog.uzimihsr.com/post/2020-12-30-sotochan/</link><pubDate>Wed, 30 Dec 2020 00:00:00 +0000</pubDate><guid>https://blog.uzimihsr.com/post/2020-12-30-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-12-30-sotochan/sotochan.jpg" alt="Featured image of post 12月のそとちゃんまとめ(2020)" /&gt;&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%91%e3%82%bd%e3%82%b3%e3%83%b3%e7%b5%b6%e5%af%be%e9%82%aa%e9%ad%94%e3%81%99%e3%82%8b%e3%81%ad%e3%81%93" &gt;パソコン絶対邪魔するねこ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e6%88%90%e9%95%b7" &gt;成長&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%af%e3%83%aa%e3%82%b9%e3%83%9e%e3%82%b9" &gt;クリスマス&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="パソコン絶対邪魔するねこ"&gt;パソコン絶対邪魔するねこ
&lt;/h3&gt;&lt;p&gt;今まであんまり邪魔してこなかったのに,&lt;br&gt;
俺が机で仕事をするようになってからやたらとパソコンの近くで遊ぶようになった.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ねこちゃんがキーボードに乗れないようにMacBook用のスタンド導入したんだけど…😭 &lt;a href="https://t.co/RApI7y92MD"&gt;pic.twitter.com/RApI7y92MD&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1336136657611804672?ref_src=twsrc%5Etfw"&gt;December 8, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;一度こうなるとそとちゃんが満足するまで撫でないといけないので, とても困る(うれしい).&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;かまってタイム &lt;a href="https://t.co/JWFFwY9U3f"&gt;pic.twitter.com/JWFFwY9U3f&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1339512480309997570?ref_src=twsrc%5Etfw"&gt;December 17, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;また, 今月導入した在宅勤務用のイスが気に入ったらしくて気を抜くとしょっちゅう占領していた.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;パソコンの次は椅子&lt;br&gt;仕事妨害の手段が日々効率化されていく &lt;a href="https://t.co/eB9v0SSaHY"&gt;pic.twitter.com/eB9v0SSaHY&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1336819841924141058?ref_src=twsrc%5Etfw"&gt;December 9, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;そとちゃんは変なところで肝が据わっているので, ちょっと動かしたくらいじゃぜんぜん降りようとしない&amp;hellip;&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;回した &lt;a href="https://t.co/xTI9NqPx57"&gt;pic.twitter.com/xTI9NqPx57&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1336825386672431106?ref_src=twsrc%5Etfw"&gt;December 10, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;俺が仕事してなくても夜はイスで寝てたりするので, 単純に座り心地が気に入ったのかも?&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ねた &lt;a href="https://t.co/9I0hipHXoF"&gt;pic.twitter.com/9I0hipHXoF&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1338477003515723777?ref_src=twsrc%5Etfw"&gt;December 14, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;h3 id="成長"&gt;成長
&lt;/h3&gt;&lt;p&gt;以前はねずみのおもちゃを失くすとそのままやる気をなくして寝てたりしたんだけど,&lt;/p&gt;
&lt;p&gt;最近は失くしたらすぐに鳴いて教えてくれるようになった. えらい😊&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;「おもちゃが取れないところに入っちゃったからとってください」の顔 &lt;a href="https://t.co/SYw2YPjRau"&gt;pic.twitter.com/SYw2YPjRau&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1341241932727549953?ref_src=twsrc%5Etfw"&gt;December 22, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;でもそれ以前におもちゃを失くさずに遊べるようになると, もっとえらいなあ&amp;hellip;😅&lt;br&gt;
(そとちゃんはなぜか台所でねずみをドリブルするのが好きなので, 冷蔵庫の下によくシュートして取れなくなっちゃう)&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ねこおちてた &lt;a href="https://t.co/uehluq1cmd"&gt;pic.twitter.com/uehluq1cmd&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1341245309477769216?ref_src=twsrc%5Etfw"&gt;December 22, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;h3 id="クリスマス"&gt;クリスマス
&lt;/h3&gt;&lt;p&gt;今年もそとちゃんがかわいいサンタさんになってくれた😊&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;サンタねこ &lt;a href="https://t.co/cK1ZWEUct4"&gt;pic.twitter.com/cK1ZWEUct4&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1342073934712205312?ref_src=twsrc%5Etfw"&gt;December 24, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;&amp;hellip;しかし服が結構動きづらくてそとちゃんが不機嫌だったので, サンタさんは数分で終了&amp;hellip;&lt;/p&gt;
&lt;p&gt;詫びちゅーるでなんとか許してもらった.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;クリスマスちゅーる &lt;a href="https://t.co/lP8DkHjiJy"&gt;pic.twitter.com/lP8DkHjiJy&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1342080224708550659?ref_src=twsrc%5Etfw"&gt;December 24, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;来年は腕を通さないマントタイプの服にしよう&amp;hellip;&lt;/p&gt;
&lt;p&gt;クリスマスプレゼントには&lt;a class="link" href="https://www.garigari-cat.com/product/nyancoroby/nyancoroby-box/" target="_blank" rel="noopener"
 &gt;ニャンコロビー&lt;/a&gt;をあげた🎁&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;今年もいい子にしてたねこにクリスマスプレゼント &lt;a href="https://t.co/vzOqXSmFjR"&gt;pic.twitter.com/vzOqXSmFjR&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1342089746269364226?ref_src=twsrc%5Etfw"&gt;December 24, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;喜んでくれてよかった🎉&lt;/p&gt;
&lt;div class="video-wrapper"&gt;
 &lt;iframe loading="lazy" 
 src="https://www.youtube.com/embed/ykZPLXpj3-Q" 
 allowfullscreen 
 title="YouTube Video"
 &gt;
 &lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;(この後1日で飽きちゃったのは秘密&amp;hellip;😭)&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;今月もそとちゃんはよく遊んでよく食べて良い子だった.&lt;/p&gt;
&lt;p&gt;世間は大変な1年だったけどそとちゃんは今年も特に大きな病気(誤飲騒動を除く)はなかったし,&lt;/p&gt;
&lt;p&gt;俺が在宅勤務になったのもあって去年よりも一緒に遊べる時間が増えて楽しかった.&lt;/p&gt;
&lt;p&gt;来年もそとちゃんが幸せに暮らせるようにしたい.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="そとちゃんサンタ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-12-30-sotochan/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-12-30-sotochan/sotochan_hu_9254beb5717148a6.jpg 800w, https://blog.uzimihsr.com/post/2020-12-30-sotochan/sotochan_hu_9e75012dea0b9825.jpg 1600w, https://blog.uzimihsr.com/post/2020-12-30-sotochan/sotochan_hu_29802ac0c010ec29.jpg 2400w, https://blog.uzimihsr.com/post/2020-12-30-sotochan/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>Hugoを新しくしてThemeを変えた</title><link>https://blog.uzimihsr.com/post/2020-12-23-hugo-theme/</link><pubDate>Wed, 23 Dec 2020 22:30:18 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-12-23-hugo-theme/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-12-23-hugo-theme/sotochan.jpg" alt="Featured image of post Hugoを新しくしてThemeを変えた" /&gt;&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Hugo&lt;/code&gt;を更新した&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Hugo&lt;/code&gt;の&lt;code&gt;Theme&lt;/code&gt;を&lt;code&gt;Beautiful Hugo&lt;/code&gt;から&lt;code&gt;Hugo Theme Stack&lt;/code&gt;に乗り換えた&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Mojave 10.14&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/gohugoio/hugo" target="_blank" rel="noopener"
 &gt;Hugo&lt;/a&gt; v0.79.0
&lt;ul&gt;
&lt;li&gt;今回v0.56.3からv0.79.0に更新した&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/CaiJimmy/hugo-theme-stack" target="_blank" rel="noopener"
 &gt;Hugo Theme Stack&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#hugo%e3%81%ae%e6%9b%b4%e6%96%b0" &gt;Hugoの更新&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%aa%e3%82%93%e3%81%8b%e3%81%8a%e3%81%8b%e3%81%97%e3%81%84" &gt;なんかおかしい&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#theme%e3%81%ae%e5%a4%89%e6%9b%b4" &gt;Themeの変更&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="hugoの更新"&gt;Hugoの更新
&lt;/h3&gt;&lt;p&gt;使っている&lt;code&gt;Hugo&lt;/code&gt;のバージョンが結構古くなっていたので, 最新版にする.&lt;/p&gt;
&lt;p&gt;自分の場合は&lt;code&gt;brew&lt;/code&gt;でインストールしているので, まずは&lt;code&gt;brew upgrade&lt;/code&gt;&amp;hellip;&lt;/p&gt;
&lt;p&gt;しようとしたら怒られた.&lt;/p&gt;
&lt;p&gt;なんか&lt;code&gt;GitHub&lt;/code&gt;と&lt;code&gt;brew&lt;/code&gt;の間でいろいろあって, &lt;code&gt;shallow clone&lt;/code&gt;をしないように変更があったらしい&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# どうして...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ brew update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Error:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; homebrew-core is a shallow clone.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; homebrew-cask is a shallow clone.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;To &lt;span class="sb"&gt;`&lt;/span&gt;brew update&lt;span class="sb"&gt;`&lt;/span&gt;, first run:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core fetch --unshallow
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask fetch --unshallow
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;This restriction has been made on GitHub&lt;span class="s1"&gt;&amp;#39;s request because updating shallow
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;clones is an extremely expensive operation due to the tree layout and traffic of
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;Homebrew/homebrew-core and Homebrew/homebrew-cask. We don&amp;#39;&lt;/span&gt;t &lt;span class="k"&gt;do&lt;/span&gt; this &lt;span class="k"&gt;for&lt;/span&gt; you
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;automatically to avoid repeatedly performing an expensive unshallow operation in
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;CI systems &lt;span class="o"&gt;(&lt;/span&gt;which should instead be fixed to not use shallow clones&lt;span class="o"&gt;)&lt;/span&gt;. Sorry &lt;span class="k"&gt;for&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;the inconvenience!
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 言われたとおりにする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core fetch --unshallow
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask fetch --unshallow
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# できた&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ brew update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Updated &lt;span class="m"&gt;2&lt;/span&gt; taps &lt;span class="o"&gt;(&lt;/span&gt;homebrew/core and homebrew/cask&lt;span class="o"&gt;)&lt;/span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;気を取り直して&lt;code&gt;Hugo&lt;/code&gt;を更新する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 更新前の状態&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ hugo version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Hugo Static Site Generator v0.56.3/extended darwin/amd64 BuildDate: unknown
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# hugoを更新&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ brew upgrade hugo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 最新版になった&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ hugo version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Hugo Static Site Generator v0.79.0/extended darwin/amd64 BuildDate: unknown&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;できた.&lt;/p&gt;
&lt;h3 id="なんかおかしい"&gt;なんかおかしい
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Hugo&lt;/code&gt;の更新後にブログの状態をローカルで確認するために&lt;code&gt;hugo server&lt;/code&gt;を実行したらなんかやたらと警告が出た.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ページを立ち上げてみる...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; blog
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ hugo server -D
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;WARN 2020/12/17 23:55:53 Failed to get translated string &lt;span class="k"&gt;for&lt;/span&gt; language &lt;span class="s2"&gt;&amp;#34;en&amp;#34;&lt;/span&gt; and ID &lt;span class="s2"&gt;&amp;#34;postedOnDate&amp;#34;&lt;/span&gt;: template: :1:13: executing &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt; at &amp;lt;.Count&amp;gt;: can&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;t evaluate field Count in &lt;span class="nb"&gt;type&lt;/span&gt; string
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;なんかテンプレートに渡されるべきフィールドが変わっちゃってる?っぽくて直し方がよくわからなかった(無能)のと,&lt;br&gt;
今まで使ってた&lt;code&gt;Beautiful Hugo&lt;/code&gt;の開発が2019年の11月で止まっちゃってた&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;のもあって, これを機に&lt;code&gt;Theme&lt;/code&gt;を変えることにした.&lt;br&gt;
&lt;del&gt;(自分で作ろうとしないあたりがダメ)&lt;/del&gt;&lt;/p&gt;
&lt;h3 id="themeの変更"&gt;Themeの変更
&lt;/h3&gt;&lt;p&gt;適当に&lt;code&gt;Theme&lt;/code&gt;の一覧&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;を漁ってたら良さそうなのがあった.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Hugo Theme Stack&lt;/code&gt;&lt;sup id="fnref:4"&gt;&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref"&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;シンプルなデザインでいい感じ.&lt;/p&gt;
&lt;p&gt;このまま&lt;code&gt;theme&lt;/code&gt;配下に&lt;code&gt;submodule add&lt;/code&gt;してもいいんだけど,&lt;br&gt;
どうしても細かい変更がしたいことがあったりするので&lt;a class="link" href="https://github.com/uzimihsr/hugo-theme-stack" target="_blank" rel="noopener"
 &gt;fork&lt;/a&gt;して使わせていただく&amp;hellip;&lt;br&gt;
(ライセンスなどはいじらないこと!)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# themeを追加する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git submodule add https://github.com/uzimihsr/hugo-theme-stack.git themes/hugo-theme-stack
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# サンプルサイトの内容をコピーする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cp -r ./themes/hugo-theme-stack/exampleSite/* ./&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;あとは&lt;code&gt;config.toml&lt;/code&gt;の内容を&lt;code&gt;config.yaml&lt;/code&gt;に書き直したり,&lt;br&gt;
今までの記事の内容を&lt;code&gt;content/post&lt;/code&gt;配下に移動したり画像ファイルの場所を変えたりしてお引越しは完了.&lt;/p&gt;
&lt;p&gt;あまりにも泥臭い作業だったので詳細は省くけど,&lt;br&gt;
今までとは&lt;code&gt;post&lt;/code&gt;配下の構造が違う(記事タイトルのディレクトリ配下に&lt;code&gt;index.md&lt;/code&gt;と画像ファイルを配置する方式)ので元のブログ用ディレクトリの内容をいい感じにコピーするスクリプトを書いたりもした.&lt;br&gt;
(ほんとにしょぼかったので割愛)&lt;/p&gt;
&lt;p&gt;とりあえず元の記事は全部引っ越せたのでおしまい.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;ブログの&lt;code&gt;Theme&lt;/code&gt;を変えてみた.&lt;/p&gt;
&lt;p&gt;前のデザインもシンプルで良かったけど, 新しい&lt;code&gt;Theme&lt;/code&gt;もかなりいい感じ.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="しっぽをおさえて寝るねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-12-23-hugo-theme/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-12-23-hugo-theme/sotochan_hu_873185c407255803.jpg 800w, https://blog.uzimihsr.com/post/2020-12-23-hugo-theme/sotochan_hu_c87dd736064146db.jpg 1600w, https://blog.uzimihsr.com/post/2020-12-23-hugo-theme/sotochan_hu_1d0a41b4f59c6b50.jpg 2400w, https://blog.uzimihsr.com/post/2020-12-23-hugo-theme/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/Homebrew/brew/pull/9383" target="_blank" rel="noopener"
 &gt;https://github.com/Homebrew/brew/pull/9383&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/halogenica/beautifulhugo" target="_blank" rel="noopener"
 &gt;https://github.com/halogenica/beautifulhugo&lt;/a&gt;&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;&lt;a class="link" href="https://themes.gohugo.io/" target="_blank" rel="noopener"
 &gt;https://themes.gohugo.io/&lt;/a&gt;&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:4"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/CaiJimmy/hugo-theme-stack" target="_blank" rel="noopener"
 &gt;https://github.com/CaiJimmy/hugo-theme-stack&lt;/a&gt;&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>kindで作ったKubernetesクラスタでHelmを試した</title><link>https://blog.uzimihsr.com/post/2020-12-17-helm-on-kind/</link><pubDate>Thu, 17 Dec 2020 12:10:24 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-12-17-helm-on-kind/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-12-17-helm-on-kind/sotochan.jpg" alt="Featured image of post kindで作ったKubernetesクラスタでHelmを試した" /&gt;&lt;h2 id="めっちゃべんり"&gt;めっちゃべんり
&lt;/h2&gt;&lt;p&gt;kindで作成したKubernetesクラスタを使ってHelmクイックスタートの内容を試した.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Helm&lt;/code&gt;のCLIをMacにインストールした&lt;/li&gt;
&lt;li&gt;サンプル&lt;code&gt;Chart&lt;/code&gt;を&lt;code&gt;Kubernetes&lt;/code&gt;クラスタにインストールした&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Chartリポジトリの追加&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ helm repo add &amp;lt;リポジトリ名&amp;gt; &amp;lt;リポジトリURL&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Chartリポジトリの更新&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ helm repo update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 利用可能なChartの一覧を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ helm search repo &amp;lt;キーワード&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Chartの簡易情報&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ helm show chart &amp;lt;Chart名&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Chartのインストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ helm install &amp;lt;Chart名&amp;gt; --generate-name
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# リリースの確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ helm ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Chartのアンインストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ helm uninstall &amp;lt;リリース名&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Mojave 10.14&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/editions/community/docker-ce-desktop-mac" target="_blank" rel="noopener"
 &gt;Docker Desktop for Mac&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Version 2.5.0.0&lt;/li&gt;
&lt;li&gt;Docker version 19.03.13&lt;/li&gt;
&lt;li&gt;インストール済み&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/kubernetes-sigs/kind/" target="_blank" rel="noopener"
 &gt;kind&lt;/a&gt; v0.9.0 go1.15.5 darwin/amd64
&lt;ul&gt;
&lt;li&gt;インストール済み&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/kubernetes/kubernetes" target="_blank" rel="noopener"
 &gt;Kubernetes&lt;/a&gt; v1.19.1
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;kind&lt;/code&gt;で作成&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/kubernetes/kubectl" target="_blank" rel="noopener"
 &gt;kubectl&lt;/a&gt; Client Version: v1.19.3
&lt;ul&gt;
&lt;li&gt;インストール済み&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/helm/helm" target="_blank" rel="noopener"
 &gt;Helm&lt;/a&gt; v3.4.2+g23dd3af
&lt;ul&gt;
&lt;li&gt;今回インストールする&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#helm%e3%81%ab%e3%81%a4%e3%81%84%e3%81%a6" &gt;Helmについて&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#kubernetes%e3%82%af%e3%83%a9%e3%82%b9%e3%82%bf%e3%81%ae%e6%ba%96%e5%82%99" &gt;Kubernetesクラスタの準備&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#mac%e3%81%abhelm%e3%82%92%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" &gt;MacにHelmをインストール&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#chart%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" &gt;Chartのインストール&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#chart%e3%81%ae%e3%82%a2%e3%83%b3%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" &gt;Chartのアンインストール&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="helmについて"&gt;Helmについて
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Helm&lt;/code&gt;&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;は&lt;code&gt;Kubernetes&lt;/code&gt;用のパッケージマネージャー.&lt;/p&gt;
&lt;p&gt;アプリケーションを動かすために必要な各種&lt;code&gt;Kubernetes&lt;/code&gt;リソース(&lt;code&gt;Pod&lt;/code&gt;, &lt;code&gt;Service&lt;/code&gt;, &lt;code&gt;ConfigMap&lt;/code&gt;など)の定義や依存関係, 設定をまとめた&lt;code&gt;Chart&lt;/code&gt;を使うことでアプリケーションのデプロイを簡単にしてくれる. らしい.&lt;br&gt;
(&lt;code&gt;Ubuntu&lt;/code&gt;でいう&lt;code&gt;apt&lt;/code&gt;, &lt;code&gt;CentOS&lt;/code&gt;でいう&lt;code&gt;yum&lt;/code&gt;みたいなもの)&lt;/p&gt;
&lt;p&gt;以前は&lt;code&gt;Chart&lt;/code&gt;を解釈するための&lt;code&gt;Tiller&lt;/code&gt;という&lt;code&gt;Helm&lt;/code&gt;専用のコンポーネントを&lt;code&gt;Kubernetes&lt;/code&gt;クラスタにデプロイする必要があって面倒そうだったのでちょっと敬遠してたんだけど,&lt;br&gt;
いつの間にか(&lt;code&gt;Helm v3.0&lt;/code&gt;以降)&lt;code&gt;Tiller&lt;/code&gt;が不要になった&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;らしいので試してみた.&lt;/p&gt;
&lt;h3 id="kubernetesクラスタの準備"&gt;Kubernetesクラスタの準備
&lt;/h3&gt;&lt;p&gt;まずは&lt;code&gt;Helm&lt;/code&gt;でアプリを動かすための&lt;code&gt;Kubernetes&lt;/code&gt;クラスタを&lt;code&gt;kind&lt;/code&gt;で作成する.&lt;/p&gt;
&lt;p&gt;今回は一応&lt;code&gt;Ingress&lt;/code&gt;が使えるよう設定したけど, それも省けばかなり&lt;a class="link" href="https://uzimihsr.github.io/post/2020-12-14-kind-kubernetes-in-docker/#%E3%82%AF%E3%83%A9%E3%82%B9%E3%82%BF%E3%81%AE%E8%B5%B7%E5%8B%95" target="_blank" rel="noopener"
 &gt;かんたんにクラスタを作成&lt;/a&gt;できる.&lt;/p&gt;
&lt;p&gt;やっぱり&lt;code&gt;kind&lt;/code&gt;はすごい.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# kindでクラスタを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat &lt;span class="s"&gt;&amp;lt;&amp;lt;EOF | kind create cluster --name helm-practice --config=-
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: Cluster
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: kind.x-k8s.io/v1alpha4
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;nodes:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;- role: control-plane
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; kubeadmConfigPatches:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; - |
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; kind: InitConfiguration
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; nodeRegistration:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; kubeletExtraArgs:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; node-labels: &amp;#34;ingress-ready=true&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; extraPortMappings:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; - containerPort: 80
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; hostPort: 80
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; protocol: TCP
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; - containerPort: 443
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; hostPort: 443
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; protocol: TCP
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Creating cluster &lt;span class="s2"&gt;&amp;#34;helm-practice&amp;#34;&lt;/span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✓ Ensuring node image &lt;span class="o"&gt;(&lt;/span&gt;kindest/node:v1.19.1&lt;span class="o"&gt;)&lt;/span&gt; 🖼
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✓ Preparing nodes 📦
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✓ Writing configuration 📜
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✓ Starting control-plane 🕹️
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✓ Installing CNI 🔌
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✓ Installing StorageClass 💾
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Set kubectl context to &lt;span class="s2"&gt;&amp;#34;kind-helm-practice&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;You can now use your cluster with:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl cluster-info --context kind-helm-practice
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Thanks &lt;span class="k"&gt;for&lt;/span&gt; using kind! 😊
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# contextは自動で切り替わるけど念の為明示的に変えておく&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl config use-context kind-helm-practice
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Switched to context &lt;span class="s2"&gt;&amp;#34;kind-helm-practice&amp;#34;&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Ingress Controllerのデプロイ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/kind/deploy.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;namespace/ingress-nginx created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;serviceaccount/ingress-nginx created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;configmap/ingress-nginx-controller created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;clusterrole.rbac.authorization.k8s.io/ingress-nginx created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;role.rbac.authorization.k8s.io/ingress-nginx created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rolebinding.rbac.authorization.k8s.io/ingress-nginx created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/ingress-nginx-controller-admission created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/ingress-nginx-controller created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps/ingress-nginx-controller created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;serviceaccount/ingress-nginx-admission created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;role.rbac.authorization.k8s.io/ingress-nginx-admission created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;job.batch/ingress-nginx-admission-create created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;job.batch/ingress-nginx-admission-patch created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;wait&lt;/span&gt; --namespace ingress-nginx &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --for&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;condition&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ready pod &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --selector&lt;span class="o"&gt;=&lt;/span&gt;app.kubernetes.io/component&lt;span class="o"&gt;=&lt;/span&gt;controller &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --timeout&lt;span class="o"&gt;=&lt;/span&gt;90s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/ingress-nginx-controller-6df69bd4f7-brc52 condition met&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="macにhelmをインストール"&gt;MacにHelmをインストール
&lt;/h3&gt;&lt;p&gt;以降はクイックスタート&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;の内容をなぞっていく.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Helm&lt;/code&gt;を使うにはまず&lt;code&gt;Chart&lt;/code&gt;を&lt;code&gt;Kubernetes&lt;/code&gt;クラスタに投下するためのCLIが必要になる.&lt;/p&gt;
&lt;p&gt;&amp;hellip;が, &lt;code&gt;Mac&lt;/code&gt;の場合は&lt;code&gt;brew&lt;/code&gt;で入るのでらくちん.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# helmをインストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ brew install helm
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ which helm
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/usr/local/bin/helm
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 動作確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ helm version --short
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;v3.4.2+g23dd3af
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# completionを効かせておくと楽&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;source&lt;/span&gt; &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;helm completion zsh&lt;span class="o"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;CLIがインストールできたら, &lt;code&gt;Chart&lt;/code&gt;を取得するためのリポジトリを追加する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Chartリポジトリの追加&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ helm repo add stable https://charts.helm.sh/stable
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;stable&amp;#34;&lt;/span&gt; has been added to your repositories
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Chartリポジトリを更新する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ helm repo update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Hang tight &lt;span class="k"&gt;while&lt;/span&gt; we grab the latest from your chart repositories...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...Successfully got an update from the &lt;span class="s2"&gt;&amp;#34;stable&amp;#34;&lt;/span&gt; chart repository
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Update Complete. ⎈Happy Helming!⎈&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;これで&lt;code&gt;Helm&lt;/code&gt;の準備はOK.&lt;/p&gt;
&lt;h3 id="chartのインストール"&gt;Chartのインストール
&lt;/h3&gt;&lt;p&gt;いよいよ&lt;code&gt;Chart&lt;/code&gt;を&lt;code&gt;Kubernetes&lt;/code&gt;クラスタにインストールする.&lt;/p&gt;
&lt;p&gt;今回は例として&lt;code&gt;MySQL&lt;/code&gt;の&lt;code&gt;Chart&lt;/code&gt;を使う.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Helm&lt;/code&gt;のCLIは&lt;code&gt;kubectl&lt;/code&gt;の&lt;code&gt;context&lt;/code&gt;を参照して&lt;code&gt;Kubernetes API&lt;/code&gt;へ操作を行うので,&lt;br&gt;
&lt;code&gt;context&lt;/code&gt;が所望の設定になっているか注意する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Chartをインストールする前の状態&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get all
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/kubernetes ClusterIP 10.96.0.1 &amp;lt;none&amp;gt; 443/TCP 10m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Chart(stable/mysql)の簡易情報を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ helm show chart stable/mysql
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apiVersion: v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;appVersion: 5.7.30
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deprecated: &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;description: DEPRECATED - Fast, reliable, scalable, and easy to use open-source relational
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; database system.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;home: https://www.mysql.com/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;icon: https://www.mysql.com/common/logos/logo-mysql-170x115.png
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;keywords:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- mysql
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- database
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- sql
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;name: mysql
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sources:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- https://github.com/kubernetes/charts
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- https://github.com/docker-library/mysql
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;version: 1.6.9
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Chartをインストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ helm install stable/mysql --generate-name
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;WARNING: This chart is deprecated
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME: mysql-1608125461
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;LAST DEPLOYED: Wed Dec &lt;span class="m"&gt;16&lt;/span&gt; 22:31:04 &lt;span class="m"&gt;2020&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAMESPACE: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;STATUS: deployed
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;REVISION: &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NOTES:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;MySQL can be accessed via port &lt;span class="m"&gt;3306&lt;/span&gt; on the following DNS name from within your cluster:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mysql-1608125461.default.svc.cluster.local
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;To get your root password run:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;kubectl get secret --namespace default mysql-1608125461 -o &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;{.data.mysql-root-password}&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; base64 --decode&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;To connect to your database:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1. Run an Ubuntu pod that you can use as a client:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubectl run -i --tty ubuntu --image&lt;span class="o"&gt;=&lt;/span&gt;ubuntu:16.04 --restart&lt;span class="o"&gt;=&lt;/span&gt;Never -- bash -il
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2. Install the mysql client:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; $ apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get install mysql-client -y
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3. Connect using the mysql cli, &lt;span class="k"&gt;then&lt;/span&gt; provide your password:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; $ mysql -h mysql-1608125461 -p
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;To connect to your database directly from outside the K8s cluster:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;MYSQL_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;127.0.0.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;MYSQL_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;3306&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Execute the following command to route the connection:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubectl port-forward svc/mysql-1608125461 &lt;span class="m"&gt;3306&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; mysql -h &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;MYSQL_HOST&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; -P&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;MYSQL_PORT&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; -u root -p&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# DeploymentとServiceが作成されている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get all
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/mysql-1608125461-bfdcccddb-h97b8 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 66s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/kubernetes ClusterIP 10.96.0.1 &amp;lt;none&amp;gt; 443/TCP 11m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/mysql-1608125461 ClusterIP 10.96.6.222 &amp;lt;none&amp;gt; 3306/TCP 66s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY UP-TO-DATE AVAILABLE AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps/mysql-1608125461 1/1 &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 66s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME DESIRED CURRENT READY AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;replicaset.apps/mysql-1608125461-bfdcccddb &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 66s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Helmでデプロイされたリリースの確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ helm ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME 	NAMESPACE	REVISION	UPDATED 	STATUS 	CHART 	APP VERSION
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mysql-1608125461	default 	&lt;span class="m"&gt;1&lt;/span&gt; 	2020-12-16 22:31:04.174492 +0900 JST	deployed	mysql-1.6.9	5.7.30&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;MySQL&lt;/code&gt;の&lt;code&gt;Deployment&lt;/code&gt;とそれに対応した&lt;code&gt;Service&lt;/code&gt;が作成されている.&lt;/p&gt;
&lt;p&gt;あとは&lt;code&gt;Chart&lt;/code&gt;インストール時のメッセージに従って動作確認してみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Macからクラスタ内のServiceにポート転送する(別のシェルで実行)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl port-forward svc/mysql-1608125461 &lt;span class="m"&gt;3306&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Forwarding from 127.0.0.1:3306 -&amp;gt; &lt;span class="m"&gt;3306&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Forwarding from &lt;span class="o"&gt;[&lt;/span&gt;::1&lt;span class="o"&gt;]&lt;/span&gt;:3306 -&amp;gt; &lt;span class="m"&gt;3306&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Chartで自動生成されたSecretからDBのパスワードを取得&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nv"&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;kubectl get secret --namespace default mysql-1608125461 -o &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;{.data.mysql-root-password}&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; base64 --decode&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# クラスタ外(Mac)からクラスタ内のMySQLに接続&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nv"&gt;MYSQL_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;127.0.0.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nv"&gt;MYSQL_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;3306&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mysql -h &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;MYSQL_HOST&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; -P&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;MYSQL_PORT&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; -u root -p&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mysql: &lt;span class="o"&gt;[&lt;/span&gt;Warning&lt;span class="o"&gt;]&lt;/span&gt; Using a password on the &lt;span class="nb"&gt;command&lt;/span&gt; line interface can be insecure.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Welcome to the MySQL monitor. Commands end with &lt;span class="p"&gt;;&lt;/span&gt; or &lt;span class="se"&gt;\g&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Your MySQL connection id is &lt;span class="m"&gt;167&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Server version: 5.7.30 MySQL Community Server &lt;span class="o"&gt;(&lt;/span&gt;GPL&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Copyright &lt;span class="o"&gt;(&lt;/span&gt;c&lt;span class="o"&gt;)&lt;/span&gt; 2000, 2019, Oracle and/or its affiliates. All rights reserved.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Oracle is a registered trademark of Oracle Corporation and/or its
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;affiliates. Other names may be trademarks of their respective
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;owners.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Type &lt;span class="s1"&gt;&amp;#39;help;&amp;#39;&lt;/span&gt; or &lt;span class="s1"&gt;&amp;#39;\h&amp;#39;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; help. Type &lt;span class="s1"&gt;&amp;#39;\c&amp;#39;&lt;/span&gt; to clear the current input statement.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mysql&amp;gt; SHOW DATABASES&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;+--------------------+
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; Database &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;+--------------------+
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; information_schema &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; mysql &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; performance_schema &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; sys &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;+--------------------+
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;4&lt;/span&gt; rows in &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;0.01 sec&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mysql&amp;gt; ^DBye&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;Chart&lt;/code&gt;でインストールした&lt;code&gt;MySQL&lt;/code&gt;がちゃんと動いていることを確認できた.&lt;/p&gt;
&lt;p&gt;やったぜ.&lt;/p&gt;
&lt;h3 id="chartのアンインストール"&gt;Chartのアンインストール
&lt;/h3&gt;&lt;p&gt;最後に&lt;code&gt;Chart&lt;/code&gt;をアンインストールしてみる.&lt;/p&gt;
&lt;p&gt;これもコマンド1発.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Chartをアンインストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ helm uninstall mysql-1608125461
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;release &lt;span class="s2"&gt;&amp;#34;mysql-1608125461&amp;#34;&lt;/span&gt; uninstalled
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# リリースが消えている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ helm ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME	NAMESPACE	REVISION	UPDATED	STATUS	CHART	APP VERSION
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# KubernetesもChartをインストールする前の状態に戻っている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get all
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/kubernetes ClusterIP 10.96.0.1 &amp;lt;none&amp;gt; 443/TCP 33m&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;あっさり消えた.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Helm&lt;/code&gt;を使って&lt;code&gt;Chart&lt;/code&gt;を&lt;code&gt;Kubernetes&lt;/code&gt;にインストールしてみた.&lt;/p&gt;
&lt;p&gt;なんと&lt;code&gt;YAML&lt;/code&gt;を1度も書かずに, &lt;code&gt;CentOS&lt;/code&gt;で&lt;code&gt;yum install&lt;/code&gt;するような感覚で&lt;code&gt;Kubernetes&lt;/code&gt;上でアプリを動かせてしまった. すごい.&lt;/p&gt;
&lt;p&gt;どうして今まで使ってこなかったんだろうというくらい便利.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;helm&lt;/code&gt;は神.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="本棚に隠れていたねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-12-17-helm-on-kind/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-12-17-helm-on-kind/sotochan_hu_5520034b0a2be1d6.jpg 800w, https://blog.uzimihsr.com/post/2020-12-17-helm-on-kind/sotochan_hu_797a7cdbb1b2db0f.jpg 1600w, https://blog.uzimihsr.com/post/2020-12-17-helm-on-kind/sotochan_hu_8339b1f0ef1a5cf6.jpg 2400w, https://blog.uzimihsr.com/post/2020-12-17-helm-on-kind/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a class="link" href="https://helm.sh/" target="_blank" rel="noopener"
 &gt;https://helm.sh/&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;a class="link" href="https://helm.sh/docs/faq/#changes-since-helm-2" target="_blank" rel="noopener"
 &gt;https://helm.sh/docs/faq/#changes-since-helm-2&lt;/a&gt;&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;&lt;a class="link" href="https://helm.sh/docs/intro/quickstart/" target="_blank" rel="noopener"
 &gt;https://helm.sh/docs/intro/quickstart/&lt;/a&gt;&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Docker Desktop for MacのHyperKit VMに入る</title><link>https://blog.uzimihsr.com/post/2020-12-15-docker-desktop-for-mac-hyperkit-vm/</link><pubDate>Tue, 15 Dec 2020 21:10:35 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-12-15-docker-desktop-for-mac-hyperkit-vm/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-12-15-docker-desktop-for-mac-hyperkit-vm/sotochan.jpg" alt="Featured image of post Docker Desktop for MacのHyperKit VMに入る" /&gt;&lt;h2 id="コンテナのログファイルが見たい"&gt;コンテナのログファイルが見たい
&lt;/h2&gt;&lt;p&gt;Docker Desktop for MacでDockerのホストOSに入ってコンテナのログファイルが確認したかったんだけど詰まったのでメモ.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://github.com/justincormack/nsenter1" target="_blank" rel="noopener"
 &gt;特権コンテナ&lt;/a&gt;で&lt;code&gt;nsenter&lt;/code&gt;を実行するのがかんたん.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 特権コンテナを実行してホストOSに入る&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker run -it --rm --privileged --pid&lt;span class="o"&gt;=&lt;/span&gt;host justincormack/nsenter1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Mojave 10.14&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/editions/community/docker-ce-desktop-mac" target="_blank" rel="noopener"
 &gt;Docker Desktop for Mac&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Version 2.5.0.0&lt;/li&gt;
&lt;li&gt;Docker version 19.03.13&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やりかた"&gt;やりかた
&lt;/h2&gt;&lt;h3 id="macにはない"&gt;Macにはない?
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Linux&lt;/code&gt;上で&lt;code&gt;Docker&lt;/code&gt;コンテナを実行したときのログファイルはホストOSの&lt;code&gt;/var/lib/docker/containers/&amp;lt;ContainerID&amp;gt;&lt;/code&gt;に吐き出されるんだけど,&lt;br&gt;
&lt;code&gt;Docker Desktop for Mac&lt;/code&gt;で動かしたコンテナのログを見ようとしてもそんなディレクトリがそもそも&lt;code&gt;macOS&lt;/code&gt;上に存在しない&amp;hellip;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# hellp-worldの実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run hello-world
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Hello from Docker!
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;This message shows that your installation appears to be working correctly.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;To generate this message, Docker took the following steps:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 1. The Docker client contacted the Docker daemon.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 2. The Docker daemon pulled the &lt;span class="s2"&gt;&amp;#34;hello-world&amp;#34;&lt;/span&gt; image from the Docker Hub.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;(&lt;/span&gt;amd64&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 3. The Docker daemon created a new container from that image which runs the
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; executable that produces the output you are currently reading.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 4. The Docker daemon streamed that output to the Docker client, which sent it
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; to your terminal.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;To try something more ambitious, you can run an Ubuntu container with:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; $ docker run -it ubuntu bash
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Share images, automate workflows, and more with a free Docker ID:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; https://hub.docker.com/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;For more examples and ideas, visit:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; https://docs.docker.com/get-started/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# コンテナIDの確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container ls -a
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;f9a220a39165 hello-world &lt;span class="s2"&gt;&amp;#34;/hello&amp;#34;&lt;/span&gt; &lt;span class="m"&gt;17&lt;/span&gt; seconds ago Exited &lt;span class="o"&gt;(&lt;/span&gt;0&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="m"&gt;16&lt;/span&gt; seconds ago busy_matsumoto
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container inspect f9a220a39165 -f &lt;span class="o"&gt;{{&lt;/span&gt;.Id&lt;span class="o"&gt;}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;f9a220a391654fd66c8094a2965da6e1255ffb97c6db047d0aef1985d2e49659
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ディレクトリがない&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls /var/lib/docker/containers/f9a220a391654fd66c8094a2965da6e1255ffb97c6db047d0aef1985d2e49659
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ls: /var/lib/docker/containers/f9a220a391654fd66c8094a2965da6e1255ffb97c6db047d0aef1985d2e49659: No such file or directory
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls /var/lib/docker/containers
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ls: /var/lib/docker/containers: No such file or directory&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;これは&lt;code&gt;Docker Desktop for Mac&lt;/code&gt;の&lt;code&gt;Docker&lt;/code&gt;が&lt;code&gt;macOS&lt;/code&gt;上で直接動作しているわけではなく,&lt;br&gt;
&lt;code&gt;macOS&lt;/code&gt;上に構築された&lt;code&gt;HyperKit VM&lt;/code&gt;の上で動作している&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;ため.&lt;/p&gt;
&lt;h3 id="vmに入る"&gt;VMに入る
&lt;/h3&gt;&lt;p&gt;じゃあ&lt;code&gt;HyperKit VM&lt;/code&gt;に入ればいいじゃんという話.&lt;/p&gt;
&lt;p&gt;ちょっと調べると&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;~/Library/Containers/com.docker.docker/Data/vms/0/tty&lt;/code&gt;を&lt;code&gt;screen&lt;/code&gt;で呼び出す&lt;/li&gt;
&lt;li&gt;特権コンテナを立ち上げて&lt;code&gt;nsenter&lt;/code&gt;でホストOSに入る&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;といった方法&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;が出てきた.&lt;/p&gt;
&lt;p&gt;&amp;hellip;が, 自分の環境だと&lt;code&gt;screen&lt;/code&gt;を実行しても&lt;code&gt;Cannot exec '/Users/uzimihsr/Library/Containers/com.docker.docker/Data/vms/0/tty': No such file or directory&lt;/code&gt;と表示されて落ちてしまった.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# どうして...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ screen ~/Library/Containers/com.docker.docker/Data/vms/0/tty
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;screen is terminating&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# そもそもttyコマンドが見当たらない&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls ~/Library/Containers/com.docker.docker/Data/vms/0/tty
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ls: /Users/uzimihsr/Library/Containers/com.docker.docker/Data/vms/0/tty: No such file or directory&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;なんかIssueに似た症状のコメント&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;も上がってるので, 自分だけじゃないはず&amp;hellip;🤔&lt;/p&gt;
&lt;p&gt;回避方法もよくわかんなかったので&lt;code&gt;screen&lt;/code&gt;を使う方法は諦めて,&lt;br&gt;
特権コンテナ&lt;sup id="fnref:4"&gt;&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref"&gt;4&lt;/a&gt;&lt;/sup&gt;を使う方法を試してみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 特権コンテナを使ってホストOS(VM)に入る&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker run -it --rm --privileged --pid&lt;span class="o"&gt;=&lt;/span&gt;host justincormack/nsenter1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/ &lt;span class="c1"&gt;# hostname&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker-desktop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/ &lt;span class="c1"&gt;# uname -a&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Linux docker-desktop 5.4.39-linuxkit &lt;span class="c1"&gt;#1 SMP Fri May 8 23:03:06 UTC 2020 x86_64 Linux&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;VM&lt;/code&gt;に入れたっぽい&amp;hellip;!&lt;/p&gt;
&lt;p&gt;目的のコンテナログも表示できる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;## 以下すべて特権コンテナ(ホストOS)内で実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# コンテナのログファイルを探す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls /var/lib/docker/containers/f9a220a391654fd66c8094a2965da6e1255ffb97c6db047d0aef1985d2e49659
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;checkpoints hosts
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;config.v2.json mounts
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;f9a220a391654fd66c8094a2965da6e1255ffb97c6db047d0aef1985d2e49659-json.log resolv.conf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hostconfig.json resolv.conf.hash
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hostname
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ログファイルの表示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat /var/lib/docker/containers/f9a220a391654fd66c8094a2965da6e1255ffb97c6db047d0aef1985d2e49659/f9a220a391654fd66c8094a2965da6e1255ffb97c6db047d0aef1985d2e49659-json.log
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;stream&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;stdout&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;2020-12-15T12:25:05.3727159Z&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;Hello from Docker!\n&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;stream&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;stdout&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;2020-12-15T12:25:05.3727757Z&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;This message shows that your installation appears to be working correctly.\n&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;stream&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;stdout&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;2020-12-15T12:25:05.372871Z&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;stream&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;stdout&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;2020-12-15T12:25:05.3728948Z&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;To generate this message, Docker took the following steps:\n&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;stream&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;stdout&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;2020-12-15T12:25:05.3729341Z&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34; 1. The Docker client contacted the Docker daemon.\n&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;stream&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;stdout&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;2020-12-15T12:25:05.3729571Z&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34; 2. The Docker daemon pulled the \&amp;#34;hello-world\&amp;#34; image from the Docker Hub.\n&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;stream&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;stdout&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;2020-12-15T12:25:05.3729785Z&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34; (amd64)\n&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;stream&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;stdout&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;2020-12-15T12:25:05.372997Z&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34; 3. The Docker daemon created a new container from that image which runs the\n&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;stream&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;stdout&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;2020-12-15T12:25:05.3730192Z&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34; executable that produces the output you are currently reading.\n&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;stream&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;stdout&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;2020-12-15T12:25:05.3731413Z&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34; 4. The Docker daemon streamed that output to the Docker client, which sent it\n&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;stream&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;stdout&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;2020-12-15T12:25:05.3731663Z&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34; to your terminal.\n&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;stream&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;stdout&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;2020-12-15T12:25:05.3732665Z&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;stream&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;stdout&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;2020-12-15T12:25:05.3732845Z&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;To try something more ambitious, you can run an Ubuntu container with:\n&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;stream&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;stdout&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;2020-12-15T12:25:05.3733071Z&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34; &lt;/span&gt;$&lt;span class="s2"&gt; docker run -it ubuntu bash\n&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;stream&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;stdout&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;2020-12-15T12:25:05.3733248Z&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;stream&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;stdout&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;2020-12-15T12:25:05.373345Z&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;Share images, automate workflows, and more with a free Docker ID:\n&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;stream&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;stdout&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;2020-12-15T12:25:05.3733674Z&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34; https://hub.docker.com/\n&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;stream&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;stdout&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;2020-12-15T12:25:05.3733901Z&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;stream&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;stdout&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;2020-12-15T12:25:05.3734126Z&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;For more examples and ideas, visit:\n&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;stream&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;stdout&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;2020-12-15T12:25:05.3734351Z&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34; https://docs.docker.com/get-started/\n&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;stream&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;stdout&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;2020-12-15T12:25:05.3734587Z&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;stream&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;stdout&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;2020-12-15T12:25:05.3734814Z&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# コンテナから出る&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ exit&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;Docker Desktop for Mac&lt;/code&gt;で動かした&lt;code&gt;Docker&lt;/code&gt;コンテナの標準出力の内容がログファイルとして閲覧できた.&lt;/p&gt;
&lt;p&gt;やったぜ.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Docker Desktop for Mac&lt;/code&gt;で&lt;code&gt;Docker&lt;/code&gt;を動かしているVMに入り, コンテナのログファイルを閲覧することができた.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Docker&lt;/code&gt;がそもそも&lt;code&gt;MacOS&lt;/code&gt;で直接動作していないことを理解できてなかったので, 勉強になった&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;HyperKit&lt;/code&gt;じゃなくて&lt;code&gt;VirtualBox&lt;/code&gt;で&lt;code&gt;macOS&lt;/code&gt;上にVMを立てて&lt;code&gt;Docker&lt;/code&gt;を動かす方法もあるみたいなので, 余裕があれば試してみたい.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="おもちゃが棚の下にはいっちゃったねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-12-15-docker-desktop-for-mac-hyperkit-vm/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-12-15-docker-desktop-for-mac-hyperkit-vm/sotochan_hu_c074bac322cbb8e1.jpg 800w, https://blog.uzimihsr.com/post/2020-12-15-docker-desktop-for-mac-hyperkit-vm/sotochan_hu_7cd8be88fbdec444.jpg 1600w, https://blog.uzimihsr.com/post/2020-12-15-docker-desktop-for-mac-hyperkit-vm/sotochan_hu_e7445f3b2220e8ee.jpg 2400w, https://blog.uzimihsr.com/post/2020-12-15-docker-desktop-for-mac-hyperkit-vm/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/docker-for-mac/install/#what-to-know-before-you-install" target="_blank" rel="noopener"
 &gt;Install Docker Desktop on Mac&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;a class="link" href="https://gist.github.com/BretFisher/5e1a0c7bcca4c735e716abf62afad389#option-1-use-screen-not-as-easy-as-nsenter" target="_blank" rel="noopener"
 &gt;BretFisher/docker-for-mac.md&lt;/a&gt;&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/docker/for-mac/issues/4822#issuecomment-709479906" target="_blank" rel="noopener"
 &gt;docker can&amp;rsquo;t access to volume with screen&lt;/a&gt;&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:4"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/justincormack/nsenter1" target="_blank" rel="noopener"
 &gt;justincormack/nsenter1&lt;/a&gt;&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>kind(Kubernetes IN Docker)を試した</title><link>https://blog.uzimihsr.com/post/2020-12-14-kind-kubernetes-in-docker/</link><pubDate>Mon, 14 Dec 2020 22:13:17 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-12-14-kind-kubernetes-in-docker/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-12-14-kind-kubernetes-in-docker/sotochan.jpg" alt="Featured image of post kind(Kubernetes IN Docker)を試した" /&gt;&lt;h2 id="かんたんすぎる"&gt;かんたんすぎる
&lt;/h2&gt;&lt;p&gt;Kubernetesの動作確認環境として, 簡単にクラスタを用意できるkindを使ってみた.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;kind&lt;/code&gt;をMacにインストールした&lt;/li&gt;
&lt;li&gt;&lt;code&gt;kind&lt;/code&gt;で&lt;code&gt;Kubernetes&lt;/code&gt;クラスタを作成, 削除した&lt;/li&gt;
&lt;li&gt;&lt;code&gt;kind&lt;/code&gt;で作ったクラスタに&lt;code&gt;Ingress Controller&lt;/code&gt;をデプロイした&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Mojave 10.14&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/editions/community/docker-ce-desktop-mac" target="_blank" rel="noopener"
 &gt;Docker Desktop for Mac&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Version 2.5.0.0&lt;/li&gt;
&lt;li&gt;Docker version 19.03.13&lt;/li&gt;
&lt;li&gt;インストール済み&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/anyenv/anyenv" target="_blank" rel="noopener"
 &gt;anyenv&lt;/a&gt; 1.1.1
&lt;ul&gt;
&lt;li&gt;インストール済み&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/syndbg/goenv" target="_blank" rel="noopener"
 &gt;goenv&lt;/a&gt; 2.0.0beta11
&lt;ul&gt;
&lt;li&gt;インストール済み&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/golang/go" target="_blank" rel="noopener"
 &gt;go&lt;/a&gt; version go1.15.5 darwin/amd64
&lt;ul&gt;
&lt;li&gt;今回入れる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/kubernetes-sigs/kind/" target="_blank" rel="noopener"
 &gt;kind&lt;/a&gt; v0.9.0 go1.15.5 darwin/amd64
&lt;ul&gt;
&lt;li&gt;今回入れる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/kubernetes/kubectl" target="_blank" rel="noopener"
 &gt;kubectl&lt;/a&gt; Client Version: v1.19.3
&lt;ul&gt;
&lt;li&gt;インストール済み&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#kind%e3%81%a3%e3%81%a6%e3%81%aa%e3%81%ab" &gt;kindってなに&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#go%e3%81%ae%e6%9b%b4%e6%96%b0" &gt;Goの更新&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#kind%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" &gt;kindのインストール&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%af%e3%83%a9%e3%82%b9%e3%82%bf%e3%81%ae%e8%b5%b7%e5%8b%95" &gt;クラスタの起動&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#ingress%e3%81%ae%e8%a8%ad%e5%ae%9a" &gt;Ingressの設定&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%af%e3%83%a9%e3%82%b9%e3%82%bf%e3%81%ae%e5%89%8a%e9%99%a4" &gt;クラスタの削除&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="kindってなに"&gt;kindってなに
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;kind&lt;/code&gt;&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;は&lt;code&gt;Docker&lt;/code&gt;コンテナを&lt;code&gt;Node&lt;/code&gt;として動かすことでローカル環境で&lt;code&gt;Kubernetes&lt;/code&gt;クラスタを動作させるツール.&lt;/p&gt;
&lt;p&gt;今までローカルでの動作確認には&lt;code&gt;Docker Desktop&lt;/code&gt;で作れる&lt;code&gt;Kuberentes&lt;/code&gt;クラスタを使ってたんだけど,&lt;br&gt;
この前&lt;code&gt;Kubernetes&lt;/code&gt; &lt;strong&gt;v1.20&lt;/strong&gt;以降は&lt;code&gt;Docker&lt;/code&gt;が&lt;code&gt;Node&lt;/code&gt;のコンテナランタイムとして非推奨&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;になるとのお知らせが出ていた.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Docker Desktop&lt;/code&gt;の&lt;code&gt;Kubernetes&lt;/code&gt;クラスタは&lt;code&gt;Docker&lt;/code&gt;をコンテナランタイムとして使っているので, そのうち使えなくなるかも&amp;hellip;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Docker Desktopで立てたKubernetesクラスタのコンテナランタイムはDocker&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get nodes -o wide --context&lt;span class="o"&gt;=&lt;/span&gt;docker-desktop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker-desktop Ready master 33d v1.19.3 192.168.65.3 &amp;lt;none&amp;gt; Docker Desktop 5.4.39-linuxkit docker://19.3.13&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;ということで, これを機にローカルでの動作確認用&lt;code&gt;Kubernetes&lt;/code&gt;クラスタは&lt;code&gt;kind&lt;/code&gt;で作ることにした.&lt;br&gt;
(&lt;code&gt;kind&lt;/code&gt;では&lt;code&gt;Node&lt;/code&gt;で&lt;code&gt;containerd&lt;/code&gt;&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;をランタイムとして使っているので問題ないらしい)&lt;/p&gt;
&lt;h3 id="goの更新"&gt;Goの更新
&lt;/h3&gt;&lt;p&gt;(&lt;code&gt;Go&lt;/code&gt;の最新版がインストールされている環境なら飛ばしてOK)&lt;/p&gt;
&lt;p&gt;&lt;code&gt;kind&lt;/code&gt;のクイックスタート&lt;sup id="fnref:4"&gt;&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref"&gt;4&lt;/a&gt;&lt;/sup&gt;によると&lt;code&gt;Go&lt;/code&gt;の最新版を使ってね!とのことなのでせっかくだし新しい&lt;code&gt;Go&lt;/code&gt;(1.15)をインストールする.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;go version go1.14.6 darwin/amd64
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# goenvを更新&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ anyenv install goenv
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;anyenv: /Users/uzimihsr/.anyenv/envs/goenv already exists
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Reinstallation keeps versions directories
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;continue&lt;/span&gt; with installation? &lt;span class="o"&gt;(&lt;/span&gt;y/N&lt;span class="o"&gt;)&lt;/span&gt; y
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Install goenv succeeded!
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Please reload your profile &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nv"&gt;$SHELL&lt;/span&gt; -l&lt;span class="o"&gt;)&lt;/span&gt; or open a new session.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# シェルを再起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nv"&gt;$SHELL&lt;/span&gt; -l
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# インストール可能なバージョンの一覧を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ goenv install -l &lt;span class="p"&gt;|&lt;/span&gt; grep 1.15
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 1.15.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 1.15beta1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 1.15rc2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 1.15.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 1.15.2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 1.15.3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 1.15.4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 1.15.5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Go 1.15.5をインストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ goenv install 1.15.5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Downloading go1.15.5.darwin-amd64.tar.gz...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-&amp;gt; https://golang.org/dl/go1.15.5.darwin-amd64.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Installing Go Darwin 64bit 1.15.5...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Installed Go Darwin 64bit 1.15.5 to /Users/uzimihsr/.anyenv/envs/goenv/versions/1.15.5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# このMacで常にGo 1.15.5を使うようにする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ goenv global 1.15.5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ goenv rehash
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ goenv versions
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 1.12.9
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 1.13.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 1.14.6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 1.15.5 &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; by /Users/uzimihsr/.anyenv/envs/goenv/version&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;go version go1.15.5 darwin/amd64
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$GOPATH&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/Users/uzimihsr/go/1.15.5&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;OK.&lt;/p&gt;
&lt;h3 id="kindのインストール"&gt;kindのインストール
&lt;/h3&gt;&lt;p&gt;次に&lt;code&gt;kind&lt;/code&gt;をインストールする.&lt;/p&gt;
&lt;p&gt;といっても&lt;code&gt;go get&lt;/code&gt;で入るのでインストール自体は1行で終わっちゃう.&lt;/p&gt;
&lt;p&gt;クッソかんたん.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# kindのインストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nv"&gt;GO111MODULE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;on&amp;#34;&lt;/span&gt; go get sigs.k8s.io/kind@v0.9.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# $GOPATH/bin/kindに入っている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ which kind
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/Users/uzimihsr/go/1.15.5/bin/kind
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 動作確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kind version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kind v0.9.0 go1.15.5 darwin/amd64&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="クラスタの起動"&gt;クラスタの起動
&lt;/h3&gt;&lt;p&gt;いよいよ&lt;code&gt;Kubernetes&lt;/code&gt;クラスタを起動する.&lt;/p&gt;
&lt;p&gt;&amp;hellip;これもコマンド1発でできる.&lt;/p&gt;
&lt;p&gt;めっちゃかんたん.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Kubernetesクラスタ(kind-kind)の作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kind create cluster
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Creating cluster &lt;span class="s2"&gt;&amp;#34;kind&amp;#34;&lt;/span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✓ Ensuring node image &lt;span class="o"&gt;(&lt;/span&gt;kindest/node:v1.19.1&lt;span class="o"&gt;)&lt;/span&gt; 🖼
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✓ Preparing nodes 📦
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✓ Writing configuration 📜
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✓ Starting control-plane 🕹️
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✓ Installing CNI 🔌
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✓ Installing StorageClass 💾
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Set kubectl context to &lt;span class="s2"&gt;&amp;#34;kind-kind&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;You can now use your cluster with:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl cluster-info --context kind-kind
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Not sure what to &lt;span class="k"&gt;do&lt;/span&gt; next? 😅 Check out https://kind.sigs.k8s.io/docs/user/quick-start/&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;kubectl&lt;/code&gt;の&lt;code&gt;context&lt;/code&gt;が勝手に切り替わるので, すぐにクラスタの操作もできる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# kubectlのcontextが自動で変更されている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl config view --minify
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apiVersion: v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;clusters:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- cluster:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; certificate-authority-data: DATA+OMITTED
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; server: https://127.0.0.1:63917
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: kind-kind
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;contexts:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- context:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cluster: kind-kind
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; user: kind-kind
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: kind-kind
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;current-context: kind-kind
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kind: Config
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;preferences: &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;users:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- name: kind-kind
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; user:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; client-certificate-data: REDACTED
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; client-key-data: REDACTED
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# うまく切り替わっていない場合もkindコマンドから有効なkubeconfigを取得可能&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kind get kubeconfig --name kind
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apiVersion: v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;clusters:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- cluster:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; certificate-authority-data: ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; server: https://127.0.0.1:63917
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: kind-kind
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;contexts:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- context:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cluster: kind-kind
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; user: kind-kind
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: kind-kind
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;current-context: kind-kind
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kind: Config
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;preferences: &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;users:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- name: kind-kind
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; user:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; client-certificate-data: ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; client-key-data: ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 動作確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl cluster-info --context kind-kind
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Kubernetes master is running at https://127.0.0.1:63917
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;KubeDNS is running at https://127.0.0.1:63917/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;To further debug and diagnose cluster problems, use &lt;span class="s1"&gt;&amp;#39;kubectl cluster-info dump&amp;#39;&lt;/span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;実際に&lt;code&gt;Node&lt;/code&gt;用のコンテナが起動していることも確認できる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Nodeが1つ作成されている(コンテナランタイムがcontainerd!)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get nodes -o wide
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kind-control-plane Ready master 19m v1.19.1 172.19.0.2 &amp;lt;none&amp;gt; Ubuntu Groovy Gorilla &lt;span class="o"&gt;(&lt;/span&gt;development branch&lt;span class="o"&gt;)&lt;/span&gt; 5.4.39-linuxkit containerd://1.4.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Nodeとして動いているコンテナ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;24117f8d397f kindest/node:v1.19.1 &lt;span class="s2"&gt;&amp;#34;/usr/local/bin/entr…&amp;#34;&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt; minutes ago Up &lt;span class="m"&gt;20&lt;/span&gt; minutes 127.0.0.1:63917-&amp;gt;6443/tcp kind-control-plane&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;ちゃんと&lt;code&gt;Pod&lt;/code&gt;も動く. すごい.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podも作れる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl run nginx --image&lt;span class="o"&gt;=&lt;/span&gt;nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -o wide
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nginx 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 37s 10.244.0.5 kind-control-plane &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podの動作確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl run busybox --image&lt;span class="o"&gt;=&lt;/span&gt;busybox --restart&lt;span class="o"&gt;=&lt;/span&gt;Never --rm -it -- wget -O- 10.244.0.5:80
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Connecting to 10.244.0.5:80 &lt;span class="o"&gt;(&lt;/span&gt;10.244.0.5:80&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;writing to stdout
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;!DOCTYPE html&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;html&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;head&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;title&amp;gt;Welcome to nginx!&amp;lt;/title&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;style&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; body &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; width: 35em&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; margin: &lt;span class="m"&gt;0&lt;/span&gt; auto&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; font-family: Tahoma, Verdana, Arial, sans-serif&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;/style&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;/head&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;body&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;h1&amp;gt;Welcome to nginx!&amp;lt;/h1&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;p&amp;gt;If you see this page, the nginx web server is successfully installed and
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;working. Further configuration is required.&amp;lt;/p&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;p&amp;gt;For online documentation and support please refer to
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;a &lt;span class="nv"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;http://nginx.org/&amp;#34;&lt;/span&gt;&amp;gt;nginx.org&amp;lt;/a&amp;gt;.&amp;lt;br/&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Commercial support is available at
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;a &lt;span class="nv"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;http://nginx.com/&amp;#34;&lt;/span&gt;&amp;gt;nginx.com&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;Thank you &lt;span class="k"&gt;for&lt;/span&gt; using nginx.&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;/body&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;/html&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- 100% &lt;span class="p"&gt;|&lt;/span&gt;********************************&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;612&lt;/span&gt; 0:00:00 ETA
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;written to stdout
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod &lt;span class="s2"&gt;&amp;#34;busybox&amp;#34;&lt;/span&gt; deleted&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="ingressの設定"&gt;Ingressの設定
&lt;/h3&gt;&lt;p&gt;簡単な&lt;code&gt;Pod&lt;/code&gt;や&lt;code&gt;Job&lt;/code&gt;の動作確認だけならこれでも良いんだけど,&lt;br&gt;
クラスタ外からの動作確認がしたい場合は追加で&lt;code&gt;Ingress&lt;/code&gt;の設定が必要なので試してみる.&lt;/p&gt;
&lt;p&gt;まずは新たなクラスタを設定ファイル&lt;sup id="fnref:5"&gt;&lt;a href="#fn:5" class="footnote-ref" role="doc-noteref"&gt;5&lt;/a&gt;&lt;/sup&gt;を使って作成する.&lt;br&gt;
&lt;code&gt;extraPortMappings&lt;/code&gt;と&lt;code&gt;node-labels&lt;/code&gt;が設定されていることが重要らしい.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# kindのクラスタ設定ファイルの作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim config.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 新規クラスタ(kind-ingress-enabled)の起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kind create cluster --name ingress-enabled --config config.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Creating cluster &lt;span class="s2"&gt;&amp;#34;ingress-enabled&amp;#34;&lt;/span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✓ Ensuring node image &lt;span class="o"&gt;(&lt;/span&gt;kindest/node:v1.19.1&lt;span class="o"&gt;)&lt;/span&gt; 🖼
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✓ Preparing nodes 📦
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✓ Writing configuration 📜
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✓ Starting control-plane 🕹️
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✓ Installing CNI 🔌
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✓ Installing StorageClass 💾
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Set kubectl context to &lt;span class="s2"&gt;&amp;#34;kind-ingress-enabled&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;You can now use your cluster with:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl cluster-info --context kind-ingress-enabled
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Thanks &lt;span class="k"&gt;for&lt;/span&gt; using kind! 😊&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
&lt;script src="https://gist.github.com/uzimihsr/6db4cafe662e36b0d1c58a0ce280f825.js"&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;作ったばかりのクラスタ(&lt;strong&gt;kind-ingress-enabled&lt;/strong&gt;)に&lt;code&gt;Ingress Controller&lt;/code&gt;をデプロイする&lt;sup id="fnref:6"&gt;&lt;a href="#fn:6" class="footnote-ref" role="doc-noteref"&gt;6&lt;/a&gt;&lt;/sup&gt;.&lt;br&gt;
今回は&lt;code&gt;NGINX Ingress Controller&lt;/code&gt;&lt;sup id="fnref:7"&gt;&lt;a href="#fn:7" class="footnote-ref" role="doc-noteref"&gt;7&lt;/a&gt;&lt;/sup&gt;を使用する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# NGINX Ingress Controllerのデプロイ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply --context kind-ingress-enabled -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/kind/deploy.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;namespace/ingress-nginx created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;serviceaccount/ingress-nginx created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;configmap/ingress-nginx-controller created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;clusterrole.rbac.authorization.k8s.io/ingress-nginx created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;role.rbac.authorization.k8s.io/ingress-nginx created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rolebinding.rbac.authorization.k8s.io/ingress-nginx created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/ingress-nginx-controller-admission created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/ingress-nginx-controller created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps/ingress-nginx-controller created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;serviceaccount/ingress-nginx-admission created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;role.rbac.authorization.k8s.io/ingress-nginx-admission created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;job.batch/ingress-nginx-admission-create created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;job.batch/ingress-nginx-admission-patch created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 起動確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;wait&lt;/span&gt; --context kind-ingress-enabled --namespace ingress-nginx &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --for&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;condition&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ready pod &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --selector&lt;span class="o"&gt;=&lt;/span&gt;app.kubernetes.io/component&lt;span class="o"&gt;=&lt;/span&gt;controller &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --timeout&lt;span class="o"&gt;=&lt;/span&gt;90s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/ingress-nginx-controller-6df69bd4f7-57bkk condition met&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;これでこのクラスタで&lt;code&gt;Ingress&lt;/code&gt;を使う準備ができた.&lt;/p&gt;
&lt;p&gt;最後にサンプルアプリ&lt;sup id="fnref:8"&gt;&lt;a href="#fn:8" class="footnote-ref" role="doc-noteref"&gt;8&lt;/a&gt;&lt;/sup&gt;を動かして, &lt;code&gt;Ingress&lt;/code&gt;の動作を確認する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# サンプルアプリ(Pod, Service, Ingress)のデプロイ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f https://kind.sigs.k8s.io/examples/ingress/usage.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/foo-app created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/foo-service created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/bar-app created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/bar-service created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Warning: networking.k8s.io/v1beta1 Ingress is deprecated in v1.19+, unavailable in v1.22+&lt;span class="p"&gt;;&lt;/span&gt; use networking.k8s.io/v1 Ingress
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ingress.networking.k8s.io/example-ingress created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# リクエストに対してそれぞれfoo, barを返すPodとそれに対応したService&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get all
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/bar-app 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 33s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/foo-app 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 33s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/bar-service ClusterIP 10.96.251.3 &amp;lt;none&amp;gt; 5678/TCP 33s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/foo-service ClusterIP 10.96.170.161 &amp;lt;none&amp;gt; 5678/TCP 33s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/kubernetes ClusterIP 10.96.0.1 &amp;lt;none&amp;gt; 443/TCP 16m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# /foo, /barへのトラフィックをそれぞれのServiceに振り分けるIngress&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get ingress
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+&lt;span class="p"&gt;;&lt;/span&gt; use networking.k8s.io/v1 Ingress
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME CLASS HOSTS ADDRESS PORTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;example-ingress &amp;lt;none&amp;gt; * localhost &lt;span class="m"&gt;80&lt;/span&gt; 16m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl describe ingress example-ingress
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+&lt;span class="p"&gt;;&lt;/span&gt; use networking.k8s.io/v1 Ingress
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: example-ingress
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Address: localhost
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Default backend: default-http-backend:80 &lt;span class="o"&gt;(&lt;/span&gt;&amp;lt;error: endpoints &lt;span class="s2"&gt;&amp;#34;default-http-backend&amp;#34;&lt;/span&gt; not found&amp;gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Rules:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Host Path Backends
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---- ---- --------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; *
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; /foo foo-service:5678 10.244.0.10:5678&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; /bar bar-service:5678 10.244.0.9:5678&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Reason Age From Message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---- ------ ---- ---- -------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Sync 17m &lt;span class="o"&gt;(&lt;/span&gt;x2 over 17m&lt;span class="o"&gt;)&lt;/span&gt; nginx-ingress-controller Scheduled &lt;span class="k"&gt;for&lt;/span&gt; sync
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# クラスタ外から叩いて動作確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl localhost/foo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;foo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl localhost/bar
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bar&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;やったぜ.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;kind&lt;/code&gt;で立てたクラスタでも&lt;code&gt;Ingress&lt;/code&gt;を使ってクラスタ外からアクセスすることができた.&lt;/p&gt;
&lt;h3 id="クラスタの削除"&gt;クラスタの削除
&lt;/h3&gt;&lt;p&gt;最後にクラスタをお掃除する.&lt;/p&gt;
&lt;p&gt;これもコマンド1発なのでめちゃくちゃ簡単.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 削除前の状態&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kind get clusters
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ingress-enabled
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kind
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Node用のコンテナが2クラスタぶん存在する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;d5c5aa156df9 kindest/node:v1.19.1 &lt;span class="s2"&gt;&amp;#34;/usr/local/bin/entr…&amp;#34;&lt;/span&gt; &lt;span class="m"&gt;23&lt;/span&gt; hours ago Up &lt;span class="m"&gt;23&lt;/span&gt; hours 0.0.0.0:80-&amp;gt;80/tcp, 0.0.0.0:443-&amp;gt;443/tcp, 127.0.0.1:57487-&amp;gt;6443/tcp ingress-enabled-control-plane
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;24117f8d397f kindest/node:v1.19.1 &lt;span class="s2"&gt;&amp;#34;/usr/local/bin/entr…&amp;#34;&lt;/span&gt; &lt;span class="m"&gt;24&lt;/span&gt; hours ago Up &lt;span class="m"&gt;24&lt;/span&gt; hours 127.0.0.1:63917-&amp;gt;6443/tcp kind-control-plane
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# クラスタの削除&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kind delete cluster --name kind
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Deleting cluster &lt;span class="s2"&gt;&amp;#34;kind&amp;#34;&lt;/span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 一括削除も可能&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kind delete clusters --all
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Deleted clusters: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;ingress-enabled&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Nodeのコンテナがすべて消えている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container ls -a
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# kubeconfigの設定も勝手に消えている(残っているのは別途作成したDocker DesktopとMinikubeの設定のみ)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl config view
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apiVersion: v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;clusters:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- cluster:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; certificate-authority-data: DATA+OMITTED
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; server: https://kubernetes.docker.internal:6443
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: docker-desktop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- cluster:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; certificate-authority: /Users/uzimihsr/.minikube/ca.crt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; server: https://192.168.99.110:8443
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;contexts:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- context:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cluster: docker-desktop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; user: docker-desktop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: docker-desktop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- context:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cluster: minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; user: minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;current-context: &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kind: Config
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;preferences: &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;users:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- name: docker-desktop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; user:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; client-certificate-data: REDACTED
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; client-key-data: REDACTED
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- name: minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; user:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; client-certificate: /Users/uzimihsr/.minikube/client.crt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; client-key: /Users/uzimihsr/.minikube/client.key&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&amp;hellip;こんなに簡単でいいのか?&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;kind&lt;/code&gt;を使った&lt;code&gt;Kubernetes&lt;/code&gt;クラスタの作成, &lt;code&gt;Ingress Controller&lt;/code&gt;のデプロイ, クラスタの削除を一通り試してみた.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Ingress&lt;/code&gt;対応だけちょっと面倒だけどそれもほぼコピペでできるし,&lt;br&gt;
基本はコマンド1行でクラスタが簡単に作れるのがすごい. 便利すぎる.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="しもべの仕事用のイスに座るのがすきなねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-12-14-kind-kubernetes-in-docker/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-12-14-kind-kubernetes-in-docker/sotochan_hu_c45ba69a03e9de6.jpg 800w, https://blog.uzimihsr.com/post/2020-12-14-kind-kubernetes-in-docker/sotochan_hu_6f55de907eb57da1.jpg 1600w, https://blog.uzimihsr.com/post/2020-12-14-kind-kubernetes-in-docker/sotochan_hu_565eea4067ee2c2f.jpg 2400w, https://blog.uzimihsr.com/post/2020-12-14-kind-kubernetes-in-docker/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a class="link" href="https://kind.sigs.k8s.io/" target="_blank" rel="noopener"
 &gt;https://kind.sigs.k8s.io/&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;a class="link" href="https://kubernetes.io/blog/2020/12/02/dont-panic-kubernetes-and-docker/" target="_blank" rel="noopener"
 &gt;Don&amp;rsquo;t Panic: Kubernetes and Docker&lt;/a&gt;&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;&lt;a class="link" href="https://containerd.io/" target="_blank" rel="noopener"
 &gt;https://containerd.io/&lt;/a&gt;&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:4"&gt;
&lt;p&gt;&lt;a class="link" href="https://kind.sigs.k8s.io/docs/user/quick-start" target="_blank" rel="noopener"
 &gt;https://kind.sigs.k8s.io/docs/user/quick-start&lt;/a&gt;&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:5"&gt;
&lt;p&gt;&lt;a class="link" href="https://kind.sigs.k8s.io/docs/user/ingress/#create-cluster" target="_blank" rel="noopener"
 &gt;https://kind.sigs.k8s.io/docs/user/ingress/#create-cluster&lt;/a&gt;&amp;#160;&lt;a href="#fnref:5" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:6"&gt;
&lt;p&gt;&lt;a class="link" href="https://kind.sigs.k8s.io/docs/user/ingress/#ingress-nginx" target="_blank" rel="noopener"
 &gt;https://kind.sigs.k8s.io/docs/user/ingress/#ingress-nginx&lt;/a&gt;&amp;#160;&lt;a href="#fnref:6" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:7"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/kubernetes/ingress-nginx/" target="_blank" rel="noopener"
 &gt;https://github.com/kubernetes/ingress-nginx/&lt;/a&gt;&amp;#160;&lt;a href="#fnref:7" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:8"&gt;
&lt;p&gt;&lt;a class="link" href="https://kind.sigs.k8s.io/docs/user/ingress/#using-ingress" target="_blank" rel="noopener"
 &gt;https://kind.sigs.k8s.io/docs/user/ingress/#using-ingress&lt;/a&gt;&amp;#160;&lt;a href="#fnref:8" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Goで無限ループのテストの書き方がわかんなかった</title><link>https://blog.uzimihsr.com/post/2020-12-05-test-infinite-loop-golang/</link><pubDate>Sat, 05 Dec 2020 13:40:34 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-12-05-test-infinite-loop-golang/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-12-05-test-infinite-loop-golang/sotochan.jpg" alt="Featured image of post Goで無限ループのテストの書き方がわかんなかった" /&gt;&lt;h2 id="鬼滅のテスト-無限ループ編"&gt;鬼滅のテスト 無限ループ編
&lt;/h2&gt;&lt;p&gt;わかんなかったので自分なりにやってみたメモ&lt;br&gt;
サブタイトルはおふざけ&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;ループ1回分の処理を抜き出して, それをテストするのが良さそう.&lt;br&gt;
ループ1回分のモックが作れるなら, 無限ループの部分を呼び出して任意の回数でループを止めることもできる.&lt;/p&gt;
&lt;p&gt;(無限ループを含むコード例)&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/e477cc421bde52cf08d73d354291a160.js"&gt;&lt;/script&gt;
&lt;p&gt;(テストコード例)&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/e53d4b989ed9196547353248c673ff22.js"&gt;&lt;/script&gt;
&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Mojave 10.14&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/golang/go" target="_blank" rel="noopener"
 &gt;go&lt;/a&gt; version go1.14.6 darwin/amd64&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やりかた"&gt;やりかた
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Go&lt;/code&gt;でこんな感じの無限ループ処理があるときに,&lt;br&gt;
どうやってテストを書いたらいいかわかんなかった.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/f6c363a82a9b09c1f6391763385b3878.js"&gt;&lt;/script&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 処理としてはhogehoge.txtの内容を1秒ごとに読み込んで出力するだけ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; fugafuga &amp;gt; hogehoge.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go run main.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;fugafuga
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;fugafuga
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;fugafuga
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;fugafuga
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;fugafuga
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;^Csignal: interrupt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 無限ループなので強制終了する&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;テキトーに調べたけど&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;, 提案されているのは&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ループの回数を指定できるような仕組みを仕込んでおいてテストのときだけ回数を有限にする&lt;/li&gt;
&lt;li&gt;ループ1回分の処理だけをテストするようにする&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;のどっちかという感じだった.&lt;/p&gt;
&lt;p&gt;自分の場合はDI(Dependency Injection)以外でテストのためだけに変な引数を追加したりしたくないので,
ループ1回分だけを取り出してテストするほうが良いかな, と思った.&lt;/p&gt;
&lt;p&gt;まずは&lt;code&gt;main.go&lt;/code&gt;を修正して, ループ1回分の処理を別のメソッド(&lt;strong&gt;Loop.Run&lt;/strong&gt;)に分ける.&lt;br&gt;
(実行される処理の内容は変わらない)&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/e477cc421bde52cf08d73d354291a160.js"&gt;&lt;/script&gt;
&lt;p&gt;次に&lt;code&gt;gomock&lt;/code&gt;&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;でループ1回分の&lt;code&gt;interface&lt;/code&gt;(&lt;strong&gt;Loop&lt;/strong&gt;)のモックを作る.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# go.modの作成($GOPATH配下で作業している場合は不要)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go mod init github.com/uzimihsr/infinite-loop-test
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;go: creating new go.mod: module github.com/uzimihsr/infinite-loop-test
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# mockの生成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go get github.com/golang/mock/mockgen@v1.4.4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mockgen -source&lt;span class="o"&gt;=&lt;/span&gt;./main.go -destination&lt;span class="o"&gt;=&lt;/span&gt;mock_main.go -package&lt;span class="o"&gt;=&lt;/span&gt;main Loop&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;details&gt;&lt;summary&gt;mock_main.go(生成されたモック)&lt;/summary&gt;&lt;div&gt;
&lt;script src="https://gist.github.com/uzimihsr/cc8f477cadcc5a2014e6fddac6347cd7.js"&gt;&lt;/script&gt;
&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;(後で気づいたけど, main関数のテストはしないのでちゃんとパッケージを分ければよかった&amp;hellip;)&lt;/p&gt;
&lt;p&gt;ループ1回分(&lt;strong&gt;Loop.Run&lt;/strong&gt;)のテストと無限ループ(&lt;strong&gt;InfiniteLoop.Run&lt;/strong&gt;)のテストを作成する.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/e53d4b989ed9196547353248c673ff22.js"&gt;&lt;/script&gt;
&lt;p&gt;ループ1回分のテストでは実際に1回分の処理だけをテストしている.&lt;br&gt;
(今回は&lt;code&gt;loop.Run()&lt;/code&gt;内部で標準パッケージの&lt;code&gt;ioutil.ReadFile()&lt;/code&gt;を直接呼び出してしまっているけど, 可能であればここも依存している関数やメソッドのモックを使ったほうが良い気がする)&lt;/p&gt;
&lt;p&gt;無限ループのテストでは&lt;code&gt;mockgen&lt;/code&gt;で生成したループ1回分のモックを利用して,&lt;br&gt;
任意の回数を超えた時点でエラーを発生させてループが止まるようにしている.&lt;br&gt;
こうすることで, 結果的には無限ループの回数を指定してテストしているのと同じことができた.&lt;/p&gt;
&lt;p&gt;実際にテストを実行してみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 最終的な作業ディレクトリの状態&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ tree .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── go.mod
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── go.sum
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── hogehoge.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── main.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── main_test.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── mock_main.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── test-hogehoge.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# テスト実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; test-fugafuga &amp;gt; test-hogehoge.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go &lt;span class="nb"&gt;test&lt;/span&gt; -v -cover ./...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;===&lt;/span&gt; RUN &lt;span class="nv"&gt;TestLoop&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;===&lt;/span&gt; RUN TestLoop/正常にファイルが開けるケースのテスト
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;test-fugafuga
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;===&lt;/span&gt; RUN TestLoop/ファイルが開けず異常終了するケースのテスト
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;--- PASS: TestLoop &lt;span class="o"&gt;(&lt;/span&gt;0.00s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --- PASS: TestLoop/正常にファイルが開けるケースのテスト &lt;span class="o"&gt;(&lt;/span&gt;0.00s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --- PASS: TestLoop/ファイルが開けず異常終了するケースのテスト &lt;span class="o"&gt;(&lt;/span&gt;0.00s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;===&lt;/span&gt; RUN &lt;span class="nv"&gt;TestInfiniteLoop&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;===&lt;/span&gt; RUN TestInfiniteLoop/ループが1回正常に呼び出されることのテスト
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;===&lt;/span&gt; RUN TestInfiniteLoop/ループが任意の回数&lt;span class="o"&gt;(&lt;/span&gt;例えば10回&lt;span class="o"&gt;)&lt;/span&gt;正常に呼び出されることのテスト
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;--- PASS: TestInfiniteLoop &lt;span class="o"&gt;(&lt;/span&gt;11.03s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --- PASS: TestInfiniteLoop/ループが1回正常に呼び出されることのテスト &lt;span class="o"&gt;(&lt;/span&gt;1.01s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --- PASS: TestInfiniteLoop/ループが任意の回数&lt;span class="o"&gt;(&lt;/span&gt;例えば10回&lt;span class="o"&gt;)&lt;/span&gt;正常に呼び出されることのテスト &lt;span class="o"&gt;(&lt;/span&gt;10.02s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;PASS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;coverage: 63.4% of statements
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ok 	github.com/uzimihsr/infinite-loop-test	11.034s	coverage: 63.4% of statements&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;mock_main.go&lt;/code&gt;が&lt;code&gt;main&lt;/code&gt;パッケージに入ってたりmain関数のテストができていなかったりで,&lt;br&gt;
カバレッジは100%になっていないけど一応やりたかった内容は実行できた.&lt;/p&gt;
&lt;p&gt;テストの目的はカバレッジを100%にすることではないので, これでいいはず&amp;hellip;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;無限ループがあるコードを書いた経験があまりなかったので, けっこう詰まってしまった.&lt;/p&gt;
&lt;p&gt;自分なりにやってみたけど, 他にもっといい方法があるんだろうか&amp;hellip;&lt;br&gt;
もっと厳密にやりたいならosパッケージ&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;を呼び出してプロセスを扱ったりしてもいいんだろうけど, そこまでする必要があるかは謎🤔&lt;br&gt;
(個人的には&amp;quot;無限に繰り返されること&amp;quot;の確認にそこまでの価値があると思えなかった)&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="無限にだらだらするのが得意なねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-12-05-test-infinite-loop-golang/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-12-05-test-infinite-loop-golang/sotochan_hu_d4fee91c9598ef7.jpg 800w, https://blog.uzimihsr.com/post/2020-12-05-test-infinite-loop-golang/sotochan_hu_54e7bde331ad0eec.jpg 1600w, https://blog.uzimihsr.com/post/2020-12-05-test-infinite-loop-golang/sotochan_hu_490b3aec681de3ed.jpg 2400w, https://blog.uzimihsr.com/post/2020-12-05-test-infinite-loop-golang/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a class="link" href="https://stackoverflow.com/questions/35004276/how-to-test-code-that-loops-forever" target="_blank" rel="noopener"
 &gt;unit testing - How to test code that loops forever - Stack Overflow&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/golang/mock" target="_blank" rel="noopener"
 &gt;github.com/golang/mock&lt;/a&gt;&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;&lt;a class="link" href="https://golang.org/pkg/os/" target="_blank" rel="noopener"
 &gt;golang.org/pkg/os&lt;/a&gt;&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>11月のそとちゃんまとめ(2020)</title><link>https://blog.uzimihsr.com/post/2020-12-03-sotochan/</link><pubDate>Thu, 03 Dec 2020 12:09:40 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-12-03-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan07.jpg" alt="Featured image of post 11月のそとちゃんまとめ(2020)" /&gt;&lt;h2 id="もふもふ"&gt;もふもふ
&lt;/h2&gt;&lt;p&gt;ちょっと寒くなってきたけどそとちゃんは相変わらず元気だった.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%be%e3%82%8b%e3%81%84" &gt;まるい&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%8f%e3%83%9f%e6%af%9b%e5%87%a6%e7%90%86" &gt;ハミ毛処理&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%bd%e3%83%95%e3%82%a1" &gt;ソファ&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="まるい"&gt;まるい
&lt;/h3&gt;&lt;p&gt;11月もそとちゃんはころころしていた.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;なんだこれ &lt;a href="https://t.co/swNMCbukZs"&gt;pic.twitter.com/swNMCbukZs&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1326076203904638976?ref_src=twsrc%5Etfw"&gt;November 10, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;まるい &lt;a href="https://t.co/sVjWH7icHI"&gt;pic.twitter.com/sVjWH7icHI&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1326741513812897793?ref_src=twsrc%5Etfw"&gt;November 12, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;早朝から運動会して, お昼ごろには疲れてまるくなってお昼寝してるのが最近のパターン.&lt;/p&gt;
&lt;p&gt;14時くらいにいったん起きてごはんを食べるけど, その後はまたまるくなって夕方くらいまで寝てる.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;遊び疲れ果てた &lt;a href="https://t.co/bTvAfAoYor"&gt;pic.twitter.com/bTvAfAoYor&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1326892618672824320?ref_src=twsrc%5Etfw"&gt;November 12, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ねてる &lt;a href="https://t.co/QQz5Qbn34Z"&gt;pic.twitter.com/QQz5Qbn34Z&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1328908405440843776?ref_src=twsrc%5Etfw"&gt;November 18, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;寒いから丸まってるのかと思ってヒーターも買ったけど,&lt;br&gt;
エアコンと違って温風が直接当たるのがそんなに好きじゃないらしい.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ちゃんと離れてるのえらいねえ &lt;a href="https://t.co/1M0OmOhNjJ"&gt;pic.twitter.com/1M0OmOhNjJ&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1328626396244049924?ref_src=twsrc%5Etfw"&gt;November 17, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;横から見るとおまんじゅうみたいでかわいい.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;これなに？ &lt;a href="https://t.co/V6J0WGABj8"&gt;pic.twitter.com/V6J0WGABj8&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1329684024994848768?ref_src=twsrc%5Etfw"&gt;November 20, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;&lt;img alt="おまんじゅう" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan01.jpg" srcset="https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan01_hu_d6c1bc4d289fbb2d.jpg 800w, https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan01_hu_eae43adf991921eb.jpg 1600w, https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan01_hu_c2879bb254d4a6dc.jpg 2400w, https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan01.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;h3 id="ハミ毛処理"&gt;ハミ毛処理
&lt;/h3&gt;&lt;p&gt;ときどきフローリングですべってるから怪しいとは思ってたけど, 足のハミ毛が立派に伸びていた.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;毛深いもみじ &lt;a href="https://t.co/egVKmWiyex"&gt;pic.twitter.com/egVKmWiyex&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1331932801403289604?ref_src=twsrc%5Etfw"&gt;November 26, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;特に後ろ足のハミ毛が肉球を隠すくらい伸びていて, ちょっと危ないのでハミ毛の処理をしてみた.&lt;/p&gt;
&lt;p&gt;ハサミでやるのはちょっと怖かったのでバリカンを購入.&lt;/p&gt;
&lt;p&gt;&lt;img alt="バリカン" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan02.jpg" srcset="https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan02_hu_af2df681a4cf458f.jpg 800w, https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan02_hu_216028044e0fc317.jpg 1600w, https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan02_hu_3a6d729767622e9d.jpg 2400w, https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan02.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://www.doggyman.com/?p=showroom&amp;amp;keywords=%E3%83%90%E3%83%AA%E3%82%AB%E3%83%B3&amp;amp;id=1876" target="_blank" rel="noopener"
 &gt;ホームバーバー　エキスパートスタイル　コンパクト&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;初めて知ったんだけど猫専用バリカンというものはなくて, だいたい小型犬とかと兼用のものが使えるらしい.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;バリカンに挑戦 &lt;a href="https://t.co/oDPNO2Pg2c"&gt;pic.twitter.com/oDPNO2Pg2c&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1332895283206778880?ref_src=twsrc%5Etfw"&gt;November 29, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;途中の写真は撮れてないけど, そとちゃんは今回も協力的でおとなしく剃らせてくれた.&lt;/p&gt;
&lt;p&gt;うちのねこはほんとにいい子で助かる.&lt;br&gt;
(バリカンの音が思ったよりうるさくなかったのが良かったかもしれない&amp;hellip;)&lt;/p&gt;
&lt;p&gt;ハミ毛処理後の足はこんな感じ.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;とりあえず肉球がちゃんと見えるくらいまでハミ毛を剃れた &lt;a href="https://t.co/42ufY9RTdh"&gt;pic.twitter.com/42ufY9RTdh&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1332990950616907778?ref_src=twsrc%5Etfw"&gt;November 29, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;きれいなピンクの肉球がよく見えるようになってかわいい.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ねてる &lt;a href="https://t.co/41aBsgwCWP"&gt;pic.twitter.com/41aBsgwCWP&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1333274917903638528?ref_src=twsrc%5Etfw"&gt;November 30, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;h3 id="ソファ"&gt;ソファ
&lt;/h3&gt;&lt;p&gt;😭😭😭&lt;/p&gt;
&lt;p&gt;&lt;img alt="ソファ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan03.jpg" srcset="https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan03_hu_5e907f9b58534cbb.jpg 800w, https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan03_hu_7315c432d2bc1fbc.jpg 1600w, https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan03_hu_dcef1ef09e78a4ce.jpg 2400w, https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan03.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;もうだめだ😭😭😭&lt;/p&gt;
&lt;p&gt;&lt;img alt="そとちゃんの爪とぎ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan04.jpg" srcset="https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan04_hu_7825ba7805e062d.jpg 800w, https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan04_hu_9caf03cea398844b.jpg 1600w, https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan04_hu_b5b1271ecc10eb65.jpg 2400w, https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan04.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2020-11-03-sotochan/" target="_blank" rel="noopener"
 &gt;先月&lt;/a&gt;に引き続きソファバリバリするたびに叱ってたんだけど, どうやら&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;バリバリする&lt;/strong&gt; → &lt;strong&gt;しもべが寄ってくる&lt;/strong&gt; = &lt;strong&gt;かまってもらえる!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;と学習してしまったようで😭&lt;/p&gt;
&lt;p&gt;最近は朝俺が起きたときや夕方の仕事が終わりかけてるときだったり,&lt;br&gt;
かまってもらえるタイミングを見計らってわざとバリバリしてるようにも見える&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="そとちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan05.jpg" srcset="https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan05_hu_eafa8c8dad41092d.jpg 800w, https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan05_hu_42ef17b2f0846db9.jpg 1600w, https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan05_hu_f1ae5633eb8a3059.jpg 2400w, https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan05.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;自分が怒られてるとは微塵にも思ってないらしく, 現行犯で叱っても「なんか用？」みたいな顔をする.&lt;/p&gt;
&lt;p&gt;&lt;img alt="そとちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan06.jpg" srcset="https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan06_hu_665c4eaeb78dbea1.jpg 800w, https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan06_hu_4fbe001f676326f8.jpg 1600w, https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan06_hu_90e757979be112e7.jpg 2400w, https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan06.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;どうすりゃいいんだ&amp;hellip;😭&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;11月もそとちゃんは良い子だった.&lt;br&gt;
これからさらに寒くなるけどヒーターはあまり気に入ってもらえなかったので, 他の寒さ対策も考えたい.&lt;/p&gt;
&lt;p&gt;ソファはもうダメかも&amp;hellip;😭&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="簡単に目線はくれないねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan07.jpg" srcset="https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan07_hu_fed6b0db02b1c4d3.jpg 800w, https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan07_hu_43426ce307f27579.jpg 1600w, https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan07_hu_bfc3ea05e1bb41a3.jpg 2400w, https://blog.uzimihsr.com/post/2020-12-03-sotochan/sotochan07.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>Dockerとdocker-composeでMySQLを動かした</title><link>https://blog.uzimihsr.com/post/2020-11-27-mysql-on-docker/</link><pubDate>Fri, 27 Nov 2020 12:10:37 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-11-27-mysql-on-docker/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-11-27-mysql-on-docker/sotochan.jpg" alt="Featured image of post Dockerとdocker-composeでMySQLを動かした" /&gt;&lt;h2 id="環境構築が面倒"&gt;環境構築が面倒
&lt;/h2&gt;&lt;p&gt;DBを使ったアプリケーションを開発するときに毎回MySQLやテーブルを準備するのが嫌だったので,&lt;br&gt;
コンテナを使ってMySQLが動作する環境を簡単に作成できるようにした.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;MySQL&lt;/code&gt;のコンテナを&lt;code&gt;Docker&lt;/code&gt;で起動した&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docker-compose&lt;/code&gt;を使ってコンテナの起動時に初期設定用&lt;code&gt;SQL&lt;/code&gt;が自動で実行されるようにした&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt;&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/3afa9ecae472c0446fe959b3bb981530.js"&gt;&lt;/script&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# コンテナを直接起動する例&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run -d -p 3306:3306 --name mysql-container -e &lt;span class="nv"&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;rootユーザのパスワードに設定したい文字列&amp;gt; mysql:5.7.32
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# docker-composeで起動する例&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 上記docker-compose.ymlの他にpassword-root(rootパスワードを記述したファイル), member.sql初期設定用SQLファイルを用意して実行する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-compose up -d
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ホストOSからDBを操作するにはコンテナに入るか, 別のコンテナを建てるか, ホストOSのクライアントを使う&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container &lt;span class="nb"&gt;exec&lt;/span&gt; -it mysql-container mysql -u root -p
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run --rm -it mysql:5.7.32 mysql -h host.docker.internal -P &lt;span class="m"&gt;3306&lt;/span&gt; -u root -p
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mysql -h 127.0.0.1 -P &lt;span class="m"&gt;3306&lt;/span&gt; -u root -p&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Mojave 10.14&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/editions/community/docker-ce-desktop-mac" target="_blank" rel="noopener"
 &gt;Docker Desktop for Mac&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Version 2.5.0.0&lt;/li&gt;
&lt;li&gt;Kubernetes: v1.19.3&lt;/li&gt;
&lt;li&gt;Docker version 19.03.13&lt;/li&gt;
&lt;li&gt;docker-compose version 1.27.4&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/layers/mysql/library/mysql/5.7.32/images/sha256-ec6742af6625f76f98162b17fd62d22e1824d13fd80f214ab9184c7b6b50bad5?context=explore" target="_blank" rel="noopener"
 &gt;MySQL&lt;/a&gt; (Docker image)
&lt;ul&gt;
&lt;li&gt;Server version: 5.7.32&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#docker%e3%81%a7%e8%b5%b7%e5%8b%95%e3%81%99%e3%82%8b" &gt;Dockerで起動する&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#docker-compose%e3%81%a7%e8%b5%b7%e5%8b%95%e3%81%99%e3%82%8b" &gt;docker-composeで起動する&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="dockerで起動する"&gt;Dockerで起動する
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;MySQL&lt;/code&gt;の公式&lt;code&gt;Docker image&lt;/code&gt;&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;が用意されているので, これを使う.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# localhostからアクセスできるよう3306ポートを割り当てて起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 環境変数(MYSQL_ROOT_PASSWORD)でrootユーザのパスワード(hogehoge)を設定する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run -d -p 3306:3306 --name mysql-container -e &lt;span class="nv"&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;hogehoge mysql:5.7.32
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# コンテナに入ってMySQLクライアントを起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container &lt;span class="nb"&gt;exec&lt;/span&gt; -it mysql-container mysql -u root -p
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Enter password: &lt;span class="c1"&gt;# hogehoge&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Welcome to the MySQL monitor. Commands end with &lt;span class="p"&gt;;&lt;/span&gt; or &lt;span class="se"&gt;\g&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Your MySQL connection id is &lt;span class="m"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Server version: 5.7.32 MySQL Community Server &lt;span class="o"&gt;(&lt;/span&gt;GPL&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Copyright &lt;span class="o"&gt;(&lt;/span&gt;c&lt;span class="o"&gt;)&lt;/span&gt; 2000, 2019, Oracle and/or its affiliates. All rights reserved.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Oracle is a registered trademark of Oracle Corporation and/or its
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;affiliates. Other names may be trademarks of their respective
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;owners.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Type &lt;span class="s1"&gt;&amp;#39;help;&amp;#39;&lt;/span&gt; or &lt;span class="s1"&gt;&amp;#39;\h&amp;#39;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; help. Type &lt;span class="s1"&gt;&amp;#39;\c&amp;#39;&lt;/span&gt; to clear the current input statement.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mysql&amp;gt; show databases&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;+--------------------+
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; Database &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;+--------------------+
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; information_schema &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; mysql &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; performance_schema &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; sys &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;+--------------------+
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;4&lt;/span&gt; rows in &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;0.01 sec&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mysql&amp;gt; &lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Bye
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ホストOSのMySQLクライアントからも接続できる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mysql -h 127.0.0.1 -P &lt;span class="m"&gt;3306&lt;/span&gt; -u root -p
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Enter password: &lt;span class="c1"&gt;# hogehoge&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mysql&amp;gt; &lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Bye
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 使い捨てのコンテナからホストOSのlocalhost:3306で起動しているMySQLのコンテナに接続&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run --rm -it mysql:5.7.32 mysql -h host.docker.internal -P &lt;span class="m"&gt;3306&lt;/span&gt; -u root -p
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Enter password: &lt;span class="c1"&gt;# hogehoge&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mysql&amp;gt; &lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Bye
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# クライアント用のコンテナを使用するパターン&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 事前にdocker network(bridge)内のmysql-containerのIPを確認する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container inspect mysql-container -f &lt;span class="s2"&gt;&amp;#34;{{.NetworkSettings.IPAddress}}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;172.17.0.2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run --rm -it mysql:5.7.32 mysql -h 172.17.0.2 -P &lt;span class="m"&gt;3306&lt;/span&gt; -u root -p
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Enter password: &lt;span class="c1"&gt;# hogehoge&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mysql&amp;gt; &lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Bye
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# コンテナを削除&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container rm -f mysql-container&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;流石に&lt;code&gt;Docker&lt;/code&gt;なら簡単に動かせた.&lt;/p&gt;
&lt;h3 id="docker-composeで起動する"&gt;docker-composeで起動する
&lt;/h3&gt;&lt;p&gt;もうちょっと複雑なことがしたいので, &lt;code&gt;docker-compose&lt;/code&gt;で起動してみる.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/3afa9ecae472c0446fe959b3bb981530.js"&gt;&lt;/script&gt;
&lt;script src="https://gist.github.com/uzimihsr/9fd580abe2bc545694162130db29ecd3.js"&gt;&lt;/script&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# パスワードファイルの作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim password-root &lt;span class="c1"&gt;# パスワード文字列(hogehoge)を入力する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat password-root
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hogehoge
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# パスワードファイル(password-root), 初期設定用SQLファイル(member.sql), docker-compose.ymlが存在する状態&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker-compose.yml member.sql password-root
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# コンテナの起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-compose up -d
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Starting mysql-container ... &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# データベースの確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# mysql -h 127.0.0.1 -P 3306 -u root -p でも同じことができる(ホストOSのMySQLクライアントを使う場合)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-compose &lt;span class="nb"&gt;exec&lt;/span&gt; mysql mysql -u root -p
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Enter password: &lt;span class="c1"&gt;# hogehoge&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mysql&amp;gt; use mydb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Database changed
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mysql&amp;gt; SELECT * FROM members&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;+----+----------+------+---------+------+
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; id &lt;span class="p"&gt;|&lt;/span&gt; name &lt;span class="p"&gt;|&lt;/span&gt; team &lt;span class="p"&gt;|&lt;/span&gt; role &lt;span class="p"&gt;|&lt;/span&gt; age &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;+----+----------+------+---------+------+
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; Alice &lt;span class="p"&gt;|&lt;/span&gt; A &lt;span class="p"&gt;|&lt;/span&gt; manager &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; Ben &lt;span class="p"&gt;|&lt;/span&gt; B &lt;span class="p"&gt;|&lt;/span&gt; manager &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; Charlie &lt;span class="p"&gt;|&lt;/span&gt; A &lt;span class="p"&gt;|&lt;/span&gt; member &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;40&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; Daniel &lt;span class="p"&gt;|&lt;/span&gt; A &lt;span class="p"&gt;|&lt;/span&gt; member &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; Emily &lt;span class="p"&gt;|&lt;/span&gt; A &lt;span class="p"&gt;|&lt;/span&gt; member &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;6&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; Florence &lt;span class="p"&gt;|&lt;/span&gt; A &lt;span class="p"&gt;|&lt;/span&gt; member &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;7&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; George &lt;span class="p"&gt;|&lt;/span&gt; A &lt;span class="p"&gt;|&lt;/span&gt; trainee &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; Harry &lt;span class="p"&gt;|&lt;/span&gt; B &lt;span class="p"&gt;|&lt;/span&gt; member &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;40&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;9&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; Isabel &lt;span class="p"&gt;|&lt;/span&gt; B &lt;span class="p"&gt;|&lt;/span&gt; member &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;40&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; Jack &lt;span class="p"&gt;|&lt;/span&gt; B &lt;span class="p"&gt;|&lt;/span&gt; trainee &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;11&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; Katie &lt;span class="p"&gt;|&lt;/span&gt; B &lt;span class="p"&gt;|&lt;/span&gt; trainee &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;+----+----------+------+---------+------+
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;11&lt;/span&gt; rows in &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;0.00 sec&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 初期設定用SQLが実行されているので最初からデータベースとテーブルが作成されている&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;ポイントは2つ.&lt;/p&gt;
&lt;p&gt;1つめはrootユーザのパスワードをファイルから読み込む形にしていること.&lt;/p&gt;
&lt;p&gt;先程使用した環境変数の&lt;code&gt;MYSQL_ROOT_PASSWORD&lt;/code&gt;ではなく&lt;code&gt;MYSQL_ROOT_PASSWORD_FILE&lt;/code&gt;でファイルのパスを指定すればその中身をパスワードとして設定できるので,&lt;br&gt;
パスワード文字列(&lt;strong&gt;hogehoge&lt;/strong&gt;)が記述されたファイル(&lt;code&gt;password-root&lt;/code&gt;)をホストOSからコンテナにマウントしてそのパスを&lt;code&gt;MYSQL_ROOT_PASSWORD_FILE&lt;/code&gt;で指定するようにしている.&lt;/p&gt;
&lt;p&gt;こうすると&lt;code&gt;docker-compose.yml&lt;/code&gt;からパスワードの情報を分離できて,&lt;br&gt;
そのままリポジトリとかで共有できるようになる.&lt;/p&gt;
&lt;p&gt;2つめはデータベースの初期設定用の&lt;code&gt;SQL&lt;/code&gt;がコンテナの起動時に勝手に実行されるようにしていること.&lt;/p&gt;
&lt;p&gt;コンテナのディレクトリ&lt;code&gt;/docker-entrypoint-initdb.d&lt;/code&gt;の配下にある拡張子が&lt;code&gt;.sh&lt;/code&gt;, &lt;code&gt;.sql&lt;/code&gt;, &lt;code&gt;.sql.gz&lt;/code&gt;のスクリプトは勝手に実行されるので,&lt;br&gt;
ここに実行したい&lt;code&gt;SQL&lt;/code&gt;ファイル(&lt;code&gt;member.sql&lt;/code&gt;)をマウントしている.&lt;/p&gt;
&lt;p&gt;こうするとわざわざ起動後のコンテナに入って初期設定用の&lt;code&gt;SQL&lt;/code&gt;を実行する必要がなくなり,&lt;br&gt;
&lt;code&gt;docker-compose&lt;/code&gt;を立ち上げるだけで使いたいデータベースとテーブルが準備できるので便利.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Docker&lt;/code&gt;と&lt;code&gt;docker-compose&lt;/code&gt;を使って&lt;code&gt;MySQL&lt;/code&gt;を起動する手順を試してみた.&lt;/p&gt;
&lt;p&gt;特に&lt;code&gt;docker-compose&lt;/code&gt;を使う方法だと設定ファイルさえ用意すればコマンド1つでレコード入りのテーブルが簡単に用意できるのでめっちゃ便利だと思う.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="へそ天?するねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-11-27-mysql-on-docker/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-11-27-mysql-on-docker/sotochan_hu_e442132a71a3cccc.jpg 800w, https://blog.uzimihsr.com/post/2020-11-27-mysql-on-docker/sotochan_hu_e569666ea15843d5.jpg 1600w, https://blog.uzimihsr.com/post/2020-11-27-mysql-on-docker/sotochan_hu_ccd1ada29e7a38a0.jpg 2400w, https://blog.uzimihsr.com/post/2020-11-27-mysql-on-docker/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a class="link" href="https://hub.docker.com/_/mysql" target="_blank" rel="noopener"
 &gt;https://hub.docker.com/_/mysql&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>kube-apiserverのversionをcurlで確認する</title><link>https://blog.uzimihsr.com/post/2020-11-12-check-kube-apiserver-version-curl/</link><pubDate>Thu, 12 Nov 2020 20:20:40 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-11-12-check-kube-apiserver-version-curl/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-11-12-check-kube-apiserver-version-curl/sotochan.jpg" alt="Featured image of post kube-apiserverのversionをcurlで確認する" /&gt;&lt;h2 id="それもそう"&gt;それもそう
&lt;/h2&gt;&lt;p&gt;これも大した話ではないんだけど勉強になったのでメモ.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Kubernetes API&lt;/code&gt;の&lt;code&gt;/version&lt;/code&gt;をたたけばversion情報を取得できる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# kube-apiserverのversion情報を取得&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -s --insecure https://&amp;lt;Kubernetes API&amp;gt;/version &lt;span class="p"&gt;|&lt;/span&gt; jq &lt;span class="s1"&gt;&amp;#39;.gitVersion&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# jqが使えない場合でも生のjsonのgitVersionから読み取れる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl --insecure https://&amp;lt;Kubernetes API&amp;gt;/version
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Mojave 10.14&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/editions/community/docker-ce-desktop-mac" target="_blank" rel="noopener"
 &gt;Docker Desktop for Mac&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Version 2.5.0.0&lt;/li&gt;
&lt;li&gt;Kubernetes: v1.19.3&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/stedolan/jq" target="_blank" rel="noopener"
 &gt;jq&lt;/a&gt;-1.6&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やりかた"&gt;やりかた
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Kubernetes&lt;/code&gt;クラスタのAPIのバージョンを調べたいとき, &lt;code&gt;kubectl&lt;/code&gt;が使えるなら&lt;code&gt;kubectl version&lt;/code&gt;で確認できる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Docker DesktopのKubernetesクラスタを使用&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl cluster-info
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Kubernetes master is running at https://kubernetes.docker.internal:6443
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;KubeDNS is running at https://kubernetes.docker.internal:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;To further debug and diagnose cluster problems, use &lt;span class="s1"&gt;&amp;#39;kubectl cluster-info dump&amp;#39;&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Kubernetesのversionを確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl version --short
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Client Version: v1.19.3 &lt;span class="c1"&gt;# クライアント(kubectl)のversion&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Server Version: v1.19.3 &lt;span class="c1"&gt;# サーバー(kube-apiserver)のversion&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これを&lt;code&gt;kubectl&lt;/code&gt;が使えない環境で確認する方法がわかんなかった.&lt;br&gt;
とはいえ&lt;code&gt;kubectl&lt;/code&gt;も中身はwebクライアントなので, API側にHTTPリクエストを飛ばして結果を表示しているはず。&lt;/p&gt;
&lt;p&gt;ということで&lt;code&gt;kubectl&lt;/code&gt;のコードを読んでみた.&lt;br&gt;
&lt;code&gt;kubectl version&lt;/code&gt;を実行したときの処理はたぶんここ&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;br&gt;
呼び出されている&lt;code&gt;discoveryClient.ServerVersion()&lt;/code&gt;の処理はおそらくここ&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;br&gt;
APIエンドポイントの&lt;code&gt;/version&lt;/code&gt;にGETを飛ばしてるだけっぽい.&lt;/p&gt;
&lt;p&gt;というわけで&lt;code&gt;curl&lt;/code&gt;でやってみる.&lt;br&gt;
今回使う&lt;code&gt;Kubernetes&lt;/code&gt;クラスタは&lt;code&gt;Docker Desktop&lt;/code&gt;で立てたものなので&lt;a class="link" href="https://uzimihsr.github.io/post/2020-11-10-generate-client-certificate-and-key-from-kubeconfig/" target="_blank" rel="noopener"
 &gt;クライアント認証&lt;/a&gt;をしているが,&lt;br&gt;
他の認証方法を使っているクラスタの場合でもエンドポイント等は同じはず.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl --insecure --cert ./client.crt --key ./client.key https://kubernetes.docker.internal:6443/version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;major&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;1&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;minor&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;19&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;gitVersion&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;v1.19.3&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;gitCommit&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;1e11e4a2108024935ecfcb2912226cedeafd99df&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;gitTreeState&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;clean&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;buildDate&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;2020-10-14T12:41:49Z&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;goVersion&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;go1.15.2&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;compiler&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;gc&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;platform&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;linux/amd64&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;取れた.&lt;br&gt;
せっかくなので&lt;code&gt;jq&lt;/code&gt;で欲しい文字列を抜いてみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -s --insecure --cert ./client.crt --key ./client.key https://kubernetes.docker.internal:6443/version &lt;span class="p"&gt;|&lt;/span&gt; jq &lt;span class="s1"&gt;&amp;#39;.gitVersion&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;v1.19.3&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;やったぜ.&lt;br&gt;
&lt;code&gt;kubectl&lt;/code&gt;を使わずに&lt;code&gt;curl&lt;/code&gt;で&lt;code&gt;kube-apiserver&lt;/code&gt;のバージョン情報を取得することができた.&lt;/p&gt;
&lt;p&gt;ちなみにコードを探さなくても, &lt;code&gt;/&lt;/code&gt;をたたけば使えるエンドポイントの一覧が取得できた.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl --insecure --cert ./client.crt --key ./client.key https://kubernetes.docker.internal:6443/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;paths&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;/api&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;/api/v1&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;/apis&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;/apis/&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;/version&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;まあ今回は解決したのでヨシ!&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;kubectl&lt;/code&gt;を使わずに&lt;code&gt;curl&lt;/code&gt;で直接&lt;code&gt;Kubernetes API&lt;/code&gt;をたたいてバージョン情報を確認する方法がわかった.&lt;br&gt;
&lt;code&gt;Kubernetes API&lt;/code&gt;を呼び出して何かする処理を自分で0から実装しようとすると結構たいへんなので, &lt;code&gt;kubectl&lt;/code&gt;のコードを読んで参考にするのが良さそう.&lt;br&gt;
やっぱりちゃんとコードを読むのは大事だと思った.&lt;br&gt;
というか&lt;code&gt;kubectl&lt;/code&gt;が便利すぎる. 偉大.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="ひっくり返るねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-11-12-check-kube-apiserver-version-curl/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-11-12-check-kube-apiserver-version-curl/sotochan_hu_8627af33e10467b1.jpg 800w, https://blog.uzimihsr.com/post/2020-11-12-check-kube-apiserver-version-curl/sotochan_hu_ee6385c4669ba269.jpg 1600w, https://blog.uzimihsr.com/post/2020-11-12-check-kube-apiserver-version-curl/sotochan_hu_b784b28b41045dc.jpg 2400w, https://blog.uzimihsr.com/post/2020-11-12-check-kube-apiserver-version-curl/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/kubernetes/kubectl/blob/cfb4414565bb55f31d742b0762c2b1761fb74fc9/pkg/cmd/version/version.go#L126" target="_blank" rel="noopener"
 &gt;kubectl/pkg/cmd/version/version.go&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/kubernetes/client-go/blob/bef66adadf9a6371b5c114db0b95c12412c2414b/discovery/discovery_client.go#L408-L419" target="_blank" rel="noopener"
 &gt;client-go/discovery/discovery_client.go&lt;/a&gt;&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>kubeconfigにベタ書きされたclient-certificate-dataをファイル化して使う</title><link>https://blog.uzimihsr.com/post/2020-11-10-generate-client-certificate-and-key-from-kubeconfig/</link><pubDate>Tue, 10 Nov 2020 21:43:47 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-11-10-generate-client-certificate-and-key-from-kubeconfig/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-11-10-generate-client-certificate-and-key-from-kubeconfig/sotochan.jpg" alt="Featured image of post kubeconfigにベタ書きされたclient-certificate-dataをファイル化して使う" /&gt;&lt;h2 id="それはそう"&gt;それはそう
&lt;/h2&gt;&lt;p&gt;冷静に考えれば大したことないんだけどちょっと詰まったので一応メモ.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;kubeconfig&lt;/code&gt;にベタ書きされている&lt;strong&gt;client-certificate-data&lt;/strong&gt;(クライアント証明書)と&lt;strong&gt;client-key-data&lt;/strong&gt;(秘密鍵)は&lt;code&gt;base64&lt;/code&gt;デコードするとファイルとして普通に使える.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# kubeconfigにベタ書きされたクライアント証明書(client.crt)と秘密鍵(client.key)をファイルに出力する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl config view --minify --raw -o &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;{.users[].user.client-certificate-data}&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; base64 --decode &amp;gt; client.crt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl config view --minify --raw -o &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;{.users[].user.client-key-data}&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; base64 --decode &amp;gt; client.key
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# kubectlじゃなくてもOK&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;## awkでやるパターン&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat ~/.kube/config &lt;span class="p"&gt;|&lt;/span&gt; grep client-certificate-data &lt;span class="p"&gt;|&lt;/span&gt; awk &lt;span class="s1"&gt;&amp;#39;{print $2}&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; base64 --decode &amp;gt; client.crt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat ~/.kube/config &lt;span class="p"&gt;|&lt;/span&gt; grep client-key-data &lt;span class="p"&gt;|&lt;/span&gt; awk &lt;span class="s1"&gt;&amp;#39;{print $2}&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; base64 --decode &amp;gt; client.key
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;## yqつかうパターン&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat ~/.kube/config &lt;span class="p"&gt;|&lt;/span&gt; yq r - &lt;span class="s2"&gt;&amp;#34;users[*].user.client-certificate-data&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; base64 --decode &amp;gt; client.crt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat ~/.kube/config &lt;span class="p"&gt;|&lt;/span&gt; yq r - &lt;span class="s2"&gt;&amp;#34;users[*].user.client-key-data&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; base64 --decode &amp;gt; client.key
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# クライアント証明書(client.crt)と秘密鍵(client.key)を使ってcurlでKubernetes APIにアクセス&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl --insecure --cert ./client.crt --key ./client.key https://&amp;lt;Kubernetes API&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Mojave 10.14&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/editions/community/docker-ce-desktop-mac" target="_blank" rel="noopener"
 &gt;Docker Desktop for Mac&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Version 2.5.0.0&lt;/li&gt;
&lt;li&gt;Kubernetes: v1.19.3&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mikefarah/yq" target="_blank" rel="noopener"
 &gt;yq&lt;/a&gt; version 3.3.2&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やりかた"&gt;やりかた
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Docker Desktop&lt;/code&gt;で作った&lt;code&gt;Kubernetes&lt;/code&gt;クラスタへのクライアント認証の情報は&lt;code&gt;~/.kube/config&lt;/code&gt;(&lt;code&gt;kubeconfig&lt;/code&gt;)に自動でベタ書きされている.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# client-certificate-data : クライアント証明書&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# client-key-data : クライアントの秘密鍵&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl config view --minify --raw
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apiVersion: v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;clusters:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- cluster:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; certificate-authority-data: LS0t...Cg&lt;span class="o"&gt;==&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; server: https://kubernetes.docker.internal:6443
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: docker-desktop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;contexts:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- context:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cluster: docker-desktop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; user: docker-desktop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: docker-desktop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;current-context: docker-desktop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kind: Config
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;preferences: &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;users:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- name: docker-desktop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; user:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; client-certificate-data: LS0t...LS0K
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; client-key-data: LS0t...Cg&lt;span class="o"&gt;==&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このクラスタのAPIへ&lt;code&gt;curl&lt;/code&gt;で接続しようとすると, &lt;a class="link" href="https://uzimihsr.github.io/post/2020-06-26-client-certification-practice/" target="_blank" rel="noopener"
 &gt;クライアント認証&lt;/a&gt;で弾かれてしまう.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# k8s API側がオレオレ証明書なので --insecure が必要&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl --insecure https://kubernetes.docker.internal:6443
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;kind&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;Status&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;apiVersion&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;v1&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;metadata&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;status&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;Failure&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;message&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;forbidden: User \&amp;#34;system:anonymous\&amp;#34; cannot get path \&amp;#34;/\&amp;#34;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;reason&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;Forbidden&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;details&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;code&amp;#34;&lt;/span&gt;: &lt;span class="m"&gt;403&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;おとなしく&lt;code&gt;kubectl&lt;/code&gt;を使えばいいんだけど, 理由はさておきどうしても&lt;code&gt;curl&lt;/code&gt;で接続したいことがあった.&lt;br&gt;
&lt;a class="link" href="https://uzimihsr.github.io/post/2020-06-26-client-certification-practice/" target="_blank" rel="noopener"
 &gt;curlでクライアント認証&lt;/a&gt;を突破するには&lt;code&gt;--cert&lt;/code&gt;(クライアント証明書)と&lt;code&gt;--key&lt;/code&gt;(クライアント秘密鍵)が必要なので,&lt;br&gt;
&lt;code&gt;kubeconfig&lt;/code&gt;にベタ書きされている値を&lt;code&gt;base64&lt;/code&gt;でデコードする.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# クライアント証明書をbase64デコード&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl config view --minify --raw -o &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;{.users[].user.client-certificate-data}&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; base64 -D
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-----BEGIN CERTIFICATE-----
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;MIIDFTCCAf2gAwIBAgIICzCv4rM20vUwDQYJKoZIhvcNAQELBQAwFTETMBEGA1UE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;QCUVil5khgn66X0Pd2GAs37k66Yyx7urGw&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-----END CERTIFICATE-----
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# クライアントの秘密鍵をbase64デコード&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl config view --minify --raw -o &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;{.users[].user.client-key-data}&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; base64 -D
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-----BEGIN RSA PRIVATE KEY-----
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;MIIEowIBAAKCAQEAx6UtMTtlcvZWKPiQcDSlP7Ic2b2QOpigVifG6HOU5OtBc+Fn
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;PEUMoWLF7jKfAGRtKrnY9DTE4HeDoohXlDG47KC+TLrm1bSwxMIn
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-----END RSA PRIVATE KEY-----
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;よくみる&lt;code&gt;PEM&lt;/code&gt;形式の証明書と秘密鍵が確認できる.&lt;br&gt;
あとはこれをファイルに出力するだけ.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# クライアント証明書(client.crt)と秘密鍵(client.key)をファイルに出力する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl config view --minify --raw -o &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;{.users[].user.client-certificate-data}&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; base64 -D -o client.crt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl config view --minify --raw -o &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;{.users[].user.client-key-data}&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; base64 -D -o client.key
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;作成したクライアント証明書と秘密鍵のファイルを使って再度&lt;code&gt;Kubernetes&lt;/code&gt;クラスタのAPIを叩いてみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# クライアント証明書(client.crt)と秘密鍵(client.key)を使って認証を突破&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl --insecure --cert ./client.crt --key ./client.key https://kubernetes.docker.internal:6443
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;paths&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;/api&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;/api/v1&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;/version&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;クライアント認証を突破できた.&lt;br&gt;
やったぜ.&lt;/p&gt;
&lt;p&gt;今回はクライアント証明書と秘密鍵を&lt;code&gt;kubeconfig&lt;/code&gt;から取り出すのに&lt;code&gt;kubectl&lt;/code&gt;を使ったけど,&lt;br&gt;
&lt;code&gt;yaml&lt;/code&gt;形式のファイルから任意の値を取り出せるならもちろん他の方法でもできる.&lt;br&gt;
&lt;code&gt;kubectl&lt;/code&gt;が使えなくて&lt;code&gt;kubeconfig&lt;/code&gt;しかないような場合はこっちの方法を使うことが多そう.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# grepとawkでやる例&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat ~/.kube/config &lt;span class="p"&gt;|&lt;/span&gt; grep client-certificate-data &lt;span class="p"&gt;|&lt;/span&gt; awk &lt;span class="s1"&gt;&amp;#39;{print $2}&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; base64 -D
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat ~/.kube/config &lt;span class="p"&gt;|&lt;/span&gt; grep client-key-data &lt;span class="p"&gt;|&lt;/span&gt; awk &lt;span class="s1"&gt;&amp;#39;{print $2}&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; base64 -D
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# yqでやる例&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat ~/.kube/config &lt;span class="p"&gt;|&lt;/span&gt; yq r - &lt;span class="s2"&gt;&amp;#34;users[*].user.client-certificate-data&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; base64 -D
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat ~/.kube/config &lt;span class="p"&gt;|&lt;/span&gt; yq r - &lt;span class="s2"&gt;&amp;#34;users[*].user.client-key-data&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; base64 -D
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# いずれも出力はkubectl config viewから取り出したときと同じ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;kubectl&lt;/code&gt;は使えないけど&lt;code&gt;kubeconfig&lt;/code&gt;は存在する, みたいな環境でどうしても&lt;code&gt;Kubernetes&lt;/code&gt;クラスタのAPIをたたく必要があったので一応やってみた.&lt;br&gt;
&lt;code&gt;kubectl&lt;/code&gt;が使える環境だけど&lt;code&gt;curl&lt;/code&gt;でのアクセスを試したい, というような場合は事前に&lt;code&gt;ServiceAccount&lt;/code&gt;を作って&lt;code&gt;Bearer Token&lt;/code&gt;を発行したほうがたぶんはやい&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="食パンクッションに乗るねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-11-10-generate-client-certificate-and-key-from-kubeconfig/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-11-10-generate-client-certificate-and-key-from-kubeconfig/sotochan_hu_b49a61dc3690b4d.jpg 800w, https://blog.uzimihsr.com/post/2020-11-10-generate-client-certificate-and-key-from-kubeconfig/sotochan_hu_8f2628356cbd4a10.jpg 1600w, https://blog.uzimihsr.com/post/2020-11-10-generate-client-certificate-and-key-from-kubeconfig/sotochan_hu_e16054d49e35c584.jpg 2400w, https://blog.uzimihsr.com/post/2020-11-10-generate-client-certificate-and-key-from-kubeconfig/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a class="link" href="https://kubernetes.io/ja/docs/reference/access-authn-authz/authentication/#%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E3%82%A2%E3%82%AB%E3%82%A6%E3%83%B3%E3%83%88%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3" target="_blank" rel="noopener"
 &gt;Kubernetes Docs&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>10月のそとちゃんまとめ(2020)</title><link>https://blog.uzimihsr.com/post/2020-11-03-sotochan/</link><pubDate>Tue, 03 Nov 2020 13:55:49 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-11-03-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-11-03-sotochan/sotochan03.jpg" alt="Featured image of post 10月のそとちゃんまとめ(2020)" /&gt;&lt;h2 id="ドラキュラねこ"&gt;ドラキュラねこ
&lt;/h2&gt;&lt;p&gt;10月のそとちゃんは新居にも慣れて元気いっぱいだった.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%bd%e3%83%95%e3%82%a1%e3%81%a0%e3%81%84%e3%81%99%e3%81%8d" &gt;ソファだいすき&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%8f%e3%83%ad%e3%82%a6%e3%82%a3%e3%83%b3" &gt;ハロウィン&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="ソファだいすき"&gt;ソファだいすき
&lt;/h3&gt;&lt;p&gt;引っ越しに合わせて買ったソファがだいぶ気に入ったらしく, 最近はずっとごろごろしている.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;しろくてかわいいね &lt;a href="https://t.co/Q4Kz1wf518"&gt;pic.twitter.com/Q4Kz1wf518&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1311681185752346625?ref_src=twsrc%5Etfw"&gt;October 1, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ソファを占拠 &lt;a href="https://t.co/zSil5iCdUf"&gt;pic.twitter.com/zSil5iCdUf&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1313660025970122753?ref_src=twsrc%5Etfw"&gt;October 7, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;気に入ってくれたのは良かったんだけど,&lt;br&gt;
ちょっと座ろうと思ってもど真ん中で寝てたりするのでたまに座れなくて困る.&lt;br&gt;
どうして人間2人がけのソファをねこ1匹で占領するのか&amp;hellip;🤔&lt;/p&gt;
&lt;p&gt;また, 最近寒くなってきたおかげで俺がソファに座ってるとひざの上に乗ってくれる. うれしい.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;家の暖房を点けるかどうかで家族会議中&lt;br&gt;(議長:ねこ) &lt;a href="https://t.co/dOv8elCMme"&gt;pic.twitter.com/dOv8elCMme&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1316663824255123456?ref_src=twsrc%5Etfw"&gt;October 15, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;仕事させる気0 &lt;a href="https://t.co/2rthPAJQLj"&gt;pic.twitter.com/2rthPAJQLj&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1319071593025261568?ref_src=twsrc%5Etfw"&gt;October 22, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;そとちゃんに乗られると柔らかいし暖かいしとても幸せ(何もできなくなるけど).&lt;/p&gt;
&lt;p&gt;流石に仕事中は困るので降りていただくことになるが, その後のプレッシャーがすごい&amp;hellip;😭&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ひざから降ろされたときの顔 &lt;a href="https://t.co/KETV5dBnve"&gt;pic.twitter.com/KETV5dBnve&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1319200664702963713?ref_src=twsrc%5Etfw"&gt;October 22, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;そして危惧していた事態が現実に&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="ソファ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-11-03-sotochan/sotochan01.jpg" srcset="https://blog.uzimihsr.com/post/2020-11-03-sotochan/sotochan01_hu_12f327d30f86c8b5.jpg 800w, https://blog.uzimihsr.com/post/2020-11-03-sotochan/sotochan01_hu_36fe091327e29b7c.jpg 1600w, https://blog.uzimihsr.com/post/2020-11-03-sotochan/sotochan01_hu_e722b3c593c8be4a.jpg 2400w, https://blog.uzimihsr.com/post/2020-11-03-sotochan/sotochan01.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;なんとそとちゃんが&lt;strong&gt;ソファで爪とぎ&lt;/strong&gt;するようになってしまった.&lt;/p&gt;
&lt;p&gt;&lt;img alt="ソファ…" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-11-03-sotochan/sotochan02.jpg" srcset="https://blog.uzimihsr.com/post/2020-11-03-sotochan/sotochan02_hu_811e63fe0fbe5549.jpg 800w, https://blog.uzimihsr.com/post/2020-11-03-sotochan/sotochan02_hu_fedeea951974eab4.jpg 1600w, https://blog.uzimihsr.com/post/2020-11-03-sotochan/sotochan02_hu_5d18c1b506bb3f10.jpg 2400w, https://blog.uzimihsr.com/post/2020-11-03-sotochan/sotochan02.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;買ってから最初の数週間は爪を立てるそぶりも無かったのに,&lt;br&gt;
どのタイミングで気づいたのかはわからないけど爪が布にひっかかっておもしろくなっちゃったらしい&amp;hellip;&lt;/p&gt;
&lt;p&gt;我が家の教育方針は&lt;strong&gt;のびのび教育, 自由に育てる&lt;/strong&gt;がモットーなのであまり叱らないようにしているんだけど,&lt;br&gt;
ボロボロにされて中身が出ちゃったりすると誤飲とかが怖いので今回ばかりはちょっと怒った.&lt;/p&gt;
&lt;p&gt;そしてこの顔である.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ソファバリバリにしたからめっちゃおこられた &lt;a href="https://t.co/HYGaXuNwVC"&gt;pic.twitter.com/HYGaXuNwVC&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1321320877078667266?ref_src=twsrc%5Etfw"&gt;October 28, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;ねこには日本語が通じないので, 全く効果なし&amp;hellip;&lt;/p&gt;
&lt;p&gt;ソファをバリバリしてる場面を見つけ次第やめさせてるんだけど,&lt;br&gt;
そとちゃんは賢いので俺が寝てる間に思う存分バリバリしているっぽい.&lt;/p&gt;
&lt;p&gt;ソファのすぐ横にお気に入りのつめとぎもあるんですけどね&amp;hellip;😭&lt;/p&gt;
&lt;h3 id="ハロウィン"&gt;ハロウィン
&lt;/h3&gt;&lt;p&gt;今年のハロウィンもそとちゃんにドラキュラになってもらった.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ドラキュラそとちゃん &lt;a href="https://t.co/WnBGWyKpSZ"&gt;pic.twitter.com/WnBGWyKpSZ&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1322540981565091841?ref_src=twsrc%5Etfw"&gt;October 31, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;着せてるのは去年と同じ100均のペット用マントだけど,&lt;br&gt;
これくらい作りがシンプル(首とお腹に巻くだけ)だとつけててもそこまで嫌じゃないらしく着せてる間も協力的だった.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;宇宙一かわいいねえ&lt;br&gt;おやついくらでもあげちゃう &lt;a href="https://t.co/5Osrj2dvYT"&gt;pic.twitter.com/5Osrj2dvYT&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1322542405338320896?ref_src=twsrc%5Etfw"&gt;October 31, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;マントが似合っててめっちゃかわいい.&lt;br&gt;
なんかキメ顔してるように見えるのも最高.&lt;/p&gt;
&lt;p&gt;ソファバリバリやねずみドリブルでお忙しい中俺のわがままに付き合ってもらったので,&lt;br&gt;
お礼に一番お気に入りのおやつを&lt;a class="link" href="https://www.instagram.com/p/CHAvdFVl5aG/?utm_source=ig_web_copy_link" target="_blank" rel="noopener"
 &gt;プレゼント&lt;/a&gt;した.&lt;/p&gt;
&lt;p&gt;1人じゃハロウィンなんて絶対スルーしてるけど, そとちゃんと一緒だと祝おうという気持ちになるのがふしぎ.&lt;br&gt;
いつまで祝えるかはわからないけど, できるだけ長く毎年祝えるようにしたい.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;10月のそとちゃんはちょっとわるいこと(ソファバリバリ)に目覚めてしまったけど, 基本は良い子にしてたし元気いっぱいだった.&lt;/p&gt;
&lt;p&gt;ソファバリバリの件はこのまま放っておくとソファが破壊されてしまうので, どうにかしつけの方法を考えたい&amp;hellip;&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="仮装を褒められてドヤ顔するねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-11-03-sotochan/sotochan03.jpg" srcset="https://blog.uzimihsr.com/post/2020-11-03-sotochan/sotochan03_hu_e0166c8fdd6188c4.jpg 800w, https://blog.uzimihsr.com/post/2020-11-03-sotochan/sotochan03_hu_9175289efe4b5ad6.jpg 1600w, https://blog.uzimihsr.com/post/2020-11-03-sotochan/sotochan03_hu_cbb836df7f0b9da8.jpg 2400w, https://blog.uzimihsr.com/post/2020-11-03-sotochan/sotochan03.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>Github Actionsを使ってDocker ImageをGitHub Container RegistryにPushする</title><link>https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/</link><pubDate>Sun, 11 Oct 2020 23:01:22 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sotochan.jpg" alt="Featured image of post Github Actionsを使ってDocker ImageをGitHub Container RegistryにPushする" /&gt;&lt;h2 id="cicdっぽいことがしたい"&gt;CI/CDっぽいことがしたい
&lt;/h2&gt;&lt;p&gt;GitHub公式のCI/CDサービスGitHub Actionsを使って, リポジトリ上のDockerfileからimageをbuildしてpushする手順を試した.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://github.com/" target="_blank" rel="noopener"
 &gt;GitHub&lt;/a&gt;のPAT(個人アクセストークン)をリポジトリの&lt;code&gt;Secrets&lt;/code&gt;に&lt;strong&gt;CR_PAT&lt;/strong&gt;として登録した状態で以下のような&lt;code&gt;.github/workflows/docker-publish.yml&lt;/code&gt;を作成すると,&lt;br&gt;
&lt;strong&gt;master&lt;/strong&gt;ブランチへのcommitやrelease(tag)の作成時に&lt;code&gt;Docker image&lt;/code&gt;を&lt;code&gt;GitHub Action&lt;/code&gt;で&lt;code&gt;GitHub Container Registry&lt;/code&gt;にpushすることができる.&lt;br&gt;
pushした&lt;code&gt;image&lt;/code&gt; : &lt;a class="link" href="https://github.com/users/uzimihsr/packages/container/package/echo" target="_blank" rel="noopener"
 &gt;https://github.com/users/uzimihsr/packages/container/package/echo&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# ghcr.io/&amp;lt;GitHubアカウント&amp;gt;/&amp;lt;image名&amp;gt;:&amp;lt;タグ&amp;gt;のimageをGitHub Packagesにpushするworkflow&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Docker&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# masterブランチまたはvから始まるtag(例:`v1.2.3`)のpushでjobsを実行する&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;push&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;branches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;master&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;v*&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 全ブランチのPRに対してもjobsを実行&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pull_request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# &amp;lt;image名&amp;gt;を指定&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;IMAGE_NAME&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;echo&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# テスト用のjob&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/checkout@v2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Run tests&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="sd"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; if [ -f docker-compose.test.yml ]; then
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; docker-compose --file docker-compose.test.yml build
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; docker-compose --file docker-compose.test.yml run sut
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; else
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; docker build . --file Dockerfile
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; fi&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# imageをpushする&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;push&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# test jobが成功した場合のみトリガーされる&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;needs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;test&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# pushイベント以外(PRなど)では実行されない&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;if&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;github.event_name == &amp;#39;push&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/checkout@v2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Build image&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;docker build . --file Dockerfile --tag $IMAGE_NAME&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Log into GitHub Container Registry&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# `read:packages`と`write:packages`の権限を持つPAT(個人アクセストークン)をSecretに`CR_PAT`として登録しておく&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# PATの作成手順 : https://docs.github.com/ja/free-pro-team@latest/github/authenticating-to-github/creating-a-personal-access-token&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;echo &amp;#34;${{ secrets.CR_PAT }}&amp;#34; | docker login https://ghcr.io -u ${{ github.actor }} --password-stdin&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Push image to GitHub Container Registry&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="sd"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; # &amp;lt;GitHubアカウント&amp;gt;が自動で選択される
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; IMAGE_ID=ghcr.io/${{ github.repository_owner }}/$IMAGE_NAME
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; IMAGE_ID=$(echo $IMAGE_ID | tr &amp;#39;[A-Z]&amp;#39; &amp;#39;[a-z]&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; VERSION=$(echo &amp;#34;${{ github.ref }}&amp;#34; | sed -e &amp;#39;s,.*/\(.*\),\1,&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; # git tagの値を&amp;lt;タグ&amp;gt;として付与
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; [[ &amp;#34;${{ github.ref }}&amp;#34; == &amp;#34;refs/tags/&amp;#34;* ]] &amp;amp;&amp;amp; VERSION=$(echo $VERSION | sed -e &amp;#39;s/^v//&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; # masterブランチへのcommitでトリガーされている場合はlatestを&amp;lt;タグ&amp;gt;として使う
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; [ &amp;#34;$VERSION&amp;#34; == &amp;#34;master&amp;#34; ] &amp;amp;&amp;amp; VERSION=latest
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; echo IMAGE_ID=$IMAGE_ID
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; echo VERSION=$VERSION
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; docker tag $IMAGE_NAME $IMAGE_ID:$VERSION
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; docker push $IMAGE_ID:$VERSION&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/uzimihsr/echo-image/blob/master/.github/workflows/docker-publish.yml" target="_blank" rel="noopener"
 &gt;https://github.com/uzimihsr/echo-image/blob/master/.github/workflows/docker-publish.yml&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Mojave 10.14&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/" target="_blank" rel="noopener"
 &gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/features/packages" target="_blank" rel="noopener"
 &gt;GitHub Packages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://git-scm.com/" target="_blank" rel="noopener"
 &gt;Git&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;git version 2.20.1 (Apple Git-117)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/editions/community/docker-ce-desktop-mac" target="_blank" rel="noopener"
 &gt;Docker Desktop for Mac&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Version 2.1.0.3&lt;/li&gt;
&lt;li&gt;Docker Engine 19.03.13&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やりかた"&gt;やりかた
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#pat%e3%81%ae%e7%99%ba%e8%a1%8c%e3%81%a8%e3%83%ad%e3%82%b0%e3%82%a4%e3%83%b3" &gt;PATの発行とログイン&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e6%89%8b%e5%8b%95%e3%81%a7push" &gt;手動でpush&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#github-actions%e3%81%a7push" &gt;GitHub Actionsでpush&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="patの発行とログイン"&gt;PATの発行とログイン
&lt;/h3&gt;&lt;p&gt;まずは公式ドキュメント&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;を参考に, &lt;code&gt;GitHub Container Registry&lt;/code&gt;の認証に必要な&lt;code&gt;PAT&lt;/code&gt;(個人アクセストークン)を発行する.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;GitHub&lt;/code&gt;にログインした状態で&lt;br&gt;
&lt;a class="link" href="https://github.com/settings/tokens" target="_blank" rel="noopener"
 &gt;https://github.com/settings/tokens&lt;/a&gt;&lt;br&gt;
を開き, &lt;strong&gt;Generate new token&lt;/strong&gt;をクリック.&lt;br&gt;
&lt;img alt="GitHubの設定画面" class="gallery-image" data-flex-basis="896px" data-flex-grow="373" height="771" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc01.png" srcset="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc01_hu_8f5c7b4167cf8374.png 800w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc01_hu_2efe9ff7633a3755.png 1600w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc01_hu_3de0eba9dbca6029.png 2400w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc01.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;PAT&lt;/code&gt;の権限設定画面では&lt;code&gt;write:packages&lt;/code&gt;, &lt;code&gt;read:packages&lt;/code&gt;にのみチェックを入れて&lt;strong&gt;Genetate token&lt;/strong&gt;をクリック.&lt;br&gt;
&lt;img alt="PATの作成" class="gallery-image" data-flex-basis="204px" data-flex-grow="85" height="2117" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc02.png" srcset="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc02_hu_2d68be7c70e8ee02.png 800w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc02_hu_90733c04af8c348a.png 1600w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc02.png 1800w" width="1800"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;PAT&lt;/code&gt;が発行される.&lt;br&gt;
&lt;img alt="発行されたPAT" class="gallery-image" data-flex-basis="658px" data-flex-grow="274" height="1049" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc03.png" srcset="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc03_hu_3754e33e00acd9f1.png 800w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc03_hu_1e2617c747050847.png 1600w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc03_hu_5ea5dfbc7929df59.png 2400w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc03.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;発行された&lt;code&gt;PAT&lt;/code&gt;を使って, コマンドラインから&lt;code&gt;GitHub Container Registry&lt;/code&gt;にログインする.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# GitHub Container Registryにログイン&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &amp;lt;PAT&amp;gt; &lt;span class="p"&gt;|&lt;/span&gt; docker login ghcr.io -u &amp;lt;GitHubアカウント&amp;gt; --password-stdin
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Login Succeeded&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;これでログインは成功.&lt;/p&gt;
&lt;h3 id="手動でpush"&gt;手動でpush
&lt;/h3&gt;&lt;p&gt;上記の手順で&lt;code&gt;GitHub Container Registry&lt;/code&gt;にログインした状態で, まずはコマンドラインから&lt;code&gt;image&lt;/code&gt;をpushしてみる.&lt;/p&gt;
&lt;p&gt;適当な&lt;code&gt;image&lt;/code&gt;を作成.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 適当なディレクトリで適当なDockerfileを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; /path/to/workspace
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ touch Dockerfile
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Docker imageをビルド, 動作確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image build -t echo:latest .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run --rm echo:latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hello, world!&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;script src="https://gist.github.com/uzimihsr/cb9e6994a2db25bc888f7aebd41b189f.js"&gt;&lt;/script&gt;
&lt;p&gt;次にこの&lt;code&gt;image&lt;/code&gt;に&lt;code&gt;GitHub Container Registry&lt;/code&gt;用のタグをつけ, pushする.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# imageのタグをつけ直す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image tag echo:latest ghcr.io/uzimihsr/echo:latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Docker imageをpush&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image push ghcr.io/uzimihsr/echo:latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;The push refers to repository &lt;span class="o"&gt;[&lt;/span&gt;ghcr.io/uzimihsr/echo&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;be8b8b42328a: Pushed
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;latest: digest: sha256:c7926eae1c1aef6291e5eef1673c9815b5644fa9c417bfab65a4baba50c046a2 size: &lt;span class="m"&gt;527&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;pushした&lt;code&gt;image&lt;/code&gt;の情報は&lt;code&gt;GitHub Packages&lt;/code&gt;のUIから確認できる.&lt;br&gt;
&lt;a class="link" href="https://github.com/users/uzimihsr/packages/container/package/echo" target="_blank" rel="noopener"
 &gt;https://github.com/users/uzimihsr/packages/container/package/echo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="pushしたimage" class="gallery-image" data-flex-basis="565px" data-flex-grow="235" height="1223" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc04.png" srcset="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc04_hu_2025c359a370aa76.png 800w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc04_hu_189b855b87275eef.png 1600w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc04_hu_9c1bd2bb07d833a3.png 2400w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc04.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;もちろんこの&lt;code&gt;image&lt;/code&gt;をpullして使うこともできる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ローカルのimageを削除&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image rm ghcr.io/uzimihsr/echo:latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# imageをpull&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image pull ghcr.io/uzimihsr/echo:latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;latest: Pulling from uzimihsr/echo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Digest: sha256:c7926eae1c1aef6291e5eef1673c9815b5644fa9c417bfab65a4baba50c046a2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Status: Downloaded newer image &lt;span class="k"&gt;for&lt;/span&gt; ghcr.io/uzimihsr/echo:latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ghcr.io/uzimihsr/echo:latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 動作確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run --rm ghcr.io/uzimihsr/echo:latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hello, world!&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;これで&lt;code&gt;GitHub Container Registry&lt;/code&gt;を使った&lt;code&gt;image&lt;/code&gt;のpush/pullができるようになった.&lt;/p&gt;
&lt;h3 id="github-actionsでpush"&gt;GitHub Actionsでpush
&lt;/h3&gt;&lt;p&gt;次に&lt;code&gt;GitHub Actions&lt;/code&gt;を使って&lt;code&gt;image&lt;/code&gt;を&lt;code&gt;GitHub Container Registry&lt;/code&gt;にpushしてみる.&lt;/p&gt;
&lt;p&gt;新たに&lt;code&gt;GitHub&lt;/code&gt;リポジトリを&lt;a class="link" href="https://github.com/new" target="_blank" rel="noopener"
 &gt;作成&lt;/a&gt;し, 先程作成した&lt;code&gt;Dockerfile&lt;/code&gt;をgit pushする.&lt;br&gt;
作ったリポジトリ : &lt;a class="link" href="https://github.com/uzimihsr/echo-image" target="_blank" rel="noopener"
 &gt;https://github.com/uzimihsr/echo-image&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Dockerfileが存在する状態&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Dockerfile
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# git initからpushまで&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git init
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git remote add origin https://github.com/uzimihsr/echo-image.git
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git add .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git commit -m &lt;span class="s2"&gt;&amp;#34;initial commit&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git push origin master&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;リポジトリの&lt;strong&gt;Actions&lt;/strong&gt;タブを開き, &lt;code&gt;Publish Docker Container&lt;/code&gt;アクションの&lt;strong&gt;Set up this workflow&lt;/strong&gt;をクリック.&lt;br&gt;
&lt;img alt="GitHub Actions" class="gallery-image" data-flex-basis="384px" data-flex-grow="160" height="1800" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc05.png" srcset="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc05_hu_8f7bcaea2fe44623.png 800w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc05_hu_bb4035cb1ae1c7d8.png 1600w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc05_hu_598b38af5d8ef2e9.png 2400w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc05.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;workflow&lt;/code&gt;の定義ファイル&lt;code&gt;docker-publish.yml&lt;/code&gt;を編集する画面が開く.&lt;br&gt;
このままでも動くけど, 自分用に&lt;code&gt;env.IMAGE_NAME&lt;/code&gt;だけ任意の&lt;code&gt;image&lt;/code&gt;名に修正する.&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;docker-publish.yml&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# ghcr.io/&amp;lt;GitHubアカウント&amp;gt;/&amp;lt;image名&amp;gt;:&amp;lt;タグ&amp;gt;のimageをGitHub Packagesにpushするworkflow&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Docker&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# masterブランチまたはvから始まるtag(例:`v1.2.3`)のpushでjobsを実行する&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;push&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;branches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;master&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;v*&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 全ブランチのPRに対してもjobsを実行&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pull_request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# &amp;lt;image名&amp;gt;を指定&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;IMAGE_NAME&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;echo&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# テスト用のjob&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/checkout@v2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Run tests&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="sd"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; if [ -f docker-compose.test.yml ]; then
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; docker-compose --file docker-compose.test.yml build
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; docker-compose --file docker-compose.test.yml run sut
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; else
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; docker build . --file Dockerfile
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; fi&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# imageをpushする&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;push&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# test jobが成功した場合のみトリガーされる&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;needs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;test&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# pushイベント以外(PRなど)では実行されない&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;if&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;github.event_name == &amp;#39;push&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/checkout@v2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Build image&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;docker build . --file Dockerfile --tag $IMAGE_NAME&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Log into GitHub Container Registry&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# `read:packages`と`write:packages`の権限を持つPAT(個人アクセストークン)をSecretに`CR_PAT`として登録しておく&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# PATの作成手順 : https://docs.github.com/ja/free-pro-team@latest/github/authenticating-to-github/creating-a-personal-access-token&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;echo &amp;#34;${{ secrets.CR_PAT }}&amp;#34; | docker login https://ghcr.io -u ${{ github.actor }} --password-stdin&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Push image to GitHub Container Registry&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="sd"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; # &amp;lt;GitHubアカウント&amp;gt;が自動で選択される
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; IMAGE_ID=ghcr.io/${{ github.repository_owner }}/$IMAGE_NAME
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; IMAGE_ID=$(echo $IMAGE_ID | tr &amp;#39;[A-Z]&amp;#39; &amp;#39;[a-z]&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; VERSION=$(echo &amp;#34;${{ github.ref }}&amp;#34; | sed -e &amp;#39;s,.*/\(.*\),\1,&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; # git tagの値を&amp;lt;タグ&amp;gt;として付与
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; [[ &amp;#34;${{ github.ref }}&amp;#34; == &amp;#34;refs/tags/&amp;#34;* ]] &amp;amp;&amp;amp; VERSION=$(echo $VERSION | sed -e &amp;#39;s/^v//&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; # masterブランチへのcommitでトリガーされている場合はlatestを&amp;lt;タグ&amp;gt;として使う
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; [ &amp;#34;$VERSION&amp;#34; == &amp;#34;master&amp;#34; ] &amp;amp;&amp;amp; VERSION=latest
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; echo IMAGE_ID=$IMAGE_ID
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; echo VERSION=$VERSION
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; docker tag $IMAGE_NAME $IMAGE_ID:$VERSION
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; docker push $IMAGE_ID:$VERSION&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/uzimihsr/echo-image/blob/master/.github/workflows/docker-publish.yml" target="_blank" rel="noopener"
 &gt;https://github.com/uzimihsr/echo-image/blob/master/.github/workflows/docker-publish.yml&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;docker-publish.yml&lt;/code&gt;の編集が終わったら, &lt;strong&gt;Start commit&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Commit new file&lt;/strong&gt;と進み&lt;code&gt;workflow&lt;/code&gt;を作成する.&lt;br&gt;
&lt;img alt="workflowの設定" class="gallery-image" data-flex-basis="384px" data-flex-grow="160" height="1800" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc07.png" srcset="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc07_hu_e6c2cf4a0d6effd7.png 800w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc07_hu_26c35773237d70c9.png 1600w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc07_hu_dc4240e8fb5938a2.png 2400w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc07.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;次にこの&lt;code&gt;workflow&lt;/code&gt;で&lt;code&gt;GitHub Container Registry&lt;/code&gt;の認証を行うための&lt;code&gt;Secrets&lt;/code&gt;の設定をする.&lt;/p&gt;
&lt;p&gt;リポジトリの&lt;strong&gt;Settings&lt;/strong&gt;タブを開き, &lt;strong&gt;New sectet&lt;/strong&gt;をクリック.&lt;br&gt;
&lt;img alt="Secretの設定画面" class="gallery-image" data-flex-basis="583px" data-flex-grow="243" height="1185" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc08.png" srcset="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc08_hu_e7236f9bbef55dea.png 800w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc08_hu_7c887437fa8afc2d.png 1600w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc08_hu_27668e2eafa3d38e.png 2400w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc08.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Secret&lt;/code&gt;の作成画面では&lt;code&gt;Name&lt;/code&gt;を&lt;strong&gt;CR_PAT&lt;/strong&gt;(&lt;code&gt;docker-publish.yml&lt;/code&gt;内で参照している名前)に設定し, &lt;code&gt;Value&lt;/code&gt;には先程作成した&lt;code&gt;PAT&lt;/code&gt;を貼り付けて&lt;strong&gt;Add secret&lt;/strong&gt;をクリック.&lt;br&gt;
&lt;img alt="Secretの作成" class="gallery-image" data-flex-basis="496px" data-flex-grow="207" height="1391" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc09.png" srcset="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc09_hu_a368b0937a3ff05d.png 800w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc09_hu_d010609a960fb736.png 1600w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc09_hu_5aed707a68af792e.png 2400w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc09.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Secret&lt;/code&gt;が作成された.&lt;br&gt;
&lt;img alt="作成されたSecret" class="gallery-image" data-flex-basis="529px" data-flex-grow="220" height="1306" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc10.png" srcset="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc10_hu_abb9eec75c07a432.png 800w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc10_hu_830b37a653833529.png 1600w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc10_hu_24f7b6b99772a36.png 2400w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc10.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Secret&lt;/code&gt;を作成した状態でリポジトリの&lt;strong&gt;Actions&lt;/strong&gt;タブを開くと,&lt;br&gt;
先程の&lt;code&gt;docker-publish.yml&lt;/code&gt;作成時のcommitで起動した&lt;code&gt;workflow&lt;/code&gt;が失敗している.&lt;br&gt;
(&lt;strong&gt;CR_PAT&lt;/strong&gt; の&lt;code&gt;Secret&lt;/code&gt;を作る前に実行されたため, 認証部分でコケている)&lt;br&gt;
&lt;strong&gt;Re-run all jobs&lt;/strong&gt;から再度&lt;code&gt;workflow&lt;/code&gt;を実行してみる.&lt;br&gt;
&lt;img alt="リトライする" class="gallery-image" data-flex-basis="384px" data-flex-grow="160" height="1800" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc11.png" srcset="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc11_hu_f5ea0a40df25e8b2.png 800w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc11_hu_751ef6d8b6fd98ae.png 1600w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc11_hu_477bd2cfe00c3119.png 2400w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc11.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;今度は&lt;strong&gt;CR_PAT&lt;/strong&gt;が作成済みなので&lt;code&gt;workflow&lt;/code&gt;が正常に終了し, &lt;code&gt;image&lt;/code&gt;が&lt;strong&gt;ghcr.io/uzimihsr/echo:latest&lt;/strong&gt;にpushされた.&lt;br&gt;
&lt;img alt="できた" class="gallery-image" data-flex-basis="384px" data-flex-grow="160" height="1800" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc12.png" srcset="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc12_hu_3946aa5c306b8032.png 800w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc12_hu_a10831247641480c.png 1600w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc12_hu_7697cca6562e4093.png 2400w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc12.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;再度&lt;code&gt;GitHub Package&lt;/code&gt;の画面&lt;br&gt;
&lt;a class="link" href="https://github.com/users/uzimihsr/packages/container/package/echo" target="_blank" rel="noopener"
 &gt;https://github.com/users/uzimihsr/packages/container/package/echo&lt;/a&gt;&lt;br&gt;
を開くと, 確かに&lt;strong&gt;Last published&lt;/strong&gt;が更新されている.&lt;br&gt;
&lt;img alt="publishされたimage" class="gallery-image" data-flex-basis="571px" data-flex-grow="238" height="1209" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc13.png" srcset="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc13_hu_23f21a8e2bc40dc4.png 800w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc13_hu_df1af8da25416d7b.png 1600w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc13_hu_28b2c61784855a70.png 2400w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc13.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;以上で&lt;code&gt;GitHub Actions&lt;/code&gt;を使って&lt;code&gt;image&lt;/code&gt;を&lt;code&gt;GitHub Container Registry&lt;/code&gt;にpushする設定ができたので, 試しに&lt;code&gt;image&lt;/code&gt;を更新してみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# masterからhogeブランチを切る&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git checkout master
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git pull origin master
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git checkout -b hoge
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Dockerfileを修正&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim Dockerfile
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat Dockerfile
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;FROM busybox
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ENTRYPOINT &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;echo&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;CMD &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;good morning!&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# CMDを変更した&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# commitしてhogeブランチをpush&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git add ./Dockerfile
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git commit -m &lt;span class="s2"&gt;&amp;#34;fixed Dockerfile: CMD&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git push origin hoge&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;Dockerfile&lt;/code&gt;の修正commitを積んだ&lt;strong&gt;hoge&lt;/strong&gt;ブランチがpushされた状態でPR(&lt;strong&gt;master&lt;/strong&gt; &amp;lt;- &lt;strong&gt;hoge&lt;/strong&gt;)を作成すると, PRにトリガーされた&lt;code&gt;workflow&lt;/code&gt;が実行される.&lt;br&gt;
&lt;strong&gt;test&lt;/strong&gt;の&lt;code&gt;job&lt;/code&gt;のみが実行され&lt;strong&gt;push&lt;/strong&gt;の&lt;code&gt;job&lt;/code&gt;がスキップされているが, これは今回作成した&lt;code&gt;docker-publish.yml&lt;/code&gt;で&lt;code&gt;GitHub event&lt;/code&gt;がpushの場合にのみ実行するよう設定しているため.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;if&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;github.event_name == &amp;#39;push&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img alt="PRでの動作" class="gallery-image" data-flex-basis="384px" data-flex-grow="160" height="1800" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc14.png" srcset="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc14_hu_7a531a42f394c9db.png 800w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc14_hu_6622e2408bec447a.png 1600w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc14_hu_623a0369788e63f9.png 2400w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc14.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;このPRをmergeすると今度は&lt;strong&gt;master&lt;/strong&gt;ブランチへのpushが行われるので, それにトリガーされた&lt;code&gt;workflow&lt;/code&gt;で&lt;strong&gt;test&lt;/strong&gt;と&lt;strong&gt;push&lt;/strong&gt;の&lt;code&gt;job&lt;/code&gt;が実行される.&lt;br&gt;
以降の&lt;code&gt;image&lt;/code&gt;がpushされるまでの流れは先程試した流れと同じで, &lt;strong&gt;latest&lt;/strong&gt;タグの&lt;code&gt;image&lt;/code&gt;がpushされる.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;latest&lt;/strong&gt;タグだけでは&lt;code&gt;image&lt;/code&gt;のバージョン管理が不便なので,&lt;br&gt;
最新版の&lt;code&gt;image&lt;/code&gt;にバージョンタグを付与してみる.&lt;br&gt;
やり方としては最新のcommitにgit tagをつけてpushするだけ.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# masterブランチで作業&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git checkout master
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git pull origin master
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# masterブランチの最新のcommitにvから始まるtagをつけてpushする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git tag -a v0.0.1 -m &lt;span class="s2"&gt;&amp;#34;hogehoge&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git push origin v0.0.1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;するとtagのpushにトリガーされて&lt;code&gt;workflow&lt;/code&gt;が実行される.&lt;br&gt;
今度はtagで指定したvからはじまる文字列が&lt;code&gt;image&lt;/code&gt;のタグとして付与されていることがわかる.&lt;br&gt;
&lt;img alt="tagをつけたpush" class="gallery-image" data-flex-basis="384px" data-flex-grow="160" height="1800" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc15.png" srcset="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc15_hu_9b346fc2dd71f72e.png 800w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc15_hu_9667da8e86d65555.png 1600w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc15_hu_8706d61a722d7a2.png 2400w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc15.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;再度&lt;code&gt;Packages&lt;/code&gt;の画面を開くと確かにgit tagで指定した&lt;strong&gt;0.0.1&lt;/strong&gt;の&lt;code&gt;image&lt;/code&gt;がpushされている.&lt;br&gt;
&lt;img alt="タグがついてる" class="gallery-image" data-flex-basis="384px" data-flex-grow="160" height="1800" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc16.png" srcset="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc16_hu_f2e6cc8806ae809e.png 800w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc16_hu_1800373fce6d4d72.png 1600w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc16_hu_3ed5024d5defd1f.png 2400w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc16.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;今回はコマンドラインでtagをつけたけど, UIからreleaseを作っても同様に&lt;code&gt;image&lt;/code&gt;のpushができる.&lt;br&gt;
&lt;img alt="UIから作成したrelease" class="gallery-image" data-flex-basis="448px" data-flex-grow="186" height="1541" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc17.png" srcset="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc17_hu_6e0baaddd5798c32.png 800w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc17_hu_856c34fa84c1e2a1.png 1600w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc17_hu_6363764da79e7f26.png 2400w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sc17.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;最後に&lt;code&gt;image&lt;/code&gt;の動作確認を行う.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 動作確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run --rm ghcr.io/uzimihsr/echo:0.0.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;good morning! &lt;span class="c1"&gt;# CMDの変更が反映されている&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;やったぜ.&lt;br&gt;
&lt;code&gt;GitHub Actions&lt;/code&gt;を使って&lt;code&gt;GitHub Container Registry&lt;/code&gt;に&lt;code&gt;image&lt;/code&gt;をタグ付けしてpushできるようになった.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;GitHub&lt;/code&gt;リポジトリ上の&lt;code&gt;Dockerfile&lt;/code&gt;から&lt;code&gt;image&lt;/code&gt;を作れるようになった.&lt;br&gt;
&lt;code&gt;GitHub Actions&lt;/code&gt;を使うのも初めてだったので, 練習にもなってよかった.&lt;br&gt;
&lt;code&gt;Docker Hub&lt;/code&gt;が無料プランだといろいろ制限が厳しくなってきてるので&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;, (今のところは無料の)&lt;code&gt;GitHub Container Registry&lt;/code&gt;に乗り換えていこうと思う.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="おもちゃで遊ぶねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sotochan_hu_87ee12f27ed8cb40.jpg 800w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sotochan_hu_714d013c8ba201f5.jpg 1600w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sotochan_hu_21ac47cb545bb361.jpg 2400w, https://blog.uzimihsr.com/post/2020-10-11-github-action-publish-docker-image-ghcr/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a class="link" href="https://docs.github.com/ja/free-pro-team@latest/github/authenticating-to-github/creating-a-personal-access-token" target="_blank" rel="noopener"
 &gt;https://docs.github.com/ja/free-pro-team@latest/github/authenticating-to-github/creating-a-personal-access-token&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;a class="link" href="https://www.docker.com/pricing/resource-consumption-updates" target="_blank" rel="noopener"
 &gt;https://www.docker.com/pricing/resource-consumption-updates&lt;/a&gt;&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>9月のそとちゃんまとめ(2020)</title><link>https://blog.uzimihsr.com/post/2020-10-07-sotochan/</link><pubDate>Wed, 07 Oct 2020 22:26:28 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-10-07-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-10-07-sotochan/sotochan04.jpg" alt="Featured image of post 9月のそとちゃんまとめ(2020)" /&gt;&lt;h2 id="新居"&gt;新居
&lt;/h2&gt;&lt;p&gt;9月のそとちゃんは環境が変わって大変だった.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%8a%e3%81%b2%e3%81%a3%e3%81%93%e3%81%97" &gt;おひっこし&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%ad%e3%81%9a%e3%81%bf%e3%81%ae%e3%81%8a%e3%82%82%e3%81%a1%e3%82%83" &gt;ねずみのおもちゃ&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="おひっこし"&gt;おひっこし
&lt;/h3&gt;&lt;p&gt;いろいろ事情があって, 9月に引っ越しをした.&lt;/p&gt;
&lt;p&gt;そとちゃんはうちに来る前は保護主さんのところで暮らしていたので, たぶん人間と一緒に引っ越すのは初めて.&lt;/p&gt;
&lt;p&gt;俺はもちろんねこと引っ越すのが初めてなので, いろいろ大変だった.&lt;/p&gt;
&lt;p&gt;まずは普段家に無いサイズのダンボールにそとちゃん大興奮.&lt;br&gt;
引っ越し用のダンボールを組み立てるたびに中に入って出てこないので, 荷物を詰めるのにめっちゃ時間がかかった&amp;hellip;&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;勝手にダンボール入って出られなくなってる &lt;a href="https://t.co/TEUyKIQqOW"&gt;pic.twitter.com/TEUyKIQqOW&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1300814347699023872?ref_src=twsrc%5Etfw"&gt;September 1, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;荷物詰めが終わったら終わったで, 積み上げたダンボールで大はしゃぎ.&lt;br&gt;
やっぱり猫はダンボール好きなんすね&amp;hellip;&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ダンボールの王 &lt;a href="https://t.co/3hMV5pcpIs"&gt;pic.twitter.com/3hMV5pcpIs&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1302471852674019328?ref_src=twsrc%5Etfw"&gt;September 6, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;今回頼んだ引っ越し業者は猫は一緒に運べなかったので, そとちゃんは荷物と別に車で移動.&lt;/p&gt;
&lt;p&gt;忙しすぎて写真を撮り忘れちゃったけど, 移動中はキャリーケースの中で不安そうに鳴いててちょっとかわいそうだった.😭&lt;/p&gt;
&lt;p&gt;&lt;img alt="そとちゃん" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="2304" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-10-07-sotochan/sotochan01.jpg" srcset="https://blog.uzimihsr.com/post/2020-10-07-sotochan/sotochan01_hu_13c0205479a6d9e2.jpg 800w, https://blog.uzimihsr.com/post/2020-10-07-sotochan/sotochan01_hu_e432d865cb9e6f72.jpg 1600w, https://blog.uzimihsr.com/post/2020-10-07-sotochan/sotochan01_hu_8d6e3c3a9eee2ff4.jpg 2400w, https://blog.uzimihsr.com/post/2020-10-07-sotochan/sotochan01.jpg 4096w" width="4096"&gt;&lt;/p&gt;
&lt;p&gt;でも新居は1日くらい探検したらすぐに慣れてくれて, すぐに&lt;strong&gt;そとちゃんの家&lt;/strong&gt;になったみたい.&lt;br&gt;
特に新しく買ったソファと仕事用の机がお気に入り.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ゲーミングキャット &lt;a href="https://t.co/HMpT2Kwzw0"&gt;pic.twitter.com/HMpT2Kwzw0&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1309719802055856128?ref_src=twsrc%5Etfw"&gt;September 26, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;仕事監視ねこ &lt;a href="https://t.co/Ue1QjyWi8v"&gt;pic.twitter.com/Ue1QjyWi8v&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1308650350933471233?ref_src=twsrc%5Etfw"&gt;September 23, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;h3 id="ねずみのおもちゃ"&gt;ねずみのおもちゃ
&lt;/h3&gt;&lt;p&gt;また, だいぶ前に失くしたと思っていたねずみのおもちゃが引っ越しのおかげで見つかった.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;お気に入りのねずみのおもちゃがなくていじけてる&lt;br&gt;(片付けたんじゃなくてそとちゃんが失くした) &lt;a href="https://t.co/tt1P6N25zy"&gt;pic.twitter.com/tt1P6N25zy&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1267307986998849536?ref_src=twsrc%5Etfw"&gt;June 1, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;&lt;img alt="ねずみのおもちゃ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-10-07-sotochan/sotochan02.jpg" srcset="https://blog.uzimihsr.com/post/2020-10-07-sotochan/sotochan02_hu_a64cfb307c473440.jpg 800w, https://blog.uzimihsr.com/post/2020-10-07-sotochan/sotochan02_hu_752b34d1acee224.jpg 1600w, https://blog.uzimihsr.com/post/2020-10-07-sotochan/sotochan02_hu_5e1434692261c8b7.jpg 2400w, https://blog.uzimihsr.com/post/2020-10-07-sotochan/sotochan02.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;なんと冷蔵庫の裏側, 壁との間に入っていた&amp;hellip;&lt;br&gt;
ねこが入れる隙間なんてなかったのに, どうやったのか謎すぎる&amp;hellip;🤔&lt;/p&gt;
&lt;p&gt;このねずみのおもちゃは&lt;a class="link" href="https://www.doggyman.com/?p=showroom&amp;amp;id=1153&amp;amp;new=1" target="_blank" rel="noopener"
 &gt;またたび&lt;/a&gt;のおまけに付いてきたやつで,&lt;br&gt;
そとちゃんの一番のお気に入り.&lt;/p&gt;
&lt;p&gt;失くしたときにあまりにも落ち込んでてかわいそうだったから同じメーカーの似た&lt;a class="link" href="https://www.doggyman.com/?p=showroom&amp;amp;id=622&amp;amp;new=1" target="_blank" rel="noopener"
 &gt;おもちゃ&lt;/a&gt;を買ってあげたんだけど, おまけのねずみほどには食いつかなかった.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ペットショップ行けたのでバチクソおもちゃ買ってあげた(失くしたねずみのおもちゃ含む) &lt;a href="https://t.co/k4CZJNWD8r"&gt;pic.twitter.com/k4CZJNWD8r&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1267819167975002113?ref_src=twsrc%5Etfw"&gt;June 2, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;このおもちゃ自体にまたたびの匂いがついてるとかそんなことはなくて, 売り物のおもちゃよりも色合いも地味.&lt;br&gt;
だけど一緒に出しても絶対おまけのおもちゃの方で遊ぶ. なぜ&amp;hellip;?&lt;/p&gt;
&lt;p&gt;&lt;img alt="ねずみのおもちゃ(右が売り物のおもちゃ)" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-10-07-sotochan/sotochan03.jpg" srcset="https://blog.uzimihsr.com/post/2020-10-07-sotochan/sotochan03_hu_6070d2ff3c34e39.jpg 800w, https://blog.uzimihsr.com/post/2020-10-07-sotochan/sotochan03_hu_e542962469f7961f.jpg 1600w, https://blog.uzimihsr.com/post/2020-10-07-sotochan/sotochan03_hu_249b7d138d96f35.jpg 2400w, https://blog.uzimihsr.com/post/2020-10-07-sotochan/sotochan03.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;きっとねこには人間ごときにはわからないこだわりがあるんだろう&amp;hellip;&lt;/p&gt;
&lt;p&gt;ちなみに遊び方はちょっと変で,&lt;br&gt;
&lt;code&gt;ねずみを自分で咥えて放り投げる&lt;/code&gt; -&amp;gt; &lt;code&gt;落下点にダッシュ&lt;/code&gt; -&amp;gt; &lt;code&gt;落ちたねずみにねこパンチ&lt;/code&gt; -&amp;gt; &lt;code&gt;再度咥えて放り投げる&lt;/code&gt;&amp;hellip;&lt;br&gt;
をねずみが手の届かないところに入るまで延々と繰り返している.&lt;br&gt;
見ていてかなり面白いので, 今度動画を撮ってみたい.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ねずみ発見 &lt;a href="https://t.co/DYX4u7wTMP"&gt;pic.twitter.com/DYX4u7wTMP&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1311155999022088193?ref_src=twsrc%5Etfw"&gt;September 30, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;ひとりで楽しそうに遊んでくれるのでしもべとしては楽なんだけど,&lt;br&gt;
すぐに失くすし, &lt;a class="link" href="https://uzimihsr.github.io/post/2020-08-13-sotochan/" target="_blank" rel="noopener"
 &gt;誤飲の前科&lt;/a&gt;もあるので頃合いを見計らって片付けるようにしている.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ねずみのおもちゃ出しっぱなしにしたら案の定すぐ失くしてふてくされてる &lt;a href="https://t.co/BJnfvgyx8y"&gt;pic.twitter.com/BJnfvgyx8y&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1311112190439469056?ref_src=twsrc%5Etfw"&gt;September 30, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;片付けるとぷーぷー文句言うのがちょっとかわいい.😂&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ねずみのおもちゃを片付けられてきげんわるい &lt;a href="https://t.co/CrZbjrzkXS"&gt;pic.twitter.com/CrZbjrzkXS&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1310437029222596608?ref_src=twsrc%5Etfw"&gt;September 28, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;9月のそとちゃんは環境の変化にもすぐに対応して, 元気いっぱいだった.&lt;br&gt;
ほんとに手がかからない良い子でいつも助かる&amp;hellip;&lt;/p&gt;
&lt;p&gt;ねずみのおもちゃも見つかって, 運動不足も解消できそうでほんとに良かった.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="2人がけソファのど真ん中がお気に入りのねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-10-07-sotochan/sotochan04.jpg" srcset="https://blog.uzimihsr.com/post/2020-10-07-sotochan/sotochan04_hu_d6d9a0645b169096.jpg 800w, https://blog.uzimihsr.com/post/2020-10-07-sotochan/sotochan04_hu_506da5f783c0ba8d.jpg 1600w, https://blog.uzimihsr.com/post/2020-10-07-sotochan/sotochan04_hu_45d5acb62e50b03.jpg 2400w, https://blog.uzimihsr.com/post/2020-10-07-sotochan/sotochan04.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>client-goを使ってKubernetesのPodをクラスタ外からwatchする</title><link>https://blog.uzimihsr.com/post/2020-09-30-kubernetes-client-go-watch-pods/</link><pubDate>Wed, 30 Sep 2020 10:23:13 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-09-30-kubernetes-client-go-watch-pods/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-09-30-kubernetes-client-go-watch-pods/sotochan.jpg" alt="Featured image of post client-goを使ってKubernetesのPodをクラスタ外からwatchする" /&gt;&lt;h2 id="podを見張りたい"&gt;Podを見張りたい
&lt;/h2&gt;&lt;p&gt;Go用のKubernetesクライアントを使ってクラスタ内のPodの様子を見張るやつを作った.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Kubernetes&lt;/code&gt;クラスタ内の&lt;code&gt;Pod&lt;/code&gt;をwatchし, &lt;code&gt;Pod&lt;/code&gt;の状態変化に応じて任意の処理を行う&lt;code&gt;observer.go&lt;/code&gt;を作った&lt;/li&gt;
&lt;li&gt;&lt;code&gt;RetryWatcher&lt;/code&gt;を使う方法と&lt;code&gt;Informer&lt;/code&gt;を使う方法を試したが, &lt;code&gt;Informer&lt;/code&gt;を使うほうがよさそう&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="gif" class="gallery-image" data-flex-basis="683px" data-flex-grow="284" height="330" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-09-30-kubernetes-client-go-watch-pods/sc01.gif" srcset="https://blog.uzimihsr.com/post/2020-09-30-kubernetes-client-go-watch-pods/sc01_hu_a391925f57e29c05.gif 800w, https://blog.uzimihsr.com/post/2020-09-30-kubernetes-client-go-watch-pods/sc01.gif 940w" width="940"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/uzimihsr/kubernetes-pod-observer/tree/144aec7d3e38562bd53dae2a5cf5052b086a7533" target="_blank" rel="noopener"
 &gt;kubernetes-pod-observer&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Mojave 10.14&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/golang/go" target="_blank" rel="noopener"
 &gt;go&lt;/a&gt; version go1.14.6 darwin/amd64&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/kubernetes/client-go" target="_blank" rel="noopener"
 &gt;kubernetes/client-go&lt;/a&gt; v0.19.2&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Kubernetes&lt;/code&gt;クラスタ v1.15.12-gke.20&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#retrywatcher%e3%81%a7watch%e3%81%99%e3%82%8b" &gt;RetryWatcherでwatchする&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#informer%e3%82%92%e4%bd%bf%e3%81%a3%e3%81%a6%e3%81%bf%e3%82%8b" &gt;Informerを使ってみる&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="retrywatcherでwatchする"&gt;RetryWatcherでwatchする
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Pod&lt;/code&gt;をListするAPI&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;で&lt;code&gt;watch&lt;/code&gt;オプションを指定すると, &lt;code&gt;Pod&lt;/code&gt;の情報(&lt;code&gt;event&lt;/code&gt;)がリアルタイムで流れてくる.&lt;br&gt;
この&lt;code&gt;event&lt;/code&gt;を見ることで, &lt;code&gt;Pod&lt;/code&gt;が作成/更新/削除されたタイミングを把握することができる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# PodのList APIにwatchオプションをつけて実行(kubectlは内部でAPIを叩いている)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -w
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# この状態で別ターミナルからJobを実行して削除&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create job busybox --image&lt;span class="o"&gt;=&lt;/span&gt;busybox -- /bin/sh -c &lt;span class="s1"&gt;&amp;#39;echo hello&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl delete job busybox
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# kubectl get pods -w の出力&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;busybox-8kzpz 0/1 Pending &lt;span class="m"&gt;0&lt;/span&gt; 1s &lt;span class="c1"&gt;# Pod作成予約&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;busybox-8kzpz 0/1 Pending &lt;span class="m"&gt;0&lt;/span&gt; 1s &lt;span class="c1"&gt;# Pod作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;busybox-8kzpz 0/1 ContainerCreating &lt;span class="m"&gt;0&lt;/span&gt; 1s &lt;span class="c1"&gt;# コンテナ起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;busybox-8kzpz 0/1 Completed &lt;span class="m"&gt;0&lt;/span&gt; 3s &lt;span class="c1"&gt;# Pod(コンテナ)完了&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;busybox-8kzpz 0/1 Terminating &lt;span class="m"&gt;0&lt;/span&gt; 12s &lt;span class="c1"&gt;# 削除直前の状態&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;busybox-8kzpz 0/1 Terminating &lt;span class="m"&gt;0&lt;/span&gt; 12s &lt;span class="c1"&gt;# Pod削除完了&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;今回は&lt;code&gt;Go&lt;/code&gt;純正の&lt;code&gt;Kubernetes&lt;/code&gt;クライアントライブラリ&lt;a class="link" href="https://github.com/kubernetes/client-go" target="_blank" rel="noopener"
 &gt;client-go&lt;/a&gt;を使い,&lt;br&gt;
&lt;code&gt;watch&lt;/code&gt;用のAPIを利用して&lt;code&gt;Pod&lt;/code&gt;をひたすら見張りつづけて状態変化に応じた処理を行うようなしくみを作ってみた.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 作業用ディレクトリとgo.modの作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;pwd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/path/to/workspace
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mkdir kubernetes-pod-observer &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; kubernetes-pod-observer
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go mod init github.com/uzimihsr/kubernetes-pod-observer
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ touch observer.go&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;observer.go&lt;/code&gt;はこんな感じで作った.&lt;br&gt;
&lt;code&gt;Kubernetes API&lt;/code&gt;クライアントの認証情報は&lt;code&gt;kubeconfig&lt;/code&gt;(~/.kube/config)を参照して,&lt;br&gt;
&lt;code&gt;Pod&lt;/code&gt;を&lt;code&gt;watch&lt;/code&gt;し, &lt;code&gt;watch&lt;/code&gt;した&lt;code&gt;event&lt;/code&gt;の内容を元に処理を分けるような形になっている.&lt;br&gt;
&lt;code&gt;kubeconfig&lt;/code&gt;読み込みからクライアント立ち上げまでの流れは公式のサンプルコード&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;を参考にした.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/ba86023e96fea6b451339418fa0a3630.js"&gt;&lt;/script&gt;
&lt;p&gt;少しこだわったのは&lt;code&gt;Pod&lt;/code&gt;を&lt;code&gt;watch&lt;/code&gt;する際に&lt;code&gt;RetryWatcher&lt;/code&gt;&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;を使用しているところ.&lt;br&gt;
普通に&lt;code&gt;watch&lt;/code&gt;用のAPIを叩く場合一定時間が経つとAPIサーバー側が接続を切ってしまう仕様なのだが&lt;sup id="fnref:4"&gt;&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref"&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;sup id="fnref:5"&gt;&lt;a href="#fn:5" class="footnote-ref" role="doc-noteref"&gt;5&lt;/a&gt;&lt;/sup&gt;,&lt;br&gt;
これを使うと&lt;code&gt;watch&lt;/code&gt;の接続が切れたときにクライアント側で勝手に再接続してくれる.&lt;/p&gt;
&lt;p&gt;また, &lt;code&gt;watch&lt;/code&gt;を再開するとすでに観測したことのある&lt;code&gt;event&lt;/code&gt;も拾ってしまうので,&lt;br&gt;
&lt;code&gt;event&lt;/code&gt;に紐づく&lt;code&gt;ResourceVersion&lt;/code&gt;を参照して既に見たことのある&lt;code&gt;event&lt;/code&gt;は無視するようにした.&lt;/p&gt;
&lt;p&gt;実際に&lt;code&gt;observer.go&lt;/code&gt;が動いている状態で, &lt;code&gt;Pod&lt;/code&gt;を手で作ったり, &lt;code&gt;Job&lt;/code&gt;から作成してみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# observer.goを実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go run observer.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 以下は別のターミナルから実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podを作成(1)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl run busybox --image&lt;span class="o"&gt;=&lt;/span&gt;busybox --restart&lt;span class="o"&gt;=&lt;/span&gt;Never -- /bin/sh -c &lt;span class="s1"&gt;&amp;#39;echo hello&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podを削除(2)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl delete pod busybox
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Job経由でPodを作成(3)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create job busybox --image&lt;span class="o"&gt;=&lt;/span&gt;busybox -- /bin/sh -c &lt;span class="s1"&gt;&amp;#39;echo hello&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Jobを削除(4)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl delete job busybox&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;このときの&lt;code&gt;observer.go&lt;/code&gt;の出力は次のようになる.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# observer.goの出力

# (1)
ResourceVersion: 60844265
the Pod &amp;lt; busybox &amp;gt; has been created.
ResourceVersion: 60844266
the Pod &amp;lt; busybox &amp;gt;&amp;#39;s phase is &amp;lt; Pending &amp;gt;.
ResourceVersion: 60844267
the Pod &amp;lt; busybox &amp;gt;&amp;#39;s phase is &amp;lt; Pending &amp;gt;.
ResourceVersion: 60844271
the Pod &amp;lt; busybox &amp;gt;&amp;#39;s phase is &amp;lt; Succeeded &amp;gt;.

# (2)
ResourceVersion: 60844359
the Pod &amp;lt; busybox &amp;gt;&amp;#39;s phase is &amp;lt; Succeeded &amp;gt;.
ResourceVersion: 60844360
the Pod &amp;lt; busybox &amp;gt; has been deleted.

# (3)
ResourceVersion: 60844936
the Pod &amp;lt; busybox-dx4f8 &amp;gt; has been created by the Job &amp;lt; busybox &amp;gt;.
ResourceVersion: 60844937
the Pod &amp;lt; busybox-dx4f8 &amp;gt;&amp;#39;s phase is &amp;lt; Pending &amp;gt;.
ResourceVersion: 60844940
the Pod &amp;lt; busybox-dx4f8 &amp;gt;&amp;#39;s phase is &amp;lt; Pending &amp;gt;.
ResourceVersion: 60844948
the Pod &amp;lt; busybox-dx4f8 &amp;gt;&amp;#39;s phase is &amp;lt; Succeeded &amp;gt;.

# (4)
ResourceVersion: 60845063
the Pod &amp;lt; busybox-dx4f8 &amp;gt;&amp;#39;s phase is &amp;lt; Succeeded &amp;gt;.
ResourceVersion: 60845064
the Pod &amp;lt; busybox-dx4f8 &amp;gt; has been deleted.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;こんな感じで, &lt;code&gt;watch&lt;/code&gt;した&lt;code&gt;Pod&lt;/code&gt;の状態に応じた処理を行うことができた.&lt;/p&gt;
&lt;h3 id="informerを使ってみる"&gt;Informerを使ってみる
&lt;/h3&gt;&lt;p&gt;&amp;hellip;実は同じようなことをする公式のサンプルコード&lt;sup id="fnref:6"&gt;&lt;a href="#fn:6" class="footnote-ref" role="doc-noteref"&gt;6&lt;/a&gt;&lt;/sup&gt;がある,&lt;br&gt;
こっちは&lt;code&gt;event&lt;/code&gt;を&lt;code&gt;watch&lt;/code&gt;する部分で&lt;code&gt;RetryWatcher&lt;/code&gt;の代わりに, &lt;code&gt;Informer&lt;/code&gt;&lt;sup id="fnref:7"&gt;&lt;a href="#fn:7" class="footnote-ref" role="doc-noteref"&gt;7&lt;/a&gt;&lt;/sup&gt;というやつを使っている.&lt;br&gt;
&lt;code&gt;Informer&lt;/code&gt;は&lt;code&gt;watch&lt;/code&gt;に関する処理をさらに抽象化したものらしくて, &lt;code&gt;watch&lt;/code&gt;が途切れたときに再度接続を復活させたり,&lt;br&gt;
&lt;code&gt;watch&lt;/code&gt;した&lt;code&gt;event&lt;/code&gt;の種類で処理を分けたりと&lt;code&gt;watch&lt;/code&gt;対象のリソース(&lt;code&gt;Pod&lt;/code&gt;)の状態変化に応じた処理がしやすくなっている. らしい.&lt;br&gt;
(&lt;code&gt;observer.go&lt;/code&gt;では自分で記述していたような処理も内部でやってくれている)&lt;/p&gt;
&lt;p&gt;サンプルコードを真似て&lt;code&gt;observer.go&lt;/code&gt;を書き直してみる.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/21972a6ca3cb66c0f4ff366f8407e545.js"&gt;&lt;/script&gt;
&lt;p&gt;ポイントは&lt;code&gt;Informer&lt;/code&gt;の作成時に&lt;code&gt;event&lt;/code&gt;のType(&lt;code&gt;ADDED&lt;/code&gt;, &lt;code&gt;MODIFIED&lt;/code&gt;, &lt;code&gt;DELETED&lt;/code&gt;)に応じた処理をそれぞれ&lt;code&gt;AddFunc&lt;/code&gt;, &lt;code&gt;UpdateFunc&lt;/code&gt;, &lt;code&gt;DeleteFunc&lt;/code&gt;で設定するところ.&lt;br&gt;
こうしておくことで, 対象のリソース(&lt;code&gt;Pod&lt;/code&gt;)の状態が変化したときにそれに応じた処理を設定することができる.&lt;/p&gt;
&lt;p&gt;実際に動かしてみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# observer.goを実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go run observer.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 以下は別のターミナルから実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Job経由でPodを作成(1)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create job busybox --image&lt;span class="o"&gt;=&lt;/span&gt;busybox -- /bin/sh -c &lt;span class="s1"&gt;&amp;#39;echo hello&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Jobを削除(2)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl delete job busybox&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# observer.goの出力&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# (1)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Pod &amp;lt;busybox-m5cd6&amp;gt; was added by Job &amp;lt;busybox&amp;gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Pod &amp;lt;busybox-m5cd6&amp;gt; is Pending phase.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Pod &amp;lt;busybox-m5cd6&amp;gt; is Pending phase.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Pod &amp;lt;busybox-m5cd6&amp;gt; is Succeeded phase. previous: Pending phase
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# (2)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Pod &amp;lt;busybox-m5cd6&amp;gt; is Succeeded phase.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Pod &amp;lt;busybox-m5cd6&amp;gt; was deleted.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;img alt="gif" class="gallery-image" data-flex-basis="683px" data-flex-grow="284" height="330" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-09-30-kubernetes-client-go-watch-pods/sc01.gif" srcset="https://blog.uzimihsr.com/post/2020-09-30-kubernetes-client-go-watch-pods/sc01_hu_a391925f57e29c05.gif 800w, https://blog.uzimihsr.com/post/2020-09-30-kubernetes-client-go-watch-pods/sc01.gif 940w" width="940"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;observer.go&lt;/code&gt;を起動した状態で&lt;code&gt;Job&lt;/code&gt;を実行し, &lt;code&gt;Pod&lt;/code&gt;の作成, 状態変化, 削除のタイミングで任意の処理を行うことができた.&lt;br&gt;
今回はデフォルト&lt;code&gt;Namespace&lt;/code&gt;の&lt;code&gt;Pod&lt;/code&gt;名を標準出力しただけだが, 頑張れば特に重要な&lt;code&gt;Namespace&lt;/code&gt;の&lt;code&gt;Pod&lt;/code&gt;については変化のタイミングで特定の相手に通知を送ったりとかもできるはず.&lt;/p&gt;
&lt;p&gt;今回は&lt;code&gt;Pod&lt;/code&gt;の状態変化を見張る部分とそれに応じた処理を1つにしてしまっているが, もちろんサンプルコード&lt;sup id="fnref1:6"&gt;&lt;a href="#fn:6" class="footnote-ref" role="doc-noteref"&gt;6&lt;/a&gt;&lt;/sup&gt;のように&lt;code&gt;AddFunc&lt;/code&gt;などでキューにデータを送り, 別の&lt;code&gt;go routine&lt;/code&gt;でキューからデータを取り出して処理することもできる. はず.&lt;br&gt;
(ここで力尽きたのでやめた)&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Kubernetes&lt;/code&gt;クラスタの外から&lt;code&gt;Pod&lt;/code&gt;を&lt;code&gt;watch&lt;/code&gt;して, その状態変化に応じた任意の処理を行うやつを作った.&lt;br&gt;
&lt;code&gt;RetryWatcher&lt;/code&gt;を使う方法と&lt;code&gt;Informer&lt;/code&gt;を使う方法の2通りを試してみたけど, &lt;code&gt;Informer&lt;/code&gt;を使うほうが&lt;code&gt;watch&lt;/code&gt;を行う部分について難しいことを考える必要がなくて楽な感じがした.&lt;br&gt;
どっちを使うべきか迷ったら&lt;code&gt;Informer&lt;/code&gt;を使うほうがおすすめ?らしい&lt;sup id="fnref:8"&gt;&lt;a href="#fn:8" class="footnote-ref" role="doc-noteref"&gt;8&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Informer&lt;/code&gt;はカスタムコントローラとかでも使われているみたいなので&lt;sup id="fnref:9"&gt;&lt;a href="#fn:9" class="footnote-ref" role="doc-noteref"&gt;9&lt;/a&gt;&lt;/sup&gt;, 時間があったらもう少し勉強してみたい.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="ソファを占拠するねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-09-30-kubernetes-client-go-watch-pods/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-09-30-kubernetes-client-go-watch-pods/sotochan_hu_eb16966d0d8d32e0.jpg 800w, https://blog.uzimihsr.com/post/2020-09-30-kubernetes-client-go-watch-pods/sotochan_hu_ee910446bca8939e.jpg 1600w, https://blog.uzimihsr.com/post/2020-09-30-kubernetes-client-go-watch-pods/sotochan_hu_1c0005ba14332140.jpg 2400w, https://blog.uzimihsr.com/post/2020-09-30-kubernetes-client-go-watch-pods/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a class="link" href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#list-pod-v1-core" target="_blank" rel="noopener"
 &gt;https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#list-pod-v1-core&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/kubernetes/client-go/tree/master/examples/out-of-cluster-client-configuration" target="_blank" rel="noopener"
 &gt;https://github.com/kubernetes/client-go/tree/master/examples/out-of-cluster-client-configuration&lt;/a&gt;&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;&lt;a class="link" href="https://pkg.go.dev/k8s.io/client-go/tools/watch#RetryWatcher" target="_blank" rel="noopener"
 &gt;https://pkg.go.dev/k8s.io/client-go/tools/watch#RetryWatcher&lt;/a&gt;&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:4"&gt;
&lt;p&gt;&lt;a class="link" href="https://kubernetes.io/docs/reference/using-api/api-concepts/#efficient-detection-of-changes" target="_blank" rel="noopener"
 &gt;https://kubernetes.io/docs/reference/using-api/api-concepts/#efficient-detection-of-changes&lt;/a&gt;&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:5"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/kubernetes/client-go/issues/623#issuecomment-506822043" target="_blank" rel="noopener"
 &gt;https://github.com/kubernetes/client-go/issues/623#issuecomment-506822043&lt;/a&gt;&amp;#160;&lt;a href="#fnref:5" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:6"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/kubernetes/client-go/tree/master/examples/workqueue" target="_blank" rel="noopener"
 &gt;https://github.com/kubernetes/client-go/tree/master/examples/workqueue&lt;/a&gt;&amp;#160;&lt;a href="#fnref:6" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&amp;#160;&lt;a href="#fnref1:6" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:7"&gt;
&lt;p&gt;&lt;a class="link" href="https://pkg.go.dev/k8s.io/client-go/tools/cache#NewInformer" target="_blank" rel="noopener"
 &gt;https://pkg.go.dev/k8s.io/client-go/tools/cache#NewInformer&lt;/a&gt;&amp;#160;&lt;a href="#fnref:7" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:8"&gt;
&lt;p&gt;&lt;a class="link" href="https://stackoverflow.com/questions/59544139/kubernetes-client-go-watch-interface-vs-cache-newinformer-vs-cache-newsharedi" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/59544139/kubernetes-client-go-watch-interface-vs-cache-newinformer-vs-cache-newsharedi&lt;/a&gt;&amp;#160;&lt;a href="#fnref:8" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:9"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/kubernetes/sample-controller/blob/master/docs/controller-client-go.md" target="_blank" rel="noopener"
 &gt;https://github.com/kubernetes/sample-controller/blob/master/docs/controller-client-go.md&lt;/a&gt;&amp;#160;&lt;a href="#fnref:9" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>GoでPrometheus用のExporterをつくる</title><link>https://blog.uzimihsr.com/post/2020-09-17-prometheus-exporter/</link><pubDate>Wed, 16 Sep 2020 22:32:00 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-09-17-prometheus-exporter/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-09-17-prometheus-exporter/sotochan.jpg" alt="Featured image of post GoでPrometheus用のExporterをつくる" /&gt;&lt;h2 id="自作exporter"&gt;自作Exporter
&lt;/h2&gt;&lt;p&gt;Prometheusでスクレイプする用のExporterを自作してみた.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Go&lt;/code&gt;の&lt;code&gt;Prometheus&lt;/code&gt;クライアント&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;を使って, 自分で設定したメトリクスを表示できる&lt;code&gt;Exporter&lt;/code&gt;を作成した&lt;/li&gt;
&lt;li&gt;作成した&lt;code&gt;Exporter&lt;/code&gt;と&lt;code&gt;Prometheus&lt;/code&gt;を&lt;code&gt;Docker&lt;/code&gt;で動かし, スクレイプできることを確認した&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="Exporter" class="gallery-image" data-flex-basis="658px" data-flex-grow="274" height="1049" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-09-17-prometheus-exporter/sc01.png" srcset="https://blog.uzimihsr.com/post/2020-09-17-prometheus-exporter/sc01_hu_c7d56a4089ca42e6.png 800w, https://blog.uzimihsr.com/post/2020-09-17-prometheus-exporter/sc01_hu_abe029cae1b0c327.png 1600w, https://blog.uzimihsr.com/post/2020-09-17-prometheus-exporter/sc01_hu_3aedd3f863c928a1.png 2400w, https://blog.uzimihsr.com/post/2020-09-17-prometheus-exporter/sc01.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/uzimihsr/example-exporter" target="_blank" rel="noopener"
 &gt;https://github.com/uzimihsr/example-exporter&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Mojave 10.14&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/golang/go" target="_blank" rel="noopener"
 &gt;go&lt;/a&gt; version go1.14.6 darwin/amd64&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/prometheus/client_golang" target="_blank" rel="noopener"
 &gt;prometheus/client_golang&lt;/a&gt; v1.7.1&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/editions/community/docker-ce-desktop-mac" target="_blank" rel="noopener"
 &gt;Docker Desktop for Mac&lt;/a&gt; 2.1.0.3
&lt;ul&gt;
&lt;li&gt;Docker version 19.03.2&lt;/li&gt;
&lt;li&gt;docker-compose version 1.24.1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#exporter%e3%81%ae%e4%bd%9c%e6%88%90" &gt;Exporterの作成&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#prometheus%e3%81%a7%e3%82%b9%e3%82%af%e3%83%ac%e3%82%a4%e3%83%97" &gt;Prometheusでスクレイプ&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="exporterの作成"&gt;Exporterの作成
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 作業用ディレクトリとgo.modの作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;pwd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/path/to/workspace
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mkdir example-exporter &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; example-exporter
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go mod init github.com/uzimihsr/example-exporter
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;go: creating new go.mod: module github.com/uzimihsr/example-exporter
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ touch main.go&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;main.go&lt;/code&gt;はこんな感じで作る.&lt;br&gt;
書き方はDocsの例&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;と&lt;code&gt;Prometheus&lt;/code&gt;クライアントのサンプルコード&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;を参考にした.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/4610ea7923274336898733c6588ef962.js"&gt;&lt;/script&gt;
&lt;p&gt;ポイントは&lt;code&gt;/metrics&lt;/code&gt;へのリクエストをハンドリングする処理と別に&lt;code&gt;go routine&lt;/code&gt;を使ってメトリクスを更新する処理を入れているところ.&lt;br&gt;
こうすることで各メトリクスが並行に更新され, リクエストが来るたびにメトリクスの最新の値を返すことができる.&lt;/p&gt;
&lt;p&gt;試しに動かしてみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# exporterの実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go run main.go&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;ブラウザで http://localhost:2112/metrics を開く.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Exporter" class="gallery-image" data-flex-basis="658px" data-flex-grow="274" height="1049" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-09-17-prometheus-exporter/sc01.png" srcset="https://blog.uzimihsr.com/post/2020-09-17-prometheus-exporter/sc01_hu_c7d56a4089ca42e6.png 800w, https://blog.uzimihsr.com/post/2020-09-17-prometheus-exporter/sc01_hu_abe029cae1b0c327.png 1600w, https://blog.uzimihsr.com/post/2020-09-17-prometheus-exporter/sc01_hu_3aedd3f863c928a1.png 2400w, https://blog.uzimihsr.com/post/2020-09-17-prometheus-exporter/sc01.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;こんな感じで&lt;code&gt;Prometheus&lt;/code&gt;が読めるフォーマットのメトリクスが表示された.&lt;br&gt;
メトリクス定義に記述したメトリクス名, 説明文, ラベルが反映されていることがわかる.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# HELP example_number Example Gauge
# TYPE example_number gauge
example_number{fuga=&amp;#34;fugafuga&amp;#34;} -0.0056473753420378525
# HELP example_total Example Counter
# TYPE example_total counter
example_total{hoge=&amp;#34;hogehoge&amp;#34;} 13
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="prometheusでスクレイプ"&gt;Prometheusでスクレイプ
&lt;/h3&gt;&lt;p&gt;せっかくなので, &lt;code&gt;Prometheus&lt;/code&gt;でスクレイプしてみる.&lt;br&gt;
今回は試しに&lt;code&gt;Docker&lt;/code&gt;上で&lt;code&gt;Prometheus&lt;/code&gt;のコンテナと今回作った &lt;strong&gt;example-exporter&lt;/strong&gt; のコンテナを同時に動かす.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;example-exporter&lt;/strong&gt; 用の&lt;code&gt;Dockerfile&lt;/code&gt;の書き方は&lt;a class="link" href="https://uzimihsr.github.io/post/2020-03-15-golang-build-image/" target="_blank" rel="noopener"
 &gt;GoアプリをDockerのscratchイメージで動かす&lt;/a&gt;を参考にする.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/7fbec7bd2acbe4ecb050f37e7f70420d.js"&gt;&lt;/script&gt;
&lt;p&gt;さらに&lt;code&gt;Prometheus&lt;/code&gt;の設定ファイル&lt;code&gt;prometheus.yml&lt;/code&gt;と,&lt;br&gt;
2つのコンテナを動かすために&lt;code&gt;docker-compose.yml&lt;/code&gt;を作成する.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/548f1a8ebae74fb84f1ee6aabed3e1f3.js"&gt;&lt;/script&gt;
&lt;script src="https://gist.github.com/uzimihsr/e08901b5093d810d68bd933149d1230b.js"&gt;&lt;/script&gt;
&lt;p&gt;この状態で&lt;code&gt;docker-compose&lt;/code&gt;で2つのコンテナを起動する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ディレクトリの状態&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ tree .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── Dockerfile
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── docker-compose.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── go.mod
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── go.sum
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── main.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── prometheus.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# docker-composeでコンテナを起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-compose up -d
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Creating network &lt;span class="s2"&gt;&amp;#34;example-exporter_default&amp;#34;&lt;/span&gt; with the default driver
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Creating example-exporter ... &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Creating prometheus ... &lt;span class="k"&gt;done&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;コンテナが起動した状態で http://localhost:9090/graph をホストのブラウザで開くと, &lt;code&gt;Prometheus&lt;/code&gt;の画面が表示される.&lt;br&gt;
無事に起動できていれば &lt;strong&gt;example-exporter&lt;/strong&gt; がスクレイプできている.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Prometheus" class="gallery-image" data-flex-basis="600px" data-flex-grow="250" height="1151" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-09-17-prometheus-exporter/sc02.png" srcset="https://blog.uzimihsr.com/post/2020-09-17-prometheus-exporter/sc02_hu_2ce340aa6191260a.png 800w, https://blog.uzimihsr.com/post/2020-09-17-prometheus-exporter/sc02_hu_4bdafae18822ed2a.png 1600w, https://blog.uzimihsr.com/post/2020-09-17-prometheus-exporter/sc02_hu_d02d86a32b594639.png 2400w, https://blog.uzimihsr.com/post/2020-09-17-prometheus-exporter/sc02.png 2878w" width="2878"&gt;&lt;/p&gt;
&lt;p&gt;試しに &lt;strong&gt;example-exporter&lt;/strong&gt; のメトリクス名でクエリを投げてみると, ちゃんと時系列の値が表示される.&lt;br&gt;
&lt;img alt="Prometheus" class="gallery-image" data-flex-basis="433px" data-flex-grow="180" height="1596" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-09-17-prometheus-exporter/sc03.png" srcset="https://blog.uzimihsr.com/post/2020-09-17-prometheus-exporter/sc03_hu_400ebedaf6b590ce.png 800w, https://blog.uzimihsr.com/post/2020-09-17-prometheus-exporter/sc03_hu_17b208eb19e85788.png 1600w, https://blog.uzimihsr.com/post/2020-09-17-prometheus-exporter/sc03_hu_4494bed62017469d.png 2400w, https://blog.uzimihsr.com/post/2020-09-17-prometheus-exporter/sc03.png 2880w" width="2880"&gt;&lt;br&gt;
&lt;img alt="Prometheus" class="gallery-image" data-flex-basis="458px" data-flex-grow="190" height="1508" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-09-17-prometheus-exporter/sc04.png" srcset="https://blog.uzimihsr.com/post/2020-09-17-prometheus-exporter/sc04_hu_6d969c8b0b2347eb.png 800w, https://blog.uzimihsr.com/post/2020-09-17-prometheus-exporter/sc04_hu_fbd8da140db8c74a.png 1600w, https://blog.uzimihsr.com/post/2020-09-17-prometheus-exporter/sc04_hu_b0f9062584ac9ba3.png 2400w, https://blog.uzimihsr.com/post/2020-09-17-prometheus-exporter/sc04.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;example_total&lt;/strong&gt; は&lt;code&gt;main.go&lt;/code&gt;で設定した通り30秒ごとに値が加算され,&lt;br&gt;
&lt;strong&gt;example_number&lt;/strong&gt; は&lt;code&gt;main.go&lt;/code&gt;で設定した値の変化の間隔(10秒)が&lt;code&gt;Prometheus&lt;/code&gt;の&lt;code&gt;scrape_interval&lt;/code&gt;(15秒)より短いために15秒ごとに値が変化している.&lt;/p&gt;
&lt;p&gt;やったぜ.&lt;br&gt;
自作の&lt;code&gt;Exporter&lt;/code&gt;をスクレイプして, 設定したとおりにメトリクスが変化していることが確認できた.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Prometheus&lt;/code&gt;でスクレイプできるかんたんな&lt;code&gt;Exporter&lt;/code&gt;を自作してみた.&lt;br&gt;
&lt;code&gt;Prometheus&lt;/code&gt;自体が&lt;code&gt;Go&lt;/code&gt;で書かれているだけあって, &lt;code&gt;Go&lt;/code&gt;だとかなり楽に記述できた. と思う.&lt;br&gt;
特に&lt;code&gt;go routine&lt;/code&gt;のおかげでメトリクスとHTTPハンドラの並行処理が簡単に書けるのがいいと思った.&lt;br&gt;
自作のAPIとかにこんな感じで&lt;code&gt;Exporter&lt;/code&gt;を実装すれば監視がめちゃめちゃ楽になりそう.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="あたらしいボールをもらってごきげんのねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-09-17-prometheus-exporter/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-09-17-prometheus-exporter/sotochan_hu_5484d1ed452804af.jpg 800w, https://blog.uzimihsr.com/post/2020-09-17-prometheus-exporter/sotochan_hu_c41edbb02322b1d1.jpg 1600w, https://blog.uzimihsr.com/post/2020-09-17-prometheus-exporter/sotochan_hu_dd847c0e975f9edb.jpg 2400w, https://blog.uzimihsr.com/post/2020-09-17-prometheus-exporter/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/prometheus/client_golang" target="_blank" rel="noopener"
 &gt;prometheus/client_golang&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;a class="link" href="https://prometheus.io/docs/guides/go-application/" target="_blank" rel="noopener"
 &gt;Instrumenting a Go application&lt;/a&gt;&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/prometheus/client_golang/tree/master/examples" target="_blank" rel="noopener"
 &gt;client_golang/examples&lt;/a&gt;&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>cobraでかんたんなCLIツールをつくった</title><link>https://blog.uzimihsr.com/post/2020-09-03-golang-cobra/</link><pubDate>Thu, 03 Sep 2020 22:10:37 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-09-03-golang-cobra/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-09-03-golang-cobra/sotochan.jpg" alt="Featured image of post cobraでかんたんなCLIツールをつくった" /&gt;&lt;h2 id="goでコマンドラインツール"&gt;Goでコマンドラインツール
&lt;/h2&gt;&lt;p&gt;golangでCLIツールを作るときに引数とかサブコマンドをいい感じにしてくれるライブラリのcobraを試した.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;cobra&lt;/code&gt;を使ってコマンドラインであいさつするおもちゃ&lt;a class="link" href="https://github.com/uzimihsr/greeting" target="_blank" rel="noopener"
 &gt;greeting&lt;/a&gt;をつくった.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# hello&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ greeting hello hoge fuga piyo --message &lt;span class="s1"&gt;&amp;#39;Nice to meet you!&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Hello, hoge, fuga, and piyo!
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Nice to meet you!
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# こんにちは&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ greeting hello 鈴木 --message &lt;span class="s1"&gt;&amp;#39;お会いできて嬉しいです!&amp;#39;&lt;/span&gt; -l ja
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;鈴木さん, こんにちは!
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;お会いできて嬉しいです!
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# goodbye&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ greeting goodbye hoge fuga piyo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Goodbye, hoge, fuga, and piyo!
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# さようなら&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ greeting goodbye A -l ja
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Aさん, さようなら!&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Mojave 10.14&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/golang/go" target="_blank" rel="noopener"
 &gt;go&lt;/a&gt; version go1.14.6 darwin/amd64&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/spf13/cobra" target="_blank" rel="noopener"
 &gt;cobra&lt;/a&gt; v1.0.0&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#cobra%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab%e3%81%a8%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab%e3%82%b3%e3%83%bc%e3%83%89%e3%81%ae%e4%bd%9c%e6%88%90" &gt;cobraのインストールとサンプルコードの作成&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%b5%e3%83%96%e3%82%b3%e3%83%9e%e3%83%b3%e3%83%89%e3%81%ae%e5%ae%9f%e8%a3%85" &gt;サブコマンドの実装&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="cobraのインストールとサンプルコードの作成"&gt;cobraのインストールとサンプルコードの作成
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;cobra&lt;/code&gt;はこれ自身がコマンドとしても提供されているので, まずはこれをインストールする.&lt;br&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# cobraをインストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go get -u github.com/spf13/cobra/cobra
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ which cobra
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/GOPATH/bin/cobra
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cobra
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Cobra is a CLI library &lt;span class="k"&gt;for&lt;/span&gt; Go that empowers applications.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;This application is a tool to generate the needed files
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;to quickly create a Cobra application.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Usage:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cobra &lt;span class="o"&gt;[&lt;/span&gt;command&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Available Commands:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; add Add a &lt;span class="nb"&gt;command&lt;/span&gt; to a Cobra Application
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;help&lt;/span&gt; Help about any &lt;span class="nb"&gt;command&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; init Initialize a Cobra Application
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Flags:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -a, --author string author name &lt;span class="k"&gt;for&lt;/span&gt; copyright attribution &lt;span class="o"&gt;(&lt;/span&gt;default &lt;span class="s2"&gt;&amp;#34;YOUR NAME&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --config string config file &lt;span class="o"&gt;(&lt;/span&gt;default is &lt;span class="nv"&gt;$HOME&lt;/span&gt;/.cobra.yaml&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -h, --help &lt;span class="nb"&gt;help&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; cobra
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -l, --license string name of license &lt;span class="k"&gt;for&lt;/span&gt; the project
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --viper use Viper &lt;span class="k"&gt;for&lt;/span&gt; configuration &lt;span class="o"&gt;(&lt;/span&gt;default &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Use &lt;span class="s2"&gt;&amp;#34;cobra [command] --help&amp;#34;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; more information about a command.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;cobra init&lt;/code&gt;を使うと動く状態のサンプルコードを生成してくれる.&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;br&gt;
昔は空のディレクトリじゃないとできなかったみたいだけど, 今は気にしなくて大丈夫.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 新規ディレクトリを作成+go.modを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mkdir -p greeting &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; greeting
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go mod init github.com/uzimihsr/greeting
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;go: creating new go.mod: module github.com/uzimihsr/greeting
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# サンプルコードの作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cobra init --pkg-name github.com/uzimihsr/greeting
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Your Cobra application is ready at
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/path/to/greeting
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ tree .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── LICENSE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── cmd
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   └── root.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── go.mod
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── main.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;1&lt;/span&gt; directory, &lt;span class="m"&gt;4&lt;/span&gt; files&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;作成されたサンプルコードはこんな感じ.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/447574ddce2b458a9ec0e9bbaced5f78.js"&gt;&lt;/script&gt;
&lt;script src="https://gist.github.com/uzimihsr/e5e45083544edb48f9b8fb392a749886.js"&gt;&lt;/script&gt;
&lt;p&gt;試しに動かしてみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# アプリの実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go run main.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;A longer description that spans multiple lines and likely contains
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;examples and usage of using your application. For example:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Cobra is a CLI library &lt;span class="k"&gt;for&lt;/span&gt; Go that empowers applications.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;This application is a tool to generate the needed files
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;to quickly create a Cobra application.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# root.goで設定されたヘルプメッセージ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;ちゃんと動いた.&lt;/p&gt;
&lt;p&gt;さらに, &lt;code&gt;cobra add&lt;/code&gt;でサブコマンドを作成できる.&lt;br&gt;
追加したサブコマンドのファイルは&lt;code&gt;root.go&lt;/code&gt;と同じく&lt;code&gt;cmd&lt;/code&gt;配下に作成される.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# サブコマンド(hello)の作成/実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cobra add hello
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hello created at /Users/uzimihsr/Workspace/greeting
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls cmd
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hello.go root.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go run main.go hello
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hello called
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go run main.go hello -h
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;A longer description that spans multiple lines and likely contains examples
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;and usage of using your command. For example:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Cobra is a CLI library &lt;span class="k"&gt;for&lt;/span&gt; Go that empowers applications.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;This application is a tool to generate the needed files
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;to quickly create a Cobra application.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Usage:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; greeting hello &lt;span class="o"&gt;[&lt;/span&gt;flags&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Flags:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -h, --help &lt;span class="nb"&gt;help&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; hello
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Global Flags:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --config string config file &lt;span class="o"&gt;(&lt;/span&gt;default is &lt;span class="nv"&gt;$HOME&lt;/span&gt;/.greeting.yaml&lt;span class="o"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;script src="https://gist.github.com/uzimihsr/b1ee2c2e0140aa1fea0e5180374488f2.js"&gt;&lt;/script&gt;
&lt;h3 id="サブコマンドの実装"&gt;サブコマンドの実装
&lt;/h3&gt;&lt;p&gt;あとはこのルートコマンド(&lt;code&gt;root.go&lt;/code&gt;)とサブコマンド(&lt;code&gt;hello.go&lt;/code&gt;)をいじっていく.&lt;br&gt;
どちらもinit()関数で引数やコマンドに必要な変数の設定を行い,&lt;br&gt;
Command.Runのfunc()で実際に行う処理を記述しているので, この形式に従っていろいろいじってみる.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/b62f55b5e70a1b924c6576cf6f713b4e.js"&gt;&lt;/script&gt;
&lt;script src="https://gist.github.com/uzimihsr/0ee18d3e322b19e86277d98bf7fc1441.js"&gt;&lt;/script&gt;
&lt;script src="https://gist.github.com/uzimihsr/a0763f5d1295ed88747c09f54da91606.js"&gt;&lt;/script&gt;
&lt;p&gt;最終的なディレクトリ構造はこんな感じ.&lt;br&gt;
出会いと別れの挨拶をするサブコマンド&lt;code&gt;cmd/hello.go&lt;/code&gt;と&lt;code&gt;cmd/goodbye.go&lt;/code&gt;を実装した.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ tree .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── cmd
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   ├── goodbye.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   ├── hello.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   └── root.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── go.mod
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── go.sum
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── main.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;1&lt;/span&gt; directory, &lt;span class="m"&gt;6&lt;/span&gt; files&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;実際に動かしてみる.&lt;br&gt;
&lt;code&gt;go install&lt;/code&gt;すると&lt;code&gt;PATH&lt;/code&gt;が通ってすぐ使えるようになるのでべんり.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ビルドして実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go build
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ./greeting hello World
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Hello, World!
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# GOPATHが通っている場合はinstallするとパスが通る&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go install
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ which greeting
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$GOPATH&lt;/span&gt;/bin/greeting
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# -l で言語(en/ja)の指定ができる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ greeting goodbye A B -l ja
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Aさん, Bさん, さようなら!
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# --message で追加のメッセージを指定できる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ greeting hello A B C --message &lt;span class="s1"&gt;&amp;#39;Nice to meet you!&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Hello, A, B, and C!
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Nice to meet you!
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# goodbyeには敢えて --message のflagをつけていないので指定するとエラーになる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ greeting goodbye A --message &lt;span class="s1"&gt;&amp;#39;See you again!&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Error: unknown flag: --message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Usage:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; greeting goodbye &lt;span class="o"&gt;[&lt;/span&gt;NAME&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;flags&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Flags:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -h, --help &lt;span class="nb"&gt;help&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; goodbye
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Global Flags:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -l, --lang string Language : en, ja &lt;span class="o"&gt;(&lt;/span&gt;default &lt;span class="s2"&gt;&amp;#34;en&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;unknown flag: --message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 引数の数が不正でもエラーになる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ greeting hello
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Error: requires at least &lt;span class="m"&gt;1&lt;/span&gt; arg&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt;, only received &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Usage:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; greeting hello &lt;span class="o"&gt;[&lt;/span&gt;NAME&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;flags&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Flags:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -h, --help &lt;span class="nb"&gt;help&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; hello
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -m, --message string Help message &lt;span class="k"&gt;for&lt;/span&gt; toggle
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Global Flags:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -l, --lang string Language : en, ja &lt;span class="o"&gt;(&lt;/span&gt;default &lt;span class="s2"&gt;&amp;#34;en&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;requires at least &lt;span class="m"&gt;1&lt;/span&gt; arg&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt;, only received &lt;span class="m"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;やったぜ.&lt;br&gt;
機能はしょぼいけど, サブコマンドごとに違う機能を持つCLIツールができた.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Cobra&lt;/code&gt;を使って簡単なCLIツールを作った.&lt;br&gt;
サブコマンドごとに&lt;code&gt;flag&lt;/code&gt;(オプション)が管理できたり, &lt;code&gt;Args&lt;/code&gt;で引数の条件を指定できたりするのがいいと思う.&lt;br&gt;
今まで&lt;code&gt;Go&lt;/code&gt;でCLIを作るときは標準パッケージの&lt;a class="link" href="https://godoc.org/flag" target="_blank" rel="noopener"
 &gt;flag&lt;/a&gt;を使ってたけど,&lt;br&gt;
これからは&lt;code&gt;Cobra&lt;/code&gt;でサクッと作るようにしたい.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="ねこのかわいい肉球" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-09-03-golang-cobra/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-09-03-golang-cobra/sotochan_hu_13112317964afa7f.jpg 800w, https://blog.uzimihsr.com/post/2020-09-03-golang-cobra/sotochan_hu_c5e7d08cf3745095.jpg 1600w, https://blog.uzimihsr.com/post/2020-09-03-golang-cobra/sotochan_hu_6f1faa1bc054105c.jpg 2400w, https://blog.uzimihsr.com/post/2020-09-03-golang-cobra/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/spf13/cobra/blob/master/cobra/README.md" target="_blank" rel="noopener"
 &gt;Cobra Generator&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>8月のそとちゃんまとめ(2020)</title><link>https://blog.uzimihsr.com/post/2020-09-02-sotochan/</link><pubDate>Wed, 02 Sep 2020 21:28:29 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-09-02-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-09-02-sotochan/sotochan03.jpg" alt="Featured image of post 8月のそとちゃんまとめ(2020)" /&gt;&lt;h2 id="大騒ぎ"&gt;大騒ぎ
&lt;/h2&gt;&lt;p&gt;8月のそとちゃんはたいへんだった.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e8%aa%a4%e9%a3%b2%e4%ba%8b%e4%bb%b6" &gt;誤飲事件&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%b2%e3%81%aa%e3%81%9f%e3%81%bc%e3%81%a3%e3%81%93%e3%82%92%e6%ba%80%e5%96%ab" &gt;ひなたぼっこを満喫&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%ab%e3%83%aa%e3%82%ab%e3%83%aa%e5%95%8f%e9%a1%8c%e3%81%ae%e9%80%b2%e6%8d%97" &gt;カリカリ問題の進捗&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="誤飲事件"&gt;誤飲事件
&lt;/h3&gt;&lt;p&gt;なんと言っても&lt;a class="link" href="https://uzimihsr.github.io/post/2020-08-13-sotochan/" target="_blank" rel="noopener"
 &gt;ヒモ誤飲事件&lt;/a&gt;があった.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;やばいことにならなくて本当によかった&lt;br&gt;&lt;br&gt;しもべの不注意が原因なので反省します &lt;a href="https://t.co/tsGqCQD8Q0"&gt;pic.twitter.com/tsGqCQD8Q0&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1291312620432064512?ref_src=twsrc%5Etfw"&gt;August 6, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;もともとそんなにおもちゃを咥えたりしないかしこいねこだったんだけど,&lt;br&gt;
その日はおもちゃにまたたびをかけてたので興奮して食べちゃったんじゃないかと推測している.&lt;/p&gt;
&lt;p&gt;というわけでまたたびは当分の間禁止になった(かわいそう).&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;きげんわるい &lt;a href="https://t.co/nkanUTcHit"&gt;pic.twitter.com/nkanUTcHit&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1299704176818057216?ref_src=twsrc%5Etfw"&gt;August 29, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;また, 今回の件でやっぱりペット保険に入ろうと思ったので, 診察ついでに獣医さんにそとちゃんのだいたいの年齢を調べてもらった.&lt;br&gt;
(元野良とかで正確な生年月日がわからないねこは獣医さんに推測してもらう必要がある)&lt;br&gt;
歯の生え方とかからだいたい推測できるらしい.&lt;/p&gt;
&lt;p&gt;&lt;img alt="5月生まれ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-09-02-sotochan/sotochan01.jpg" srcset="https://blog.uzimihsr.com/post/2020-09-02-sotochan/sotochan01_hu_e06b0d3037782b95.jpg 800w, https://blog.uzimihsr.com/post/2020-09-02-sotochan/sotochan01_hu_7ff6ae9c5150573e.jpg 1600w, https://blog.uzimihsr.com/post/2020-09-02-sotochan/sotochan01_hu_a8cb66fe30c6f60a.jpg 2400w, https://blog.uzimihsr.com/post/2020-09-02-sotochan/sotochan01.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2016年5月生まれ(推定)&lt;/strong&gt;. やっぱり4さいくらいだった.&lt;/p&gt;
&lt;p&gt;うちに来たのが&lt;a class="link" href="https://uzimihsr.github.io/post/2019-08-24-sotochan-story/" target="_blank" rel="noopener"
 &gt;5月1日&lt;/a&gt;なので,&lt;br&gt;
記念日も兼ねて &lt;strong&gt;2016年5月1日生まれ&lt;/strong&gt; ということにする.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;知らなかった &lt;a href="https://twitter.com/hashtag/%E4%B8%96%E7%95%8C%E7%8C%AB%E3%81%AE%E6%97%A5?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#世界猫の日&lt;/a&gt; &lt;a href="https://t.co/40M6d3G8IY"&gt;pic.twitter.com/40M6d3G8IY&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1292096557127315457?ref_src=twsrc%5Etfw"&gt;August 8, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;やっぱり4さいのねこは威厳がありますね&amp;hellip;(ほんまか?)&lt;/p&gt;
&lt;h3 id="ひなたぼっこを満喫"&gt;ひなたぼっこを満喫
&lt;/h3&gt;&lt;p&gt;8月は天気のいい日が多くて, ひなたぼっこが捗ったらしい.&lt;br&gt;
とくに窓際のダンボールとハンモックがお気にいりだった.&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://twitter.com/uzimihsr/status/1290172623884705793" target="_blank" rel="noopener"
 &gt;https://twitter.com/uzimihsr/status/1290172623884705793&lt;/a&gt;&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ひなたぼっこ &lt;a href="https://t.co/lJdQchyKDA"&gt;pic.twitter.com/lJdQchyKDA&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1296351276398080000?ref_src=twsrc%5Etfw"&gt;August 20, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;あとはベランダで力尽きたセミの観察にも熱心だった.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ベランダを監視 &lt;a href="https://t.co/NJD1eaGO2S"&gt;pic.twitter.com/NJD1eaGO2S&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1295238661282258944?ref_src=twsrc%5Etfw"&gt;August 17, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;陽に当たるのは健康にもいいはずなんだけど,&lt;br&gt;
そのまま寝落ちするのは熱中症が心配なのでやめてほしい&amp;hellip;&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;まーた直射日光浴びてる &lt;a href="https://t.co/z6NQd2fgi8"&gt;pic.twitter.com/z6NQd2fgi8&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1289820450663489537?ref_src=twsrc%5Etfw"&gt;August 2, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;すやすや &lt;a href="https://t.co/YGmSbf1HC0"&gt;pic.twitter.com/YGmSbf1HC0&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1290903342521044995?ref_src=twsrc%5Etfw"&gt;August 5, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;h3 id="カリカリ問題の進捗"&gt;カリカリ問題の進捗
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2020-08-03-sotochan/#%E3%82%AB%E3%83%AA%E3%82%AB%E3%83%AA%E9%A3%9F%E3%81%B9%E3%81%AA%E3%81%84%E5%95%8F%E9%A1%8C" target="_blank" rel="noopener"
 &gt;カリカリ食べない問題&lt;/a&gt;がちょっとだけ改善?した.&lt;/p&gt;
&lt;p&gt;俺がいない間ならカリカリをちゃんと食べるのがよくわかったので,&lt;br&gt;
今月は夕方にときどき外出するようにしてみた.&lt;/p&gt;
&lt;p&gt;割と効果はあって, 午後に出しているカリカリを残さず食べるようになった.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;←しもべが出かける前 帰宅時(2h後)→ &lt;a href="https://t.co/Bajm6CzAoO"&gt;pic.twitter.com/Bajm6CzAoO&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1294590272890785792?ref_src=twsrc%5Etfw"&gt;August 15, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;さらに何日か繰り返すと夕方にカリカリを食べるのが習慣化されたみたいで,&lt;br&gt;
俺が家にいても半分くらいは食べてくれるようになった.&lt;/p&gt;
&lt;p&gt;&lt;img alt="えらい" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-09-02-sotochan/sotochan02.jpg" srcset="https://blog.uzimihsr.com/post/2020-09-02-sotochan/sotochan02_hu_877e9f57fe4c6510.jpg 800w, https://blog.uzimihsr.com/post/2020-09-02-sotochan/sotochan02_hu_594f005c5e7fbcd0.jpg 1600w, https://blog.uzimihsr.com/post/2020-09-02-sotochan/sotochan02_hu_fbcef9df9f6608d6.jpg 2400w, https://blog.uzimihsr.com/post/2020-09-02-sotochan/sotochan02.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;えらい.🎉&lt;br&gt;
ちゃんとカリカリをたべられるねこはかっこいいですね.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;8月のそとちゃんは大変なこともあったけどやっぱりだいたい元気だった.&lt;/p&gt;
&lt;p&gt;9月はちょっと大変な予定があるので, なるべくそとちゃんに負担をかけずに終わらせられるようにしたい&amp;hellip;&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="愚かな人類を見下ろすねこ様" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-09-02-sotochan/sotochan03.jpg" srcset="https://blog.uzimihsr.com/post/2020-09-02-sotochan/sotochan03_hu_fccacefcfc7334d.jpg 800w, https://blog.uzimihsr.com/post/2020-09-02-sotochan/sotochan03_hu_892b9202dafb76f4.jpg 1600w, https://blog.uzimihsr.com/post/2020-09-02-sotochan/sotochan03_hu_3d96bdb05cacff3f.jpg 2400w, https://blog.uzimihsr.com/post/2020-09-02-sotochan/sotochan03.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>CKAD-JPを受験した</title><link>https://blog.uzimihsr.com/post/2020-08-17-ckad/</link><pubDate>Mon, 17 Aug 2020 21:35:13 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-08-17-ckad/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-08-17-ckad/sotochan.jpg" alt="Featured image of post CKAD-JPを受験した" /&gt;&lt;h2 id="kubernetes完全に理解した"&gt;Kubernetes完全に理解した()
&lt;/h2&gt;&lt;p&gt;CKADを受験したので受験記的なやつ. 個人の感想. n番煎じ.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="ckad受験の流れ"&gt;CKAD受験の流れ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e5%8f%97%e9%a8%93%e3%81%ae%e7%b5%8c%e7%b7%af" &gt;受験の経緯&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e8%a9%a6%e9%a8%93%e5%af%be%e7%ad%96" &gt;試験対策&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e7%94%b3%e3%81%97%e8%be%bc%e3%81%bf" &gt;申し込み&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e8%a9%a6%e9%a8%93%e5%bd%93%e6%97%a5" &gt;試験当日&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e8%a9%a6%e9%a8%93%e3%81%ab%e3%81%a4%e3%81%84%e3%81%a6" &gt;試験について&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e7%b5%90%e6%9e%9c" &gt;結果&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="受験の経緯"&gt;受験の経緯
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://training.linuxfoundation.org/certification/certified-kubernetes-application-developer-ckad/" target="_blank" rel="noopener"
 &gt;CKAD&lt;/a&gt;は&lt;code&gt;Kubernetes&lt;/code&gt;クラスタでアプリを開発したり動かしたりする能力を証明する公式の認定試験.&lt;br&gt;
他にもクラスタ管理者向けの&lt;a class="link" href="https://training.linuxfoundation.org/certification/certified-kubernetes-administrator-cka/" target="_blank" rel="noopener"
 &gt;CKA&lt;/a&gt;っていう試験もある.&lt;/p&gt;
&lt;p&gt;去年の10月くらいから業務で&lt;code&gt;Kubernetes&lt;/code&gt;を半年くらい使っていてだんだん勉強のモチベーションが保てなくなってきたので, 目先の目標として受験することにした.&lt;/p&gt;
&lt;h3 id="試験対策"&gt;試験対策
&lt;/h3&gt;&lt;p&gt;7月に受験を決めてから1ヶ月の間, 普段の業務の他に以下の教材を使って試験対策をした.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://book.impress.co.jp/books/1118101055" target="_blank" rel="noopener"
 &gt;Kubernetes完全ガイド&lt;/a&gt;&lt;br&gt;
基本はこれ.&lt;br&gt;
&lt;code&gt;Pod&lt;/code&gt;とか&lt;code&gt;Deployment&lt;/code&gt;とかの基本的な&lt;code&gt;k8s&lt;/code&gt;リソースについてしっかり勉強できる.&lt;br&gt;
一通り読んだけど, 11章以降のクラスタ自体の操作とかの内容はあんまり試験に出なかったように思う. 13章(セキュリティ)の内容はちょっとだけ出たかも.&lt;br&gt;
最近&lt;a class="link" href="https://book.impress.co.jp/books/1119101148" target="_blank" rel="noopener"
 &gt;第2版&lt;/a&gt;が出たらしい. 試験に関係なく持っておくと役に立つ.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/dgkanatsios/CKAD-exercises" target="_blank" rel="noopener"
 &gt;CKAD-exercises&lt;/a&gt;&lt;br&gt;
CKADの問題を解くための基本的なリソース操作などの練習問題集.&lt;br&gt;
実際の問題とは少し違うけど, 基本操作はこれで一通り練習できる.&lt;br&gt;
2周くらいやってコツをつかんだ.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://acloud.guru/learn/d068441f-75b4-4fe8-a7a6-df9153f24a35" target="_blank" rel="noopener"
 &gt;A Cloud GuruのCKADコース&lt;/a&gt;&lt;br&gt;
本番の対策用. 有料(7日間無料).&lt;br&gt;
&lt;strong&gt;HANDS-ON-LAB&lt;/strong&gt;, 特に &lt;strong&gt;Practice Exam&lt;/strong&gt; の問題は本番の問題にけっこう近かったように感じる.&lt;br&gt;
&lt;a class="link" href="https://book.impress.co.jp/books/1118101055" target="_blank" rel="noopener"
 &gt;Kubernetes完全ガイド&lt;/a&gt;を読んでいるのでハンズオン以外の内容は飛ばしても問題なかった.&lt;br&gt;
1週間だけ無料なので, 試験直前に登録して終わったあとにすぐ解約した.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="申し込み"&gt;申し込み
&lt;/h3&gt;&lt;p&gt;英語イキリオタクだけど母語は日本語なので, できるだけ合格の確率を上げるために日本語で受験できるという触れ込みの&lt;a class="link" href="https://training.linuxfoundation.org/ja/certified-kubernetes-application-developer-ckad-jp/" target="_blank" rel="noopener"
 &gt;CKAD-JP&lt;/a&gt;を受けることにした.&lt;/p&gt;
&lt;p&gt;&amp;hellip;が, 後述のように実際は申し込みの手順も試験官とのやり取りも全部英語だったので普通の&lt;a class="link" href="https://training.linuxfoundation.org/certification/certified-kubernetes-application-developer-ckad/" target="_blank" rel="noopener"
 &gt;CKAD&lt;/a&gt;を受けたほうがよかったのかも.&lt;/p&gt;
&lt;p&gt;申し込みには&lt;a class="link" href="https://www.linuxfoundation.org/" target="_blank" rel="noopener"
 &gt;Linux Foundation&lt;/a&gt;と&lt;a class="link" href="https://www.examslocal.com/" target="_blank" rel="noopener"
 &gt;psi&lt;/a&gt;のアカウントが必要になるけど, 1つのGoogleアカウントで全部登録できるのでかんたんだった.&lt;br&gt;
やることは名前とかの情報を入力して, クレカで受験料を払って, 試験日を予約するだけ.&lt;br&gt;
試験日の予約は結構空きが少なかったので, もっと余裕を持って予約すればよかった.&lt;/p&gt;
&lt;p&gt;受験用のブラウザは&lt;a class="link" href="https://www.google.com/intl/ja_jp/chrome/" target="_blank" rel="noopener"
 &gt;Chrome&lt;/a&gt;がおすすめで, 事前に&lt;a class="link" href="https://chrome.google.com/webstore/detail/innovative-exams-screensh/dkbjhjljfaagngbdhomnlcheiiangfle" target="_blank" rel="noopener"
 &gt;拡張機能&lt;/a&gt;をインストールしておく必要がある.&lt;br&gt;
さらに念の為にCompatibility Checkをやっておくと安心.&lt;/p&gt;
&lt;h3 id="試験当日"&gt;試験当日
&lt;/h3&gt;&lt;p&gt;試験は自分の部屋で受けた.&lt;/p&gt;
&lt;p&gt;試験開始の15分前くらいに&lt;a class="link" href="https://trainingportal.linuxfoundation.org/learn/dashboard" target="_blank" rel="noopener"
 &gt;my portal&lt;/a&gt;で &lt;strong&gt;試験開始&lt;/strong&gt; 的なボタンを押すと勝手に画面が切り替わって, 試験官がライブチャットで以下の内容を指示してきたのでその通りにした.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;拡張機能を使って画面とカメラ, マイクを共有しろ(顔を映せ)&lt;/li&gt;
&lt;li&gt;使ってるOSを教えろ&lt;/li&gt;
&lt;li&gt;強制終了メニュー(&lt;code&gt;⌘+⌥+Esc&lt;/code&gt;)を表示して起動中のアプリを見せろ(ブラウザ以外消せ)&lt;/li&gt;
&lt;li&gt;カメラ越しに身分証(パスポートとクレジットカード)を見せろ&lt;/li&gt;
&lt;li&gt;机の上のものを全部片付けろ&lt;/li&gt;
&lt;li&gt;カメラを持ったまま部屋を一周しろ&lt;/li&gt;
&lt;li&gt;試験中はカメラに顔が映るようにして目線を画面から外すな&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;要はオンライン試験なのでカンニングができないように注意しろってことだと思う.&lt;/p&gt;
&lt;p&gt;特に片付けのタイミングで, &lt;em&gt;&amp;ldquo;鼻をかむための箱ティッシュは試験中使えないよ!&amp;rdquo;&lt;/em&gt; って言われたのが面白かった.&lt;br&gt;
鼻炎だから無いと辛かったんだけどカンニング対策なので許されず, 最終的に無地のハンカチを胸ポケットに入れて使うことになった.&lt;/p&gt;
&lt;p&gt;ちなみに, &lt;a class="link" href="https://training.linuxfoundation.org/ja/certified-kubernetes-application-developer-ckad-jp/" target="_blank" rel="noopener"
 &gt;CKAD-JP&lt;/a&gt;で受験したのになぜか試験官とのやりとりは最後までずっと英語だった.&lt;br&gt;
とはいえ音声会話ではなくテキスト形式なのでそんなに困ることもなかった.&lt;/p&gt;
&lt;p&gt;最初の試験官とのやりとりが終わったあとはすぐに試験問題の画面に切り替わるので, あとは問題を解くだけだった.&lt;br&gt;
残り時間が15分になったときと試験終了時に再度試験官とやりとりが発生したけど, 特に何もなくおわった.&lt;/p&gt;
&lt;h3 id="試験について"&gt;試験について
&lt;/h3&gt;&lt;p&gt;具体的な問題の内容を公開するのは許されていないので, 簡単なメモ.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;試験用の画面は&lt;a class="link" href="https://docs.linuxfoundation.org/tc-docs/certification/lf-candidate-handbook/exam-user-interface" target="_blank" rel="noopener"
 &gt;こんな感じ&lt;/a&gt;&lt;br&gt;
左側に問題, 右側にターミナルの画面. &lt;a class="link" href="https://www.katacoda.com/" target="_blank" rel="noopener"
 &gt;Katacoda&lt;/a&gt;っぽさがある.&lt;br&gt;
&lt;code&gt;Kubernetes&lt;/code&gt;クラスタとか&lt;code&gt;kubectl&lt;/code&gt;はすでにセットアップされていて, 問題の内容をコマンドラインでガンガン解いていく感じ.&lt;br&gt;
&lt;code&gt;tmux&lt;/code&gt;が使えるので, 自分はターミナルの画面を左右分割して片方で&lt;code&gt;kubectl -h&lt;/code&gt;とか&lt;code&gt;kubectl explain&lt;/code&gt;の内容を表示しながらもう片方で操作するようにした.&lt;br&gt;
この画面以外にも1タブだけ&lt;a class="link" href="https://kubernetes.io/docs/home/" target="_blank" rel="noopener"
 &gt;公式Docs&lt;/a&gt;を開くことが許されてたけど, そこまで使わなかった. &lt;strong&gt;というかDocsをちんたら調べてる暇はなかった.&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;試験時間は2時間で問題数は19問&lt;br&gt;
&lt;em&gt;&amp;quot;~の&lt;code&gt;image&lt;/code&gt;を使った&lt;code&gt;Pod&lt;/code&gt;を作れ. それをXX番ポートで公開する&lt;code&gt;Service&lt;/code&gt;を作れ&amp;quot;&lt;/em&gt; とか,&lt;br&gt;
&lt;em&gt;&amp;quot;~の&lt;code&gt;namespace&lt;/code&gt;に壊れている&lt;code&gt;Pod&lt;/code&gt;があるのでそれを探して修復しろ&amp;quot;&lt;/em&gt; 的な問題が立て続けに来た.&lt;br&gt;
問題を解く順序は決められていないので, 飛ばした問題をあとから解き直したりもできた.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;問題文は英語, 日本語, 中国語が自由に切り替えられる&lt;br&gt;
&amp;hellip;が, 日本語の翻訳が割とガバめなのと普段英語で覚えてる用語がカタカナになっただけでかなり混乱したので, 結局最後まで英語で解いた.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;スピード勝負&lt;br&gt;
約20問を2時間, 平均で約6分/1問のペースで解かなければならなかった.&lt;br&gt;
&lt;strong&gt;いちいち&lt;code&gt;YAML&lt;/code&gt;を0から手で書いていては到底間に合わない&lt;/strong&gt; ので, &lt;a class="link" href="https://uzimihsr.github.io/post/2020-07-29-kubectl-run-and-create/" target="_blank" rel="noopener"
 &gt;kubectlでサクッと作る&lt;/a&gt;か, &lt;a class="link" href="https://kubernetes.io/docs/home/" target="_blank" rel="noopener"
 &gt;公式Docs&lt;/a&gt;からコピペするのが良さげ.&lt;br&gt;
すでに存在するリソースを修正するような問題も出るので, &lt;code&gt;kubectl edit&lt;/code&gt;や&lt;code&gt;kubectl get -o yaml&lt;/code&gt;とかも使う必要があった.&lt;br&gt;
まさに &lt;strong&gt;&lt;code&gt;YAML&lt;/code&gt;地獄&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;namespace&lt;/code&gt;が指定されている問題とそうでない問題がある&lt;br&gt;
これは結構重要.&lt;br&gt;
リソースを操作する&lt;code&gt;namespace&lt;/code&gt;が指定されている問題がある一方, 何の指定もない問題もあったのでちょっとだけ混乱した.&lt;br&gt;
何も指定されていない場合は&lt;code&gt;default&lt;/code&gt;で操作したけど, 結果を見るにそれでよかったっぽい.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;複数のクラスタを操作する必要がある&lt;br&gt;
これも重要だけど, どの問題も最初に&lt;code&gt;context&lt;/code&gt;を切り替えるコマンドが指定されているので忘れずコピペすればそこまで問題にはならなかった.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="結果"&gt;結果
&lt;/h3&gt;&lt;p&gt;結局時間はギリギリで, 最後の19問目を解いている途中で時間切れになった.&lt;/p&gt;
&lt;p&gt;結果は試験終了後36時間以内に届くことになっていたが, 結構待たされて34時間後にメールで結果が届いた.&lt;/p&gt;
&lt;p&gt;結果は&amp;hellip;?&lt;/p&gt;
&lt;p&gt;&lt;img alt="CKAD" class="gallery-image" data-flex-basis="310px" data-flex-grow="129" height="5316" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-08-17-ckad/ckad-jp-certificate.jpg" srcset="https://blog.uzimihsr.com/post/2020-08-17-ckad/ckad-jp-certificate_hu_1167f55dfd8e03f.jpg 800w, https://blog.uzimihsr.com/post/2020-08-17-ckad/ckad-jp-certificate_hu_15ff15ad8832e2f6.jpg 1600w, https://blog.uzimihsr.com/post/2020-08-17-ckad/ckad-jp-certificate_hu_a520a147bc578998.jpg 2400w, https://blog.uzimihsr.com/post/2020-08-17-ckad/ckad-jp-certificate.jpg 6879w" width="6879"&gt;&lt;/p&gt;
&lt;p&gt;合格だった. 🎉&lt;/p&gt;
&lt;p&gt;&lt;img alt="CKAD" class="gallery-image" data-flex-basis="2000px" data-flex-grow="833" height="256" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-08-17-ckad/score.png" srcset="https://blog.uzimihsr.com/post/2020-08-17-ckad/score_hu_50f87a5aa690f484.png 800w, https://blog.uzimihsr.com/post/2020-08-17-ckad/score_hu_8e237da2891dd062.png 1600w, https://blog.uzimihsr.com/post/2020-08-17-ckad/score.png 2134w" width="2134"&gt;&lt;/p&gt;
&lt;p&gt;合格点66点に対して得点は91点だったので, そこそこ余裕を持って合格できたんじゃなかろうか.&lt;br&gt;
たぶん100点満点なので解ききらなかった最後の1問以外はほとんど正解. だったらいいな.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;というわけで&lt;a class="link" href="https://training.linuxfoundation.org/certification/certified-kubernetes-application-developer-ckad/" target="_blank" rel="noopener"
 &gt;CKAD&lt;/a&gt;に合格した.&lt;br&gt;
合格したから会社の給料が上がるとか特にそういったことはないけど, なんかうれしい.&lt;br&gt;
とりあえず&lt;code&gt;YAML&lt;/code&gt;耐性は大幅に上がったはず.&lt;/p&gt;
&lt;p&gt;ようやく&lt;code&gt;Kubernetes&lt;/code&gt;完全に理解した()のでこの勢いで次は&lt;a class="link" href="https://training.linuxfoundation.org/certification/certified-kubernetes-administrator-cka/" target="_blank" rel="noopener"
 &gt;CKA&lt;/a&gt;も獲りたいけど, もっと勉強する必要がありそう&amp;hellip;&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="試験中は部屋に入れてもらえず激おこでずっと鳴き続けたねこ(お詫びにちゅーるをあげた)" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-08-17-ckad/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-08-17-ckad/sotochan_hu_1ab0628d24590608.jpg 800w, https://blog.uzimihsr.com/post/2020-08-17-ckad/sotochan_hu_94338aa485b0186f.jpg 1600w, https://blog.uzimihsr.com/post/2020-08-17-ckad/sotochan_hu_602b9e088877a24d.jpg 2400w, https://blog.uzimihsr.com/post/2020-08-17-ckad/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>ねこがおもちゃのヒモを誤飲した話</title><link>https://blog.uzimihsr.com/post/2020-08-13-sotochan/</link><pubDate>Thu, 13 Aug 2020 22:55:13 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-08-13-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-08-13-sotochan/sotochan04.jpg" alt="Featured image of post ねこがおもちゃのヒモを誤飲した話" /&gt;&lt;h2 id="肝を冷やした"&gt;肝を冷やした
&lt;/h2&gt;&lt;p&gt;結果的に問題はなかったけど, 不注意でそとちゃんを危険な目に遭わせてしまったので自分への戒めとして記録しておく.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;今回の教訓.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ねこがヒモ付きのおもちゃで遊んでるときは目を離しちゃだめ&lt;/li&gt;
&lt;li&gt;ヒモの誤飲は最悪死に至るほど危険&lt;/li&gt;
&lt;li&gt;誤飲の疑いがある時点で急患で病院に行く, 様子見は危険&lt;/li&gt;
&lt;li&gt;誤飲してから検査までの間は水とごく少量のウェットフードだけ食べさせる&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="おもちゃのヒモが消えた"&gt;おもちゃのヒモが消えた
&lt;/h3&gt;&lt;p&gt;ある日の夜のこと.&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://www.doggyman.com/?p=showroom&amp;amp;id=2412&amp;amp;new=1" target="_blank" rel="noopener"
 &gt;ヒモ付きのボールのおもちゃ&lt;/a&gt;&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;あたらしいおもちゃ &lt;a href="https://t.co/EqbMGAtRMg"&gt;pic.twitter.com/EqbMGAtRMg&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1276513662564331521?ref_src=twsrc%5Etfw"&gt;June 26, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;でねこをひとりで遊ばせていたところ, 突然ヒモが無くなっていたことに気づいた.&lt;/p&gt;
&lt;p&gt;&lt;img alt="おもちゃ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-08-13-sotochan/img01.jpg" srcset="https://blog.uzimihsr.com/post/2020-08-13-sotochan/img01_hu_565204afc172b324.jpg 800w, https://blog.uzimihsr.com/post/2020-08-13-sotochan/img01_hu_5afdfb277be7598.jpg 1600w, https://blog.uzimihsr.com/post/2020-08-13-sotochan/img01_hu_c617f5f167d126dd.jpg 2400w, https://blog.uzimihsr.com/post/2020-08-13-sotochan/img01.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;遊んでて抜けたのか, ヒモが付いてた場所にぽっかり穴が空いている.&lt;/p&gt;
&lt;p&gt;まわりを探しても見つからなかったので, ねこが食べたかもしれない.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;そとちゃん「みゃーん」&lt;/strong&gt;&lt;br&gt;
&lt;img alt="そとちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-08-13-sotochan/sotochan01.jpg" srcset="https://blog.uzimihsr.com/post/2020-08-13-sotochan/sotochan01_hu_c47a6923dafde1de.jpg 800w, https://blog.uzimihsr.com/post/2020-08-13-sotochan/sotochan01_hu_f012ba6f777bce3b.jpg 1600w, https://blog.uzimihsr.com/post/2020-08-13-sotochan/sotochan01_hu_92d87004a87f454f.jpg 2400w, https://blog.uzimihsr.com/post/2020-08-13-sotochan/sotochan01.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;そとちゃん「(ごろーん)」&lt;/strong&gt;
&lt;img alt="そとちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-08-13-sotochan/sotochan02.jpg" srcset="https://blog.uzimihsr.com/post/2020-08-13-sotochan/sotochan02_hu_84145f2ba35fdb2b.jpg 800w, https://blog.uzimihsr.com/post/2020-08-13-sotochan/sotochan02_hu_9890e601708e524e.jpg 1600w, https://blog.uzimihsr.com/post/2020-08-13-sotochan/sotochan02_hu_40e66f78cdda239b.jpg 2400w, https://blog.uzimihsr.com/post/2020-08-13-sotochan/sotochan02.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;でもなんかねこは元気っぽい.&lt;br&gt;
もしかして, 食べてない? ヒモはどこか見つけづらいところに入ってしまっただけ?&lt;/p&gt;
&lt;p&gt;とりあえず一晩様子を見て, 朝になってから動物病院にいくことにした.&lt;br&gt;
(今だから言えるけどこの判断は危険だった. 本当は急患で行くべきだった.)&lt;/p&gt;
&lt;h3 id="急変"&gt;急変
&lt;/h3&gt;&lt;p&gt;夜中に容態が急変することはなく, 朝になったので速攻で診察予約の電話をかける.&lt;/p&gt;
&lt;p&gt;電話してる途中にいきなり,&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;そとちゃん「ぐっ, くぽっ」&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;そとちゃん「げっ, ぐげっ, がっ」&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;なんか吐いた!!!&lt;/strong&gt;&lt;br&gt;
&lt;img alt="gero" class="gallery-image" data-flex-basis="341px" data-flex-grow="142" height="2572" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-08-13-sotochan/img02.jpg" srcset="https://blog.uzimihsr.com/post/2020-08-13-sotochan/img02_hu_c90961865170acd6.jpg 800w, https://blog.uzimihsr.com/post/2020-08-13-sotochan/img02_hu_37737321874efda5.jpg 1600w, https://blog.uzimihsr.com/post/2020-08-13-sotochan/img02_hu_51a01ffabf701790.jpg 2400w, https://blog.uzimihsr.com/post/2020-08-13-sotochan/img02.jpg 3659w" width="3659"&gt;&lt;/p&gt;
&lt;p&gt;やっぱりヒモを食べていた&amp;hellip;&lt;/p&gt;
&lt;p&gt;全部吐き出せたので最悪の事態は避けられたっぽい.&lt;/p&gt;
&lt;p&gt;獣医さんに電話で相談.&lt;/p&gt;
&lt;p&gt;この日は朝から診察の予約が埋まっていて, 異物が全部吐き出せていて急患じゃないのなら夕方に診てくれるとのこと.&lt;/p&gt;
&lt;p&gt;さらにそれまでにやるべきことも教えてもらえた.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;内蔵が傷ついているかもしれないので基本的に水以外は与えないでおく&lt;/li&gt;
&lt;li&gt;吐き出してからある程度時間が経ってから少しだけウェットフードを食べさせて様子を見る&lt;/li&gt;
&lt;li&gt;もしフードを吐いたり容態が急変したら急患ですぐ病院に行く&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;言われたとおりにして様子を見て, ねこも元気なままだったので少し安心した.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;おもちゃの紐食べてゲロ吐いたのにかっこつけてるねこ&lt;br&gt;&lt;br&gt;病院行ってきます &lt;a href="https://t.co/592Av5ytND"&gt;pic.twitter.com/592Av5ytND&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1291150161566081024?ref_src=twsrc%5Etfw"&gt;August 5, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;h3 id="検査結果"&gt;検査結果
&lt;/h3&gt;&lt;p&gt;夕方に動物病院へ行き, X線検査と超音波検査をしてもらった.&lt;/p&gt;
&lt;p&gt;幸いなことに内蔵に問題は見つからなかった.&lt;/p&gt;
&lt;p&gt;めっちゃ安心した.&lt;/p&gt;
&lt;p&gt;と同時に, 先生にめっちゃ怒られた.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;15cmくらいの毛糸状のヒモは誤飲すると本当に危険, 死ぬこともある&lt;/li&gt;
&lt;li&gt;ヒモ付きのおもちゃで遊んでる間は目を離してはいけない&lt;/li&gt;
&lt;li&gt;誤飲の疑いがある時点で急患で動物病院に行くべき&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;そのとおり. 完全に俺の不注意が原因だった.&lt;/p&gt;
&lt;p&gt;普段はおもちゃをくわえたりしないねこだけど, この日はまたたびで興奮していたのでもっと注意すべきだった.&lt;/p&gt;
&lt;p&gt;反省しかない.&lt;/p&gt;
&lt;p&gt;ちなみに俺が怒られてる横でもそとちゃんは診察台でごろごろして余裕ぶっこき丸だった.&lt;br&gt;
やっぱり病院は嫌いじゃないみたい.&lt;/p&gt;
&lt;p&gt;&lt;img alt="そとちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-08-13-sotochan/sotochan03.jpg" srcset="https://blog.uzimihsr.com/post/2020-08-13-sotochan/sotochan03_hu_53648fbf7985b1ce.jpg 800w, https://blog.uzimihsr.com/post/2020-08-13-sotochan/sotochan03_hu_2ef1ceb9dd7e8959.jpg 1600w, https://blog.uzimihsr.com/post/2020-08-13-sotochan/sotochan03_hu_7e78a08d50b8bdff.jpg 2400w, https://blog.uzimihsr.com/post/2020-08-13-sotochan/sotochan03.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;ちなみに今回誤飲して吐き出したヒモはこんな感じ.&lt;br&gt;
&lt;img alt="おもちゃ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-08-13-sotochan/img03.jpg" srcset="https://blog.uzimihsr.com/post/2020-08-13-sotochan/img03_hu_cc64198dfd9e29d6.jpg 800w, https://blog.uzimihsr.com/post/2020-08-13-sotochan/img03_hu_426dde2fc14803f.jpg 1600w, https://blog.uzimihsr.com/post/2020-08-13-sotochan/img03_hu_d06480ef749f8736.jpg 2400w, https://blog.uzimihsr.com/post/2020-08-13-sotochan/img03.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;こんな異物がねこのお腹の中にあったと思うとゾッとする.&lt;/p&gt;
&lt;p&gt;今回は運良く全部吐き出せただけで, 最悪の事態だってありえた.&lt;/p&gt;
&lt;p&gt;二度とこんな事が起こらないようにしたい.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="病院ではしゃいで疲れたねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-08-13-sotochan/sotochan04.jpg" srcset="https://blog.uzimihsr.com/post/2020-08-13-sotochan/sotochan04_hu_3d8e5ccab39d2657.jpg 800w, https://blog.uzimihsr.com/post/2020-08-13-sotochan/sotochan04_hu_5c9f143931a70bed.jpg 1600w, https://blog.uzimihsr.com/post/2020-08-13-sotochan/sotochan04_hu_141d53f19a5832eb.jpg 2400w, https://blog.uzimihsr.com/post/2020-08-13-sotochan/sotochan04.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>パラメータがあるときだけWHERE句が有効になるようなSQLを書こうとして詰んだ</title><link>https://blog.uzimihsr.com/post/2020-08-05-sql/</link><pubDate>Wed, 05 Aug 2020 20:55:20 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-08-05-sql/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-08-05-sql/sotochan.jpg" alt="Featured image of post パラメータがあるときだけWHERE句が有効になるようなSQLを書こうとして詰んだ" /&gt;&lt;h2 id="クエリ1個で済ませたかった"&gt;クエリ1個で済ませたかった
&lt;/h2&gt;&lt;p&gt;SELECT文のWHEREで絞りたい条件が複数あるときに静的なクエリでできないか試したけど, あんまり良くなさそうだった.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;OR&lt;/code&gt;とか&lt;code&gt;CASE&lt;/code&gt;とかを使うと一応動くものは作れる.&lt;br&gt;
けどあんまりパフォーマンスが良くなさそうなのでおとなしく動的SQLを使うほうが良さげ.&lt;br&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-mysql" data-lang="mysql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# どちらもTEAMとROLEに空文字(&amp;#39;&amp;#39;)以外の文字列が指定された場合のみWHERE句が有効になる
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;employee&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;OR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AND&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;OR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;employee&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;CASE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;THEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ELSE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;END&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AND&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;CASE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;THEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ELSE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;END&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Mojave 10.14&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.mysql.com/" target="_blank" rel="noopener"
 &gt;MySQL&lt;/a&gt; 5.7.25&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やりかた"&gt;やりかた
&lt;/h2&gt;&lt;p&gt;まずは適当なテーブルを作成する.&lt;br&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-mysql" data-lang="mysql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;employee&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;sql&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;DESC&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;employee&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+-------+-------------+------+-----+---------+----------------+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Field&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;Null&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Key&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Default&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Extra&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+-------+-------------+------+-----+---------+----------------+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;NO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PRI&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;NULL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;auto_increment&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;YES&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;NULL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;YES&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;NULL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;YES&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;NULL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;YES&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;NULL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+-------+-------------+------+-----+---------+----------------+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sec&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;employee&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+----+----------+------+---------+------+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+----+----------+------+---------+------+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Alice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Ben&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Charlie&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Daniel&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Emily&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Florence&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;George&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;trainee&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Harry&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Isabel&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Jack&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;trainee&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Katie&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;trainee&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+----+----------+------+---------+------+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sec&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/d39ff18aaf2378726e4b3c9ad58a1f48.js"&gt;&lt;/script&gt;
&lt;p&gt;このテーブルから「&lt;code&gt;team&lt;/code&gt;が&lt;code&gt;A&lt;/code&gt;で, かつ&lt;code&gt;role&lt;/code&gt;が&lt;code&gt;member&lt;/code&gt;」のレコードを抽出するクエリは次のように書ける.&lt;br&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-mysql" data-lang="mysql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;employee&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;A&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AND&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;member&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+----+----------+------+--------+------+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+----+----------+------+--------+------+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Charlie&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Daniel&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Emily&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Florence&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+----+----------+------+--------+------+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sec&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;ここまではいいんだけど,&lt;br&gt;
外部からクエリを投げるときなんかに&lt;code&gt;team&lt;/code&gt;と&lt;code&gt;role&lt;/code&gt;がそれぞれ指定されたときだけ&lt;code&gt;WHERE&lt;/code&gt;の条件を増やして, 次のようなクエリを自動で作れないか考えてみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-mysql" data-lang="mysql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# roleだけ指定された場合
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;employee&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;member&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# teamだけ指定された場合
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;employee&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;A&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 両方指定された場合
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;employee&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;A&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AND&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;member&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 何も指定されなかった場合
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;employee&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;これをプログラム側で実現するなら次のように動的にクエリを組み立てればできる.&lt;br&gt;
(これは簡単すぎる例, 本当はこんな適当な文字列連結でクエリを組み立てるのはSQLインジェクションとかを考えるとたぶんセキュリティ的によろしくない)&lt;/p&gt;
&lt;p&gt;&lt;code&gt;sql_example.go&lt;/code&gt;&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/7b4ea00c50706e9676407d8cc04dd49b.js"&gt;&lt;/script&gt;
&lt;p&gt;これでも問題なさそうなんだけど,&lt;br&gt;
プログラム側の処理に頼らず&lt;code&gt;SQL&lt;/code&gt;だけでこんな感じのクエリを組み立てたくなった.&lt;/p&gt;
&lt;p&gt;できそうなのは2通り.&lt;/p&gt;
&lt;h3 id="orを使う"&gt;ORを使う
&lt;/h3&gt;&lt;p&gt;レコードの要素に&lt;code&gt;NULL&lt;/code&gt;がない場合は&lt;code&gt;OR&lt;/code&gt;で複数の条件を合わせればできそう.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-mysql" data-lang="mysql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;employee&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;OR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AND&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;OR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;WHERE (team = @TEAM OR @TEAM = '')&lt;/code&gt;はパラメータ&lt;code&gt;@TEAM&lt;/code&gt;の内容によって次のように変わる.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;@TEAM = ''&lt;/code&gt;の場合&lt;br&gt;
&lt;code&gt;WHERE (team = '' OR '' = '')&lt;/code&gt;&lt;br&gt;
-&amp;gt; &lt;code&gt;team = ''&lt;/code&gt;となるレコードはないので&lt;code&gt;'' = ''&lt;/code&gt;を満たすレコード(即ち全件)を抽出&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;@TEAM = 'A'&lt;/code&gt;の場合&lt;br&gt;
&lt;code&gt;WHERE (team = 'A' OR 'A' = '')&lt;/code&gt;&lt;br&gt;
-&amp;gt; &lt;code&gt;'A' = ''&lt;/code&gt;となるレコードはないので&lt;code&gt;team = 'A'&lt;/code&gt;を満たすレコードのみ抽出&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;実際に試してみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-mysql" data-lang="mysql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;SET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;SET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;employee&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;OR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AND&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;OR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+----+----------+------+---------+------+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+----+----------+------+---------+------+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Alice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Ben&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Charlie&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Daniel&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Emily&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Florence&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;George&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;trainee&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Harry&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Isabel&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Jack&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;trainee&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Katie&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;trainee&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+----+----------+------+---------+------+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sec&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# SELECT * FROM employee; と同じ
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;SET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;A&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;SET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;employee&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;OR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AND&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;OR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+----+----------+------+---------+------+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+----+----------+------+---------+------+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Alice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Charlie&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Daniel&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Emily&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Florence&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;George&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;trainee&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+----+----------+------+---------+------+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sec&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# SELECT * FROM employee WHERE team = &amp;#39;A&amp;#39;; と同じ
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;SET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;SET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;member&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;employee&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;OR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AND&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;OR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+----+----------+------+--------+------+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+----+----------+------+--------+------+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Charlie&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Daniel&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Emily&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Florence&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Harry&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Isabel&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+----+----------+------+--------+------+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sec&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# SELECT * FROM employee WHERE role = &amp;#39;member&amp;#39;; と同じ
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;SET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;A&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;SET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;member&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;employee&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;OR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AND&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;OR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+----+----------+------+--------+------+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+----+----------+------+--------+------+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Charlie&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Daniel&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Emily&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Florence&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+----+----------+------+--------+------+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sec&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# SELECT * FROM employee WHERE team = &amp;#39;A&amp;#39; AND role = &amp;#39;member&amp;#39;; と同じ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;やったぜ.&lt;br&gt;
と思ったらこのやり方は個別の条件を指定するクエリに比べると&lt;code&gt;INDEX&lt;/code&gt;が使えなくなるので, 性能が良くないらしい&amp;hellip;&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;br&gt;
今はまだテーブルが小さいからうまくいってるように見えるだけなんだろうか.&lt;br&gt;
SQLチューニングはちゃんと勉強したことがないのでよくわからん.&lt;/p&gt;
&lt;h3 id="caseでがんばる"&gt;CASEでがんばる
&lt;/h3&gt;&lt;p&gt;ちょっと探してみたら&lt;code&gt;CASE&lt;/code&gt;を使う別の方法もあった&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-mysql" data-lang="mysql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;employee&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;CASE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;THEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ELSE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;END&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AND&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;CASE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;THEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ELSE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;END&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;こっちも構文が違うだけで結果は同じになるけど, パフォーマンスも変わらないんだろうか&amp;hellip;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-mysql" data-lang="mysql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;SET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;A&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;SET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;member&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;employee&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;CASE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;THEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ELSE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;END&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AND&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;CASE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;THEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ELSE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;END&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+----+----------+------+--------+------+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+----+----------+------+--------+------+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Charlie&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Daniel&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Emily&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Florence&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+----+----------+------+--------+------+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sec&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# SELECT * FROM employee WHERE team = &amp;#39;A&amp;#39; AND role = &amp;#39;member&amp;#39;; と同じ
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;SET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;A&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;SET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;employee&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;CASE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;THEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ELSE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;END&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AND&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;CASE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;THEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ELSE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;END&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+----+----------+------+---------+------+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+----+----------+------+---------+------+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Alice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Charlie&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Daniel&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Emily&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Florence&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;George&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;trainee&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+----+----------+------+---------+------+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sec&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# SELECT * FROM employee WHERE team = &amp;#39;A&amp;#39;; と同じ
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;SET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;SET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;member&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;employee&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;CASE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;THEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ELSE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;END&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AND&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;CASE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;THEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ELSE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;END&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+----+----------+------+--------+------+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+----+----------+------+--------+------+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Charlie&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Daniel&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Emily&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Florence&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Harry&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Isabel&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+----+----------+------+--------+------+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sec&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# SELECT * FROM employee WHERE role = &amp;#39;member&amp;#39;; と同じ
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;SET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;SET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;employee&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;CASE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;THEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ELSE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;END&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;TEAM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AND&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;CASE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;THEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ELSE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;END&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ROLE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+----+----------+------+---------+------+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+----+----------+------+---------+------+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Alice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Ben&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Charlie&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Daniel&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Emily&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Florence&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;George&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;trainee&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Harry&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Isabel&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Jack&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;trainee&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Katie&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;trainee&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+----+----------+------+---------+------+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sec&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# SELECT * FROM employee; と同じ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;一応動くものは作れたけど, このやり方だとパフォーマンス面を考えると微妙みたい&amp;hellip;&lt;br&gt;
参考にした記事にもあるように, やっぱりクエリを変化させたいときは動的に組み立てるほうがいいんだろうか?&lt;/p&gt;
&lt;p&gt;目的の用途はそこまでスピードが求められるものではないので一旦はこれで良しとしたいけど, やっぱりちょっとひっかかる&amp;hellip;&lt;br&gt;
SQLの勉強は正直あまりやりたくないので多分ORMとか使って動的SQLを組み立てるほうが楽そう.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="ねこのかわいい肉球" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-08-05-sql/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-08-05-sql/sotochan_hu_13112317964afa7f.jpg 800w, https://blog.uzimihsr.com/post/2020-08-05-sql/sotochan_hu_c5e7d08cf3745095.jpg 1600w, https://blog.uzimihsr.com/post/2020-08-05-sql/sotochan_hu_6f1faa1bc054105c.jpg 2400w, https://blog.uzimihsr.com/post/2020-08-05-sql/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a class="link" href="https://use-the-index-luke.com/ja/sql/where-clause/obfuscation/smart-logic" target="_blank" rel="noopener"
 &gt;SQLにおける条件付きのWHERE句- スマートなロジックを使わない場合&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;a class="link" href="https://qiita.com/nogitsune413/items/9c939f50714e430461c8" target="_blank" rel="noopener"
 &gt;検索SQLで、検索欄が空欄のとき、全検索にする&lt;/a&gt;&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>7月のそとちゃんまとめ(2020)</title><link>https://blog.uzimihsr.com/post/2020-08-03-sotochan/</link><pubDate>Mon, 03 Aug 2020 21:03:58 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-08-03-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-08-03-sotochan/sotochan02.jpg" alt="Featured image of post 7月のそとちゃんまとめ(2020)" /&gt;&lt;h2 id="割とごきげん"&gt;割とごきげん
&lt;/h2&gt;&lt;p&gt;7月もそとちゃんは元気だった.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%80%e3%83%b3%e3%83%9c%e3%83%bc%e3%83%ab%e3%83%96%e3%83%bc%e3%83%a0%e5%86%8d%e6%9d%a5" &gt;ダンボールブーム再来&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%ab%e3%83%aa%e3%82%ab%e3%83%aa%e9%a3%9f%e3%81%b9%e3%81%aa%e3%81%84%e5%95%8f%e9%a1%8c" &gt;カリカリ食べない問題&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e6%ad%af%e3%81%bf%e3%81%8c%e3%81%8d%e3%81%ae%e9%80%b2%e6%8d%97" &gt;歯みがきの進捗&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="ダンボールブーム再来"&gt;ダンボールブーム再来
&lt;/h3&gt;&lt;p&gt;またダンボールが増えた📦&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;新しいはこも気に入った &lt;a href="https://t.co/h5S6t7lLpg"&gt;pic.twitter.com/h5S6t7lLpg&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1279219986012098560?ref_src=twsrc%5Etfw"&gt;July 4, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;今まで使ってたAmazonのダンボールより浅くて, フチによっかかったりできるのがお気に入りらしい.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="hu" dir="ltr"&gt;nyamazon &lt;a href="https://t.co/SlJKDmv2cn"&gt;pic.twitter.com/SlJKDmv2cn&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1278571833151729665?ref_src=twsrc%5Etfw"&gt;July 2, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;あごのっけてるのかわいい &lt;a href="https://t.co/GPBwyDkHSb"&gt;pic.twitter.com/GPBwyDkHSb&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1279929892969144320?ref_src=twsrc%5Etfw"&gt;July 6, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;夜~朝はだいたいこのダンボールで寝てる.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;おはようございます &lt;a href="https://t.co/mW6raTOkOT"&gt;pic.twitter.com/mW6raTOkOT&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1281374867648950272?ref_src=twsrc%5Etfw"&gt;July 9, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;昼間はいつも窓際のダンボールベッドで寝てる.&lt;br&gt;
ダンボールに猫用ベッドを詰めただけなんだけどこれもかなりお気に入り.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ごめん寝的ななにか &lt;a href="https://t.co/7mm7cqs7yL"&gt;pic.twitter.com/7mm7cqs7yL&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1284667114205282304?ref_src=twsrc%5Etfw"&gt;July 19, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;おててまくらにしてる &lt;a href="https://t.co/JARBjliSWk"&gt;pic.twitter.com/JARBjliSWk&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1285790017118285824?ref_src=twsrc%5Etfw"&gt;July 22, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;なんでそんな窮屈な姿勢で寝るの？ &lt;a href="https://t.co/wrUa9hyEnZ"&gt;pic.twitter.com/wrUa9hyEnZ&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1287681616366641154?ref_src=twsrc%5Etfw"&gt;July 27, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;&lt;strong&gt;結論&lt;/strong&gt;: そとちゃんは常に寝ている💤&lt;/p&gt;
&lt;h3 id="カリカリ食べない問題"&gt;カリカリ食べない問題
&lt;/h3&gt;&lt;p&gt;そとちゃんがカリカリ食べない問題が発生した😭&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;おるすばんのときはカリカリ一粒残らず綺麗に食べるのにしもべが家に居ると全く食べない&lt;br&gt;猫缶を要求されている &lt;a href="https://t.co/4aV7VISHlR"&gt;pic.twitter.com/4aV7VISHlR&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1282990461972406274?ref_src=twsrc%5Etfw"&gt;July 14, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;食欲が無いとか味が気にいらないとかじゃなくて,&lt;br&gt;
&lt;strong&gt;俺が家にいる間だけ食べない.&lt;/strong&gt; どうして😭&lt;/p&gt;
&lt;p&gt;朝と昼に自動給餌器でカリカリを出してるんだけど,&lt;br&gt;
俺が寝てる間に出る朝のカリカリはきれいに食べてたり,&lt;br&gt;
昼に出したカリカリでも俺が夕方に出かけて戻ってくると食べてたりする.&lt;/p&gt;
&lt;p&gt;直接あげてる晩ごはんの&lt;a class="link" href="https://www.aixia.jp/product/detail_4571104712992" target="_blank" rel="noopener"
 &gt;黒缶パウチ&lt;/a&gt;とかおやつの&lt;a class="link" href="https://www.lion-pet.jp/product/petkiss/kinou_cat_niboshi.htm" target="_blank" rel="noopener"
 &gt;にぼし&lt;/a&gt;は喜んで食べるので,&lt;br&gt;
どうやら俺がいるともっと美味しいウェットフードとかおやつがもらえると思ってるみたい&amp;hellip;&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;カリカリ残しまくってるのにおなかすいたアピールしてくる&lt;br&gt;ちゃんとごはん食べないとおやつはあげません &lt;a href="https://t.co/RajRpJvc3G"&gt;pic.twitter.com/RajRpJvc3G&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1278898528266276864?ref_src=twsrc%5Etfw"&gt;July 3, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;そとちゃんは元々下痢気味で&lt;a class="link" href="https://www.royalcanin.com/jp/cats/products/vet-products/feline-gastrointestinal-high-energy-dry-cat-food" target="_blank" rel="noopener"
 &gt;療法食のカリカリ&lt;/a&gt;を食べさせてるので, ちゃんと食べてくれないと困る&amp;hellip;&lt;/p&gt;
&lt;p&gt;獣医さんに相談しようか&amp;hellip;&lt;/p&gt;
&lt;h3 id="歯みがきの進捗"&gt;歯みがきの進捗
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2020-07-01-sotochan/#%E3%81%AF%E3%81%BF%E3%81%8C%E3%81%8D%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%84" target="_blank" rel="noopener"
 &gt;歯みがき苦手問題&lt;/a&gt;は少しだけ改善した.&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://www.lion-pet.jp/product/petkiss/kinou_finger_sheet_apple.htm" target="_blank" rel="noopener"
 &gt;歯みがきシート&lt;/a&gt;はあまりにも嫌がるので一旦やめて,&lt;br&gt;
&lt;a class="link" href="https://www.lion-pet.jp/product/petkiss/kinou_jel.htm" target="_blank" rel="noopener"
 &gt;歯みがきジェル&lt;/a&gt;を指に塗って直接磨くようにしたらおとなしく触らせてくれるようになった.&lt;/p&gt;
&lt;p&gt;匂いを嗅いでも嫌な顔しない.&lt;/p&gt;
&lt;p&gt;&lt;img alt="歯みがきジェル" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-08-03-sotochan/sotochan01.jpg" srcset="https://blog.uzimihsr.com/post/2020-08-03-sotochan/sotochan01_hu_e503950ad5f05a9.jpg 800w, https://blog.uzimihsr.com/post/2020-08-03-sotochan/sotochan01_hu_8ef4f307f05bdeb7.jpg 1600w, https://blog.uzimihsr.com/post/2020-08-03-sotochan/sotochan01_hu_c88d35a50749c59e.jpg 2400w, https://blog.uzimihsr.com/post/2020-08-03-sotochan/sotochan01.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;もうちょっと歯みがきジェルを使って慣れさせてから再度歯みがきシートに挑戦したい.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;そとちゃんは7月も元気だった.&lt;/p&gt;
&lt;p&gt;元気だけどもごはんをちゃんとたべなかったりするので,&lt;br&gt;
8月はいろいろ試して改善できるようにしたい.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="晩ごはんを食べて満足したねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-08-03-sotochan/sotochan02.jpg" srcset="https://blog.uzimihsr.com/post/2020-08-03-sotochan/sotochan02_hu_4656da3383732a6d.jpg 800w, https://blog.uzimihsr.com/post/2020-08-03-sotochan/sotochan02_hu_429292345a667423.jpg 1600w, https://blog.uzimihsr.com/post/2020-08-03-sotochan/sotochan02_hu_2e03bba103c25726.jpg 2400w, https://blog.uzimihsr.com/post/2020-08-03-sotochan/sotochan02.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>YAMLを使わずにkubectl run/createでサクッとリソースを作る</title><link>https://blog.uzimihsr.com/post/2020-07-29-kubectl-run-and-create/</link><pubDate>Wed, 29 Jul 2020 20:43:33 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-07-29-kubectl-run-and-create/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-07-29-kubectl-run-and-create/sotochan.jpg" alt="Featured image of post YAMLを使わずにkubectl run/createでサクッとリソースを作る" /&gt;&lt;h2 id="yamlめんどくさい"&gt;YAMLめんどくさい
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://www.cncf.io/certification/ckad/" target="_blank" rel="noopener"
 &gt;CKAD&lt;/a&gt;対策で&lt;a class="link" href="https://github.com/dgkanatsios/CKAD-exercises" target="_blank" rel="noopener"
 &gt;CKAD-exercises&lt;/a&gt;の問題をやってみたんだけどいちいちYAMLを書くのがめんどくさすぎたのでメモ.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;kubectl run&lt;/code&gt;と&lt;code&gt;kubectl create&lt;/code&gt;でだいたいのリソースは作れそう.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Pod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl run nginx --image&lt;span class="o"&gt;=&lt;/span&gt;nginx --restart&lt;span class="o"&gt;=&lt;/span&gt;Never
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Deployment&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create deployment nginx --image&lt;span class="o"&gt;=&lt;/span&gt;nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Job&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create job busybox --image&lt;span class="o"&gt;=&lt;/span&gt;busybox -- /bin/sh -c &lt;span class="s1"&gt;&amp;#39;date; echo Hello&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# CronJob&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create cronjob busybox --image&lt;span class="o"&gt;=&lt;/span&gt;busybox --schedule&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;*/10 * * * *&amp;#34;&lt;/span&gt; -- /bin/sh -c &lt;span class="s1"&gt;&amp;#39;date; echo Hello&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ConfigMap&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create configmap my-config --from-literal&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;key1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;config1 --from-literal&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;key2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;config2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Secret&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create secret generic my-secret --from-literal&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;key1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;supersecret --from-literal&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;key2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;topsecret&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Mojave 10.14&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/kubernetes/kubectl" target="_blank" rel="noopener"
 &gt;kubectl&lt;/a&gt; v1.14.6&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/kubernetes/kubernetes" target="_blank" rel="noopener"
 &gt;Kubernetes&lt;/a&gt; v1.14.10-gke.36&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やりかた"&gt;やりかた
&lt;/h2&gt;&lt;h3 id="pod"&gt;Pod
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;kubectl run&lt;/code&gt;のオプションで&lt;code&gt;--restart=Never&lt;/code&gt;をつけてあげると&lt;code&gt;Pod&lt;/code&gt;が作成できる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# nginxのPodを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl run nginx --image&lt;span class="o"&gt;=&lt;/span&gt;nginx --restart&lt;span class="o"&gt;=&lt;/span&gt;Never
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/nginx created&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;Pod&lt;/code&gt;と同時に&lt;code&gt;Service&lt;/code&gt;(&lt;code&gt;ClusterIP&lt;/code&gt;)を作成することもできる.&lt;br&gt;
また, 使い捨ての&lt;code&gt;Pod&lt;/code&gt;を作成することもできる.&lt;br&gt;
他の&lt;code&gt;Pod&lt;/code&gt;の疎通確認するときなんかに便利.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# PodとServiceを同時に作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl run nginx --image&lt;span class="o"&gt;=&lt;/span&gt;nginx --restart&lt;span class="o"&gt;=&lt;/span&gt;Never --port&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt; --expose
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/nginx created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/nginx created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get service nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nginx ClusterIP 10.4.0.85 &amp;lt;none&amp;gt; 80/TCP 14m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 使い捨てのbusyboxのPodでServiceの疎通確認をする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl run busybox --image&lt;span class="o"&gt;=&lt;/span&gt;busybox --restart&lt;span class="o"&gt;=&lt;/span&gt;Never --rm -it -- wget -O- 10.4.0.85:80
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Connecting to 10.4.0.85:80 &lt;span class="o"&gt;(&lt;/span&gt;10.4.0.85:80&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;writing to stdout
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;!DOCTYPE html&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;html&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;head&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;title&amp;gt;Welcome to nginx!&amp;lt;/title&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;written to stdout
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod &lt;span class="s2"&gt;&amp;#34;busybox&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 使い捨てのbusyboxのPodを作成してshに入る&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl run busybox --image&lt;span class="o"&gt;=&lt;/span&gt;busybox --restart&lt;span class="o"&gt;=&lt;/span&gt;Never --rm -it -- /bin/sh
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/ $ hostname
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;busybox
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/ $ &lt;span class="c1"&gt;# Ctrl+Dで抜ける&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod &lt;span class="s2"&gt;&amp;#34;busybox&amp;#34;&lt;/span&gt; deleted&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;実際の&lt;code&gt;Pod&lt;/code&gt;はつくらずにマニフェストのYAMLだけ生成することもできる.&lt;br&gt;
とりあえず下書きだけでも用意してさらに詳細な設定を書きたいときとかに便利.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podは作成せずYAMLだけを表示させる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl run nginx --image&lt;span class="o"&gt;=&lt;/span&gt;nginx --restart&lt;span class="o"&gt;=&lt;/span&gt;Never --port&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt; --env&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;key1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;value1 --limits&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;cpu=200m,memory=512Mi&amp;#39;&lt;/span&gt; --labels&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;v1 -o yaml --dry-run
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apiVersion: v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kind: Pod
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; creationTimestamp: null
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; labels:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; app: v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; containers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - env:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - name: key1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; value: value1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; image: nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ports:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - containerPort: &lt;span class="m"&gt;80&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; resources:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; limits:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cpu: 200m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; memory: 512Mi
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; dnsPolicy: ClusterFirst
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; restartPolicy: Never
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;status: &lt;span class="o"&gt;{}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="deployment"&gt;Deployment
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Pod&lt;/code&gt;以外のリソースは&lt;code&gt;kubectl create&lt;/code&gt;で作れる.&lt;br&gt;
&lt;code&gt;kubectl run&lt;/code&gt;でも作れるんだけど, Deprecatedなのであんまり使わないほうがよさそう.&lt;br&gt;
&lt;code&gt;kubectl create&lt;/code&gt;だと今の所レプリカ数を指定するオプションがないっぽいのが残念.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# kubectl runでのDeployment作成はDeprecatedらしい&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl run nginx --image&lt;span class="o"&gt;=&lt;/span&gt;nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl run --generator&lt;span class="o"&gt;=&lt;/span&gt;deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator&lt;span class="o"&gt;=&lt;/span&gt;run-pod/v1 or kubectl create instead.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps/nginx created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Deploymentを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create deployment nginx --image&lt;span class="o"&gt;=&lt;/span&gt;nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps/nginx created&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;kubectl run&lt;/code&gt;と同様に実際のリソース作成はせずYAMLだけ生成することもできる.&lt;br&gt;
こっちのほうが出番が多そう.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Deploymentを作成せずYAMLを表示させる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create deployment nginx --image&lt;span class="o"&gt;=&lt;/span&gt;nginx -o yaml --dry-run
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apiVersion: apps/v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kind: Deployment
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; creationTimestamp: null
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; labels:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; app: nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; replicas: &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; selector:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; matchLabels:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; app: nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; strategy: &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; template:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; metadata:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; creationTimestamp: null
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; labels:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; app: nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; spec:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; containers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - image: nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; resources: &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;status: &lt;span class="o"&gt;{}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="cronjob-job"&gt;CronJob, Job
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;CronJob&lt;/code&gt;と&lt;code&gt;Job&lt;/code&gt;も&lt;code&gt;Deployment&lt;/code&gt;と同様に作成できる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Jobの作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create job busybox --image&lt;span class="o"&gt;=&lt;/span&gt;busybox -- /bin/sh -c &lt;span class="s1"&gt;&amp;#39;date; echo Hello&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -l job-name&lt;span class="o"&gt;=&lt;/span&gt;busybox
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;busybox-rvsr9 0/1 Completed &lt;span class="m"&gt;0&lt;/span&gt; 34s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl logs busybox-rvsr9
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Tue Jul &lt;span class="m"&gt;28&lt;/span&gt; 14:48:24 UTC &lt;span class="m"&gt;2020&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Hello
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# CronJobの作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create cronjob busybox --image&lt;span class="o"&gt;=&lt;/span&gt;busybox --schedule&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;*/10 * * * *&amp;#34;&lt;/span&gt; -- /bin/sh -c &lt;span class="s1"&gt;&amp;#39;date; echo Hello&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;また, すでに存在する&lt;code&gt;CronJob&lt;/code&gt;から&lt;code&gt;Job&lt;/code&gt;部分だけを抜き出して作成することもできる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# CronJobからJobを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create job busybox --from&lt;span class="o"&gt;=&lt;/span&gt;cronjob/busybox -o yaml --dry-run
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apiVersion: batch/v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kind: Job
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; annotations:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cronjob.kubernetes.io/instantiate: manual
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; creationTimestamp: null
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: busybox
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; template:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; metadata:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; creationTimestamp: null
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; spec:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; containers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - command:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - /bin/sh
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - -c
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - date&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; Hello
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; image: busybox
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; imagePullPolicy: Always
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: busybox
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; resources: &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; terminationMessagePath: /dev/termination-log
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; terminationMessagePolicy: File
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; dnsPolicy: ClusterFirst
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; restartPolicy: OnFailure
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; schedulerName: default-scheduler
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; securityContext: &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; terminationGracePeriodSeconds: &lt;span class="m"&gt;30&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;status: &lt;span class="o"&gt;{}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="configmap-secret"&gt;ConfigMap, Secret
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;ConfigMap&lt;/code&gt;や&lt;code&gt;Secret&lt;/code&gt;も&lt;code&gt;kubectl create&lt;/code&gt;のオプションにKey-Valueの情報を渡して作ることができる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ConfigMapの作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create configmap my-config --from-literal&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;key1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;config1 --from-literal&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;key2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;config2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get configmap my-config -o &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;={&lt;/span&gt;.data.key1&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;config1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Secretの作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create secret generic my-secret --from-literal&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;key1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;supersecret --from-literal&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;key2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;topsecret
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get secret my-secret -o &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;={&lt;/span&gt;.data.key1&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; base64 -D
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;supersecret&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;kubectl run/create&lt;/code&gt;でかんたんなリソースが作れることを確認できた. いちいちYAMLを書く必要がないので便利.&lt;br&gt;
さらに&lt;code&gt;--dry-run&lt;/code&gt;と&lt;code&gt;-o yaml&lt;/code&gt;を使うとYAMLの雛形を生成できるので, 細かい設定を書きたい場合も便利に使えそう.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="あくびするねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-07-29-kubectl-run-and-create/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-07-29-kubectl-run-and-create/sotochan_hu_27c9bdf451acb3ae.jpg 800w, https://blog.uzimihsr.com/post/2020-07-29-kubectl-run-and-create/sotochan_hu_d3cf1337890f5552.jpg 1600w, https://blog.uzimihsr.com/post/2020-07-29-kubectl-run-and-create/sotochan_hu_71e82411e53a9d6d.jpg 2400w, https://blog.uzimihsr.com/post/2020-07-29-kubectl-run-and-create/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;h2 id="参考"&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/dgkanatsios/CKAD-exercises" target="_blank" rel="noopener"
 &gt;https://github.com/dgkanatsios/CKAD-exercises&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Kubernetes完全に理解したい 7章</title><link>https://blog.uzimihsr.com/post/2020-07-25-kubernetes-guide-chap7/</link><pubDate>Sat, 25 Jul 2020 17:57:31 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-07-25-kubernetes-guide-chap7/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-07-25-kubernetes-guide-chap7/sotochan.jpg" alt="Featured image of post Kubernetes完全に理解したい 7章" /&gt;&lt;h2 id="configmapとかsecretとか"&gt;ConfigMapとかSecretとか
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://book.impress.co.jp/books/1118101055" target="_blank" rel="noopener"
 &gt;Kubernetes完全ガイド&lt;/a&gt;の続き.&lt;br&gt;
ConfigMapとかSecretとか, Podから利用できるリソースの話.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="読んだもの"&gt;読んだもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://book.impress.co.jp/books/1118101055" target="_blank" rel="noopener"
 &gt;Kubernetes完全ガイド&lt;/a&gt; 7章(Config &amp;amp; Storageリソース)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;重要そうなところとかよく使いそうなところだけまとめる.&lt;/p&gt;
&lt;h2 id="読んだことのまとめ"&gt;読んだことのまとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#configmap" &gt;ConfigMap&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#secret" &gt;Secret&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#volume" &gt;Volume&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#persistentvolume" &gt;PersistentVolume&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#persistentvolumeclaim" &gt;PersistentVolumeClaim&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="configmap"&gt;ConfigMap
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Pod&lt;/code&gt;から利用できる情報をKey-Value形式で保持するリソース.&lt;br&gt;
平文ファイル, 直接入力, マニフェストファイル(YAML)の3種類の方法で作成できる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 平文ファイルからConfigMapを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat config.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;abc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;def
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ghi
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;1234&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create configmap --save-config sample-configmap-01 --from-file&lt;span class="o"&gt;=&lt;/span&gt;./config.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;configmap/sample-configmap-01 created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# kubectlで値を直接入力してConfigMapを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create configmap --save-config web-config &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --from-literal&lt;span class="o"&gt;=&lt;/span&gt;connection.max&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --from-literal&lt;span class="o"&gt;=&lt;/span&gt;connection.min&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;configmap/web-config created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# マニフェストファイルから作成する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f sample-configmap.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;configmap/sample-configmap created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 値がKey-Value形式で保存されている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get configmap sample-configmap-01 -o json &lt;span class="p"&gt;|&lt;/span&gt; jq &lt;span class="s1"&gt;&amp;#39;.data&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;config.txt&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;abc\ndef\nghi\n1234\n&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get configmap web-config -o json &lt;span class="p"&gt;|&lt;/span&gt; jq &lt;span class="s1"&gt;&amp;#39;.data&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;connection.max&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;100&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;connection.min&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get configmap sample-configmap -o json &lt;span class="p"&gt;|&lt;/span&gt; jq &lt;span class="s1"&gt;&amp;#39;.data&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;connection.max&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;100&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;connection.min&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;nginx.conf&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;user nginx;\nworker_processes auto;\nerror_log /var/log/nginx/error.log;\npid /run/nginx.pid;\n&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;sample.properties&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;property.1=value-1\nproperty.2=value-2\nproperty.3=value-3\n&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;thread&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;16&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/master/samples/chapter07/sample-configmap.yaml" target="_blank" rel="noopener"
 &gt;sample-configmap.yaml&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;作成した&lt;code&gt;ConfigMap&lt;/code&gt;は&lt;code&gt;Pod&lt;/code&gt;から環境変数またはマウントしたファイルとして扱うことができる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ConfigMap(sample-configmap)のValue(Key=connection.max)が環境変数CONNECTION_MAXとして利用されている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pod sample-configmap-single-env -o json &lt;span class="p"&gt;|&lt;/span&gt; jq &lt;span class="s1"&gt;&amp;#39;.spec.containers[].env[]&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;CONNECTION_MAX&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;valueFrom&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;configMapKeyRef&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;connection.max&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;sample-configmap&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it sample-configmap-single-env env &lt;span class="p"&gt;|&lt;/span&gt; grep CONNECTION_MAX
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;CONNECTION_MAX&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ConfigMap(sample-configmap)のKey-ValueがVolume(config-volume)として/configにマウントされている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pod sample-configmap-multi-volume -o json &lt;span class="p"&gt;|&lt;/span&gt; jq &lt;span class="s1"&gt;&amp;#39;.spec.volumes[0]&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;configMap&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;defaultMode&amp;#34;&lt;/span&gt;: 420,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;sample-configmap&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;config-volume&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pod sample-configmap-multi-volume -o json &lt;span class="p"&gt;|&lt;/span&gt; jq &lt;span class="s1"&gt;&amp;#39;.spec.containers[0].volumeMounts[0]&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;mountPath&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;/config&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;config-volume&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it sample-configmap-multi-volume ls /config
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;connection.max	connection.min	nginx.conf sample.properties thread
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it sample-configmap-multi-volume cat /config/nginx.conf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;user nginx&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;worker_processes auto&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;error_log /var/log/nginx/error.log&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pid /run/nginx.pid&lt;span class="p"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/master/samples/chapter07/sample-configmap-single-env.yaml" target="_blank" rel="noopener"
 &gt;sample-configmap-single-env.yaml&lt;/a&gt;&lt;br&gt;
&lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/master/samples/chapter07/sample-configmap-multi-volume.yaml" target="_blank" rel="noopener"
 &gt;sample-configmap-multi-volume.yaml&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="secret"&gt;Secret
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;ConfigMap&lt;/code&gt;とは異なり, 秘密情報を扱うためのリソース.&lt;br&gt;
対応する&lt;code&gt;Secret&lt;/code&gt;を利用する&lt;code&gt;Pod&lt;/code&gt;がある場合のみ&lt;code&gt;etcd&lt;/code&gt;から&lt;code&gt;Node&lt;/code&gt;の一時的な領域(&lt;code&gt;tmpfs&lt;/code&gt;)にKey-Valueのデータが送られるようになっているので, &lt;code&gt;ConfigMap&lt;/code&gt;に比べて機密性が高い.&lt;br&gt;
また, 安全のためにKey-ValueのValueがbase64エンコードされていて少し見えにくくなっている.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Opaque&lt;/code&gt;タイプの&lt;code&gt;Secret&lt;/code&gt;は基本的に&lt;code&gt;ConfigMap&lt;/code&gt;と同じような使い方ができる.&lt;br&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 平文ファイルからSecretを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; -n &lt;span class="s2"&gt;&amp;#34;root&amp;#34;&lt;/span&gt; &amp;gt; ./username
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; -n &lt;span class="s2"&gt;&amp;#34;rootpassword&amp;#34;&lt;/span&gt; &amp;gt; ./password
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create secret generic --save-config sample-db-auth-from-file &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --from-file&lt;span class="o"&gt;=&lt;/span&gt;./username --from-file&lt;span class="o"&gt;=&lt;/span&gt;./password
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;secret/sample-db-auth-from-file created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# envfileからSecretを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat &lt;span class="s"&gt;&amp;lt;&amp;lt; &amp;#39;EOF&amp;#39; &amp;gt; env-secret.txt
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;username=root
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;password=rootpassword
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create secret generic --save-config sample-db-auth-from-env-file &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --from-env-file ./env-secret.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;secret/sample-db-auth-from-env-file created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# kubectlで値を直接入力してSecretを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create secret generic --save-config sample-db-auth-from-literal &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --from-literal&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;root --from-literal&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;rootpassword
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;secret/sample-db-auth-from-literal created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# マニフェストファイルからSecretを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f sample-db-auth.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;secret/sample-db-auth created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# describeしても見えない&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl describe secret sample-db-auth-from-literal
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: sample-db-auth-from-literal
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Type: Opaque
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;Data&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;====&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;password: &lt;span class="m"&gt;12&lt;/span&gt; bytes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;username: &lt;span class="m"&gt;4&lt;/span&gt; bytes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 中身はbase64エンコードされている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get secret sample-db-auth-from-literal -o json &lt;span class="p"&gt;|&lt;/span&gt; jq &lt;span class="s1"&gt;&amp;#39;.data&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;password&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;cm9vdHBhc3N3b3Jk&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;username&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;cm9vdA==&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get secret sample-db-auth-from-literal -o json &lt;span class="p"&gt;|&lt;/span&gt; jq -r &lt;span class="s1"&gt;&amp;#39;.data.username&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; base64 -D
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;root
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get secret sample-db-auth-from-literal -o json &lt;span class="p"&gt;|&lt;/span&gt; jq -r &lt;span class="s1"&gt;&amp;#39;.data.password&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; base64 -D
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rootpassword&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/master/samples/chapter07/sample-db-auth.yaml" target="_blank" rel="noopener"
 &gt;sample-db-auth.yaml&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Ingress&lt;/code&gt;などからTLSに必要な証明書と秘密鍵を扱うための&lt;code&gt;kubernetes.io/tls&lt;/code&gt;タイプの&lt;code&gt;Secret&lt;/code&gt;もある.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 秘密鍵(tls.key)とオレオレ証明書(tls.crt)を同時に作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl req -x509 -nodes -days &lt;span class="m"&gt;365&lt;/span&gt; -newkey rsa:2048 &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -keyout ./tls.key -out ./tls.crt -subj &lt;span class="s2"&gt;&amp;#34;/CN=sample1.example.com&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Generating a &lt;span class="m"&gt;2048&lt;/span&gt; bit RSA private key
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;......+++
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.........................................................................................................................................................................................................+++
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;writing new private key to &lt;span class="s1"&gt;&amp;#39;./tls.key&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-----
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tls.crt tls.key
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 秘密鍵と証明書からSecretを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create secret tls --save-config tls-sample --key ./tls.key --cert ./tls.crt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;secret/tls-sample created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 秘密鍵と証明書のpemをbase64エンコードしたものが登録されている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get secret tls-sample -o json &lt;span class="p"&gt;|&lt;/span&gt; jq &lt;span class="s1"&gt;&amp;#39;.data&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;tls.crt&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;LS0tLS...tLS0K&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;tls.key&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;LS0tLS...tLS0K&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get secret tls-sample -o json &lt;span class="p"&gt;|&lt;/span&gt; jq -r .data&lt;span class="s1"&gt;&amp;#39;[&amp;#34;tls.crt&amp;#34;]&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; base64 -D &lt;span class="p"&gt;|&lt;/span&gt; openssl x509 -noout -text
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Certificate:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Data:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Version: &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;0x0&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Serial Number: &lt;span class="m"&gt;12508610311645361173&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;0xad9782ce1368f415&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Signature Algorithm: sha256WithRSAEncryption
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Issuer: &lt;span class="nv"&gt;CN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample1.example.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Validity
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Not Before: Jul &lt;span class="m"&gt;8&lt;/span&gt; 14:54:37 &lt;span class="m"&gt;2020&lt;/span&gt; GMT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Not After : Jul &lt;span class="m"&gt;8&lt;/span&gt; 14:54:37 &lt;span class="m"&gt;2021&lt;/span&gt; GMT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Subject: &lt;span class="nv"&gt;CN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample1.example.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;DockerHub&lt;/code&gt;のプライベートリポジトリなど, 認証のかかった&lt;code&gt;Docker&lt;/code&gt;レジストリから&lt;code&gt;image&lt;/code&gt;を取得するための認証情報を扱う場合は&lt;code&gt;kubernetes.io/dockerconfigjson&lt;/code&gt;タイプの&lt;code&gt;Secret&lt;/code&gt;を使用する.&lt;br&gt;
&lt;code&gt;Pod&lt;/code&gt;から認証がかかったリポジトリの&lt;code&gt;image&lt;/code&gt;をpullするにはマニフェストファイルの&lt;code&gt;.spec.imagePullSecrets&lt;/code&gt;に&lt;code&gt;Secret&lt;/code&gt;名を指定する(例 : &lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/master/samples/chapter07/sample-pull-secret.yaml" target="_blank" rel="noopener"
 &gt;sample-pull-secret.yaml&lt;/a&gt;).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 認証情報からSecretを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create secret docker-registry --save-config sample-registry-auth &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --docker-server&lt;span class="o"&gt;=&lt;/span&gt;SERVER &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --docker-username&lt;span class="o"&gt;=&lt;/span&gt;USER &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --docker-password&lt;span class="o"&gt;=&lt;/span&gt;PASSWORD &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --docker-email&lt;span class="o"&gt;=&lt;/span&gt;EMAIL
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;secret/sample-registry-auth created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# dockercfg形式の認証情報が保存されている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get secret sample-registry-auth -o json &lt;span class="p"&gt;|&lt;/span&gt; jq -r .data&lt;span class="s1"&gt;&amp;#39;[&amp;#34;.dockerconfigjson&amp;#34;]&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; base64 -D
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;auths&amp;#34;&lt;/span&gt;:&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;SERVER&amp;#34;&lt;/span&gt;:&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;username&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;USER&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;password&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;PASSWORD&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;email&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;EMAIL&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;auth&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;VVNFUjpQQVNTV09SRA==&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}}}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;作成した&lt;code&gt;Secret&lt;/code&gt;は&lt;code&gt;Pod&lt;/code&gt;から環境変数またはマウントしたファイルとして扱うことができる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Secret(sample-db-auth)のValue(Key=username)が環境変数DB_USERNAMEとして利用されている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pod sample-secret-single-env -o json &lt;span class="p"&gt;|&lt;/span&gt; jq &lt;span class="s1"&gt;&amp;#39;.spec.containers[].env[]&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;DB_USERNAME&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;valueFrom&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;secretKeyRef&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;username&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;sample-db-auth&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it sample-secret-single-env env &lt;span class="p"&gt;|&lt;/span&gt; grep DB_USERNAME
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;DB_USERNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;root
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Secret(sample-db-auth)のKey-ValueがVolume(config-volume)として/configにマウントされている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pod sample-secret-multi-volume -o json &lt;span class="p"&gt;|&lt;/span&gt; jq &lt;span class="s1"&gt;&amp;#39;.spec.volumes[0]&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;config-volume&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;secret&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;defaultMode&amp;#34;&lt;/span&gt;: 420,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;secretName&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;sample-db-auth&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pod sample-secret-multi-volume -o json &lt;span class="p"&gt;|&lt;/span&gt; jq &lt;span class="s1"&gt;&amp;#39;.spec.containers[].volumeMounts[0]&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;mountPath&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;/config&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;config-volume&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it sample-secret-multi-volume ls /config
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;password username
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it sample-secret-multi-volume cat /config/username
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;root&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="volume"&gt;Volume
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Pod&lt;/code&gt;からディスクを扱うためのリソース.&lt;br&gt;
いくつか種類があるが, どれも&lt;code&gt;Pod&lt;/code&gt;上に静的に領域を指定して使用する.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;emptyDir&lt;/code&gt;は&lt;code&gt;Pod&lt;/code&gt;に一時的なディスク領域を作成し, &lt;code&gt;Pod&lt;/code&gt;が終了すると同時に削除される.&lt;br&gt;
&lt;code&gt;Pod&lt;/code&gt;内の複数のコンテナ間でファイルを共有したりするのに使える.&lt;br&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# emptyDirが /cache にマウントされている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pod sample-emptydir -o json &lt;span class="p"&gt;|&lt;/span&gt; jq &lt;span class="s1"&gt;&amp;#39;.spec.volumes[0]&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;emptyDir&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;cache-volume&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pod sample-emptydir -o json &lt;span class="p"&gt;|&lt;/span&gt; jq &lt;span class="s1"&gt;&amp;#39;.spec.containers[0].volumeMounts[0]&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;mountPath&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;/cache&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;cache-volume&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 中身は空&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it sample-emptydir -- ls -la /cache
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;total &lt;span class="m"&gt;8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;drwxrwxrwx &lt;span class="m"&gt;2&lt;/span&gt; root root &lt;span class="m"&gt;4096&lt;/span&gt; Jul &lt;span class="m"&gt;9&lt;/span&gt; 14:26 .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;drwxr-xr-x &lt;span class="m"&gt;1&lt;/span&gt; root root &lt;span class="m"&gt;4096&lt;/span&gt; Jul &lt;span class="m"&gt;9&lt;/span&gt; 14:26 ..&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/master/samples/chapter07/sample-emptydir.yaml" target="_blank" rel="noopener"
 &gt;sample-emptydir.yaml&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;hostPath&lt;/code&gt;は&lt;code&gt;Node&lt;/code&gt;上の領域を指定して&lt;code&gt;Pod&lt;/code&gt;のコンテナにマウントする.&lt;br&gt;
&lt;code&gt;Node&lt;/code&gt;に直接影響を与えるので扱いには注意が必要.&lt;br&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Node(gke-k8s-01-pool-2-641104a4-7r06)の /etc が /srv としてPodにマウントされている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pod sample-hostpath -o wide
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-hostpath 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 3m22s 10.0.1.5 gke-k8s-01-pool-2-641104a4-7r06 &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pod sample-hostpath -o json &lt;span class="p"&gt;|&lt;/span&gt; jq &lt;span class="s1"&gt;&amp;#39;.spec.volumes[0]&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;hostPath&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;path&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;/etc&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;DirectoryOrCreate&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;hostpath-sample&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pod sample-hostpath -o json &lt;span class="p"&gt;|&lt;/span&gt; jq &lt;span class="s1"&gt;&amp;#39;.spec.containers[0].volumeMounts[0]&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;mountPath&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;/srv&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;hostpath-sample&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# マウントしたNodeの領域にアクセスする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it sample-hostpath cat /srv/os-release &lt;span class="p"&gt;|&lt;/span&gt; grep PRETTY_NAME
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;PRETTY_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Container-Optimized OS from Google&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# NodeのOS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# コンテナ自体の領域にアクセスする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it sample-hostpath cat /etc/os-release &lt;span class="p"&gt;|&lt;/span&gt; grep PRETTY_NAME
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;PRETTY_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Debian GNU/Linux 9 (stretch)&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# コンテナのOS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 実際にNodeの同じ領域のファイルを確認する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ gcloud compute ssh gke-k8s-01-pool-2-641104a4-7r06
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gke-k8s-01-pool-2-641104a4-7r06 ~ $ cat /etc/os-release &lt;span class="p"&gt;|&lt;/span&gt; grep PRETTY_NAME
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;PRETTY_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Container-Optimized OS from Google&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/master/samples/chapter07/sample-hostpath.yaml" target="_blank" rel="noopener"
 &gt;sample-hostpath.yaml&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;downwardAPI&lt;/code&gt;は&lt;code&gt;Pod&lt;/code&gt;の情報を&lt;code&gt;Pod&lt;/code&gt;上の領域にファイルとして配置する.&lt;br&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# /srv/podnameと/srv/cpu-requestにmetadata.nameとrequests.cpuの値がファイルとして配置されている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pod sample-downward-api -o json &lt;span class="p"&gt;|&lt;/span&gt; jq &lt;span class="s1"&gt;&amp;#39;.spec.volumes[0]&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;downwardAPI&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;defaultMode&amp;#34;&lt;/span&gt;: 420,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;items&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;fieldRef&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;apiVersion&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;v1&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;fieldPath&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;metadata.name&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;path&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;podname&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;path&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;cpu-request&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;resourceFieldRef&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;containerName&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;nginx-container&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;divisor&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;0&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;resource&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;requests.cpu&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;downward-api-volume&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pod sample-downward-api -o json &lt;span class="p"&gt;|&lt;/span&gt; jq &lt;span class="s1"&gt;&amp;#39;.spec.containers[0].volumeMounts[0]&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;mountPath&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;/srv&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;downward-api-volume&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ファイルを確認する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it sample-downward-api cat /srv/podname
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-downward-api
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it sample-downward-api cat /srv/cpu-request
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/master/samples/chapter07/sample-downward-api.yaml" target="_blank" rel="noopener"
 &gt;sample-downward-api.yaml&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;projected&lt;/code&gt;は複数の&lt;code&gt;Volume&lt;/code&gt;, &lt;code&gt;Secret&lt;/code&gt;, &lt;code&gt;ConfigMap&lt;/code&gt;などを1つの&lt;code&gt;volumeMounts&lt;/code&gt;にまとめる.&lt;br&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Secret(sample-db-auth), ConfigMap(sample-configmap), downwardAPIが /srv にまとめてマウントされている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get secret sample-db-auth
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME TYPE DATA AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-db-auth Opaque &lt;span class="m"&gt;2&lt;/span&gt; 24h
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get configmap sample-configmap
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME DATA AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-configmap &lt;span class="m"&gt;5&lt;/span&gt; 12d
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pod sample-projected -o yaml &lt;span class="p"&gt;|&lt;/span&gt; yq &lt;span class="nb"&gt;read&lt;/span&gt; - &lt;span class="s1"&gt;&amp;#39;spec.volumes[0]&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;name: projected-volume
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;projected:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; defaultMode: &lt;span class="m"&gt;420&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; sources:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - secret:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; items:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - key: username
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; path: secret/username.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: sample-db-auth
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - configMap:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; items:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - key: nginx.conf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; path: configmap/nginx.conf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: sample-configmap
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - downwardAPI:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; items:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - fieldRef:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; apiVersion: v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; fieldPath: metadata.name
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; path: podname
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pod sample-projected -o yaml &lt;span class="p"&gt;|&lt;/span&gt; yq &lt;span class="nb"&gt;read&lt;/span&gt; - &lt;span class="s1"&gt;&amp;#39;spec.containers[0].volumeMounts[0]&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mountPath: /srv
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;name: projected-volume
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 中身を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it sample-projected ls /srv
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;configmap podname secret
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it sample-projected cat /srv/secret/username.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;root
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it sample-projected cat /srv/configmap/nginx.conf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;user nginx&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;worker_processes auto&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;error_log /var/log/nginx/error.log&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pid /run/nginx.pid&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it sample-projected cat /srv/podname
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-projected&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/master/samples/chapter07/sample-projected.yaml" target="_blank" rel="noopener"
 &gt;sample-projected.yaml&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="persistentvolume"&gt;PersistentVolume
&lt;/h3&gt;&lt;p&gt;永続化領域を扱うための&lt;code&gt;Volume&lt;/code&gt;で, 個別のリソースとして扱う.&lt;br&gt;
ネットワーク経由で&lt;code&gt;Pod&lt;/code&gt;等から利用するため, アクセス可能な場所にディスクを用意する必要がある.&lt;br&gt;
(&lt;code&gt;Ingress&lt;/code&gt;みたいな感じ?)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# GCPでディスクを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ gcloud compute disks create --size&lt;span class="o"&gt;=&lt;/span&gt;10GB sample-gce-pv --zone us-central1-a
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME ZONE SIZE_GB TYPE STATUS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-gce-pv us-central1-a &lt;span class="m"&gt;10&lt;/span&gt; pd-standard READY
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# PersistentVolume(sample-pv)を作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f sample-pv.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;persistentvolume/sample-pv created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pv sample-pv
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-pv 10Gi RWO Retain Available manual 56s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/master/samples/chapter07/sample-pv.yaml" target="_blank" rel="noopener"
 &gt;sample-pv.yaml&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="persistentvolumeclaim"&gt;PersistentVolumeClaim
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Pod&lt;/code&gt;等から利用できる&lt;code&gt;PersistentVolume&lt;/code&gt;を払い出すためのリソース.&lt;br&gt;
クラスタが認識している&lt;code&gt;PersistentVolume&lt;/code&gt;の中で&lt;code&gt;PersistentVolumeClaim&lt;/code&gt;の条件に合ったものが&lt;code&gt;Pod&lt;/code&gt;に接続される.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# PersistentVolume(sample-pv)が存在する状態でPersistentVolumeClaim(sample-pvc)を作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f sample-pvc.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;persistentvolumeclaim/sample-pvc created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pvc sample-pvc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-pvc Bound sample-pv 10Gi RWO manual 26s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# PersistentVolume(sample-pv)がsample-pvcに確保(Bound)されている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pv sample-pv
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-pv 10Gi RWO Retain Bound default/sample-pvc manual 111s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podの/usr/share/nginx/htmlにsample-pvcで払い出されたPersistentVolumeがマウントされている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pod sample-pvc-pod -o yaml &lt;span class="p"&gt;|&lt;/span&gt; yq &lt;span class="nb"&gt;read&lt;/span&gt; - &lt;span class="s1"&gt;&amp;#39;spec.volumes[0]&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;name: nginx-pvc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;persistentVolumeClaim:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; claimName: sample-pvc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pod sample-pvc-pod -o yaml &lt;span class="p"&gt;|&lt;/span&gt; yq &lt;span class="nb"&gt;read&lt;/span&gt; - &lt;span class="s1"&gt;&amp;#39;spec.containers[0].volumeMounts[0]&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mountPath: /usr/share/nginx/html
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;name: nginx-pvc&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/master/samples/chapter07/sample-pvc.yaml" target="_blank" rel="noopener"
 &gt;sample-pvc.yaml&lt;/a&gt;&lt;br&gt;
&lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/master/samples/chapter07/sample-pvc-pod.yaml" target="_blank" rel="noopener"
 &gt;sample-pvc-pod.yaml&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;また, &lt;code&gt;StorageClass&lt;/code&gt;の設定によっては,&lt;br&gt;
事前に&lt;code&gt;PersistentVolume&lt;/code&gt;を用意しなくても&lt;code&gt;PersistentVolumeClaim&lt;/code&gt;に応じた&lt;code&gt;PersistentVolume&lt;/code&gt;を自動で払い出すことができる(&lt;code&gt;Dynamic Provisioning&lt;/code&gt;).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# GKEのデフォルトStorageClass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl describe sc standard
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: standard
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IsDefaultClass: Yes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: storageclass.kubernetes.io/is-default-class&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Provisioner: kubernetes.io/gce-pd
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Parameters: &lt;span class="nv"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;pd-standard
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;AllowVolumeExpansion: True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;MountOptions: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ReclaimPolicy: Delete
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VolumeBindingMode: Immediate
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# PersistentVolumeがない状態でStorageClassを指定しないPersistentVolumeClaimを作成する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pv
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;No resources found.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f sample-pvc-default-storageclass.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;persistentvolumeclaim/sample-pvc created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# GCPのディスクとPersistentVolumeが自動で払い出されている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pv
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pvc-332c4de9-ce56-11ea-a3f9-42010a80005d 4Gi RWO Delete Bound default/sample-pvc standard 69s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ gcloud compute disks list
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME LOCATION LOCATION_SCOPE SIZE_GB TYPE STATUS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gke-k8s-01-08fea67e-dy-pvc-332c4de9-ce56-11ea-a3f9-42010a80005d us-central1-a zone &lt;span class="m"&gt;4&lt;/span&gt; pd-standard READY
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 使用したPersistentVolumeClaimはsample-pvc.yamlを改変したもの&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat sample-pvc-default-storageclass.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kind: PersistentVolumeClaim
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apiVersion: v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: sample-pvc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; resources:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; requests:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; storage: 4Gi
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; accessModes:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - ReadWriteOnce&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="謎ポーズをきめるねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-07-25-kubernetes-guide-chap7/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-07-25-kubernetes-guide-chap7/sotochan_hu_e4cb2855a20471e0.jpg 800w, https://blog.uzimihsr.com/post/2020-07-25-kubernetes-guide-chap7/sotochan_hu_485372ab8fc43948.jpg 1600w, https://blog.uzimihsr.com/post/2020-07-25-kubernetes-guide-chap7/sotochan_hu_b279bcc1b31c73e7.jpg 2400w, https://blog.uzimihsr.com/post/2020-07-25-kubernetes-guide-chap7/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>GoでサイコロAPIを作る</title><link>https://blog.uzimihsr.com/post/2020-07-23-golang-dice-api/</link><pubDate>Thu, 23 Jul 2020 14:10:10 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-07-23-golang-dice-api/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-07-23-golang-dice-api/sotochan.jpg" alt="Featured image of post GoでサイコロAPIを作る" /&gt;&lt;h2 id="web-apiつくってみる"&gt;Web APIつくってみる
&lt;/h2&gt;&lt;p&gt;Web APIを自分で最初から作ったことがなかったので, Goの練習も兼ねてやってみた.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;p&gt;以下のようにランダムなサイコロの出目(&lt;code&gt;number&lt;/code&gt;)とサイコロの面の数(&lt;code&gt;faces&lt;/code&gt;)を&lt;code&gt;JSON&lt;/code&gt;で返すだけのWeb APIを&lt;code&gt;Go&lt;/code&gt;で作った.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 普通に叩くと6面サイコロを振る&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -X GET &lt;span class="s2"&gt;&amp;#34;localhost:8080&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;number&amp;#34;&lt;/span&gt;:1,&lt;span class="s2"&gt;&amp;#34;faces&amp;#34;&lt;/span&gt;:6&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -X GET &lt;span class="s2"&gt;&amp;#34;localhost:8080&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;number&amp;#34;&lt;/span&gt;:5,&lt;span class="s2"&gt;&amp;#34;faces&amp;#34;&lt;/span&gt;:6&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# クエリパラメータで面の数を指定できる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -X GET &lt;span class="s2"&gt;&amp;#34;localhost:8080?faces=100&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;number&amp;#34;&lt;/span&gt;:71,&lt;span class="s2"&gt;&amp;#34;faces&amp;#34;&lt;/span&gt;:100&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ズルをするためのエンドポイントも用意&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -X GET &lt;span class="s2"&gt;&amp;#34;localhost:8080/cheat&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;number&amp;#34;&lt;/span&gt;:6,&lt;span class="s2"&gt;&amp;#34;faces&amp;#34;&lt;/span&gt;:6&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -X GET &lt;span class="s2"&gt;&amp;#34;localhost:8080/cheat?faces=100&amp;amp;number=99&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;number&amp;#34;&lt;/span&gt;:99,&lt;span class="s2"&gt;&amp;#34;faces&amp;#34;&lt;/span&gt;:100&lt;span class="o"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Mojave 10.14&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/anyenv/anyenv" target="_blank" rel="noopener"
 &gt;anyenv&lt;/a&gt; 1.1.1
&lt;ul&gt;
&lt;li&gt;インストール済み&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/syndbg/goenv" target="_blank" rel="noopener"
 &gt;goenv&lt;/a&gt; 2.0.0beta11
&lt;ul&gt;
&lt;li&gt;インストール済み&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/golang/go" target="_blank" rel="noopener"
 &gt;go&lt;/a&gt; version go1.14.6 darwin/amd64
&lt;ul&gt;
&lt;li&gt;今回入れる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e6%ba%96%e5%82%99" &gt;準備&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%b5%e3%82%a4%e3%82%b3%e3%83%ad%e3%81%ae%e4%bd%9c%e6%88%90" &gt;サイコロの作成&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#http%e3%83%8f%e3%83%b3%e3%83%89%e3%83%a9%e3%81%ae%e4%bd%9c%e6%88%90" &gt;HTTPハンドラの作成&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%86%e3%82%b9%e3%83%88%e3%81%ae%e4%bd%9c%e6%88%90" &gt;テストの作成&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="準備"&gt;準備
&lt;/h3&gt;&lt;p&gt;まずは開発環境の準備.&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://golang.org/doc/devel/release.html" target="_blank" rel="noopener"
 &gt;公式&lt;/a&gt;によると現在(2020/07/16)&lt;code&gt;Go&lt;/code&gt;の最新版が &lt;strong&gt;1.14.6&lt;/strong&gt; なので, これを使うようにする.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# goenvの更新&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ anyenv install goenv
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;anyenv: /Users/uzimihsr/.anyenv/envs/goenv already exists
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Reinstallation keeps versions directories
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;continue&lt;/span&gt; with installation? &lt;span class="o"&gt;(&lt;/span&gt;y/N&lt;span class="o"&gt;)&lt;/span&gt; y
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Install goenv succeeded!
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Please reload your profile &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nv"&gt;$SHELL&lt;/span&gt; -l&lt;span class="o"&gt;)&lt;/span&gt; or open a new session.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nv"&gt;$SHELL&lt;/span&gt; -l
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Go 1.14.6のインストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ goenv install 1.14.6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ goenv global 1.14.6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ goenv rehash
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nv"&gt;$SHELL&lt;/span&gt; -l
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ goenv version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1.14.6 &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; by /Users/uzimihsr/.anyenv/envs/goenv/version&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;go version go1.14.6 darwin/amd64
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$GOPATH&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/Users/uzimihsr/go/1.14.6&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;次にGitHubリポジトリを&lt;a class="link" href="https://github.com/new" target="_blank" rel="noopener"
 &gt;新規作成&lt;/a&gt;する.&lt;br&gt;
&lt;img alt="GitHub" class="gallery-image" data-flex-basis="276px" data-flex-grow="115" height="1290" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-07-23-golang-dice-api/sc01.png" srcset="https://blog.uzimihsr.com/post/2020-07-23-golang-dice-api/sc01_hu_be95444e9074e0c1.png 800w, https://blog.uzimihsr.com/post/2020-07-23-golang-dice-api/sc01.png 1486w" width="1486"&gt;&lt;/p&gt;
&lt;p&gt;作ったリポジトリ : &lt;a class="link" href="https://github.com/uzimihsr/dice-api" target="_blank" rel="noopener"
 &gt;https://github.com/uzimihsr/dice-api&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;作成したリポジトリをローカルにcloneして, &lt;code&gt;Go Modules&lt;/code&gt;とか&lt;code&gt;.gitignore&lt;/code&gt;の準備をする.&lt;br&gt;
&lt;code&gt;Go Modules&lt;/code&gt;の使い方は&lt;a class="link" href="https://github.com/golang/go/wiki/Modules#example" target="_blank" rel="noopener"
 &gt;公式&lt;/a&gt;を参考にする.&lt;br&gt;
&lt;code&gt;.gitignore&lt;/code&gt;は&lt;a class="link" href="https://www.toptal.com/developers/gitignore" target="_blank" rel="noopener"
 &gt;gitignore.io&lt;/a&gt;を使って作るのが楽.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 適当なディレクトリで作業&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; workspace
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git clone https://github.com/uzimihsr/dice-api.git
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Cloning into &lt;span class="s1"&gt;&amp;#39;dice-api&amp;#39;&lt;/span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;warning: You appear to have cloned an empty repository.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; dice-api
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Go Moduleの初期化&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go mod init github.com/uzimihsr/dice-api
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;go: creating new go.mod: module github.com/uzimihsr/dice-api
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;go.mod
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# gitignore.ioのAPIを利用して.gitignoreを作成する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -o ./.gitignore https://www.toptal.com/developers/gitignore/api/go,macos,linux
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# いったんpushしておく&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;# dice-api&amp;#34;&lt;/span&gt; &amp;gt; README.md
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git add .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git commit -m &lt;span class="s2"&gt;&amp;#34;first commit&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git push origin master&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;このときのリポジトリは&lt;a class="link" href="https://github.com/uzimihsr/dice-api/tree/f484784bcd1b569fcf1bc77cd882263ea809b715" target="_blank" rel="noopener"
 &gt;こんなかんじ&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="サイコロの作成"&gt;サイコロの作成
&lt;/h3&gt;&lt;p&gt;まずはサイコロの動作を作ってみる.&lt;br&gt;
&lt;a class="link" href="https://uzimihsr.github.io/post/2019-09-04-golang-dice/" target="_blank" rel="noopener"
 &gt;以前作ったもの&lt;/a&gt;を流用する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mkdir dice &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; dice
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim dice.go&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;今回は普通にサイコロの出目を返すメソッド&lt;code&gt;Roll()&lt;/code&gt;の他に指定した出目を返す&lt;code&gt;Cheat()&lt;/code&gt;を作ってみた.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/6f9b3cc44bae4b4b0738bbe29585e390.js"&gt;&lt;/script&gt;
&lt;p&gt;ためしに動かしてみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; ..
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim main.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go run main.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go run main.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;script src="https://gist.github.com/uzimihsr/d3d4cf0ef43f6de5faee53417c6c2aa6.js"&gt;&lt;/script&gt;
&lt;p&gt;いい感じ.&lt;/p&gt;
&lt;h3 id="httpハンドラの作成"&gt;HTTPハンドラの作成
&lt;/h3&gt;&lt;p&gt;次にこれをWeb APIとして動かすためのハンドラ関数を作る.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mkdir handler &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; handler
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim handler.go&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;ポイントはハンドラ関数&lt;code&gt;DiceHandler()&lt;/code&gt;, &lt;code&gt;CheatDiceHandler()&lt;/code&gt;の引数で&lt;code&gt;interface&lt;/code&gt;を受けるようにしているところ.&lt;br&gt;
こうしておくと後でテストを書くときにmockを使いやすくなる.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/f5029b7b42805a0ea6c5820aa6df099c.js"&gt;&lt;/script&gt;
&lt;p&gt;これらのハンドラ関数を扱ってHTTPサーバーを動かすため, &lt;code&gt;main.go&lt;/code&gt;を修正する.&lt;br&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; ..
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim main.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go run main.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 動作を確認したら Ctrl+C で終了&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;こちらは&lt;code&gt;http.NewServeMux()&lt;/code&gt;を使ってリクエストパスごとに異なるハンドラを呼び出すようにしているのがポイント.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/d56241bed0c022585885812c438d068f.js"&gt;&lt;/script&gt;
&lt;p&gt;&lt;code&gt;main.go&lt;/code&gt;を実行するとMacの警告が出るので, &lt;code&gt;許可&lt;/code&gt;を選択するとアプリが動く.&lt;br&gt;
&lt;img alt="許可する" class="gallery-image" data-flex-basis="425px" data-flex-grow="177" height="600" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-07-23-golang-dice-api/sc02.png" srcset="https://blog.uzimihsr.com/post/2020-07-23-golang-dice-api/sc02_hu_acf5f7e3b8b2287b.png 800w, https://blog.uzimihsr.com/post/2020-07-23-golang-dice-api/sc02.png 1064w" width="1064"&gt;&lt;/p&gt;
&lt;p&gt;試しに別のターミナルからAPIを叩いてみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 正常系&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl &lt;span class="s2"&gt;&amp;#34;localhost:8080&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;number&amp;#34;&lt;/span&gt;:1,&lt;span class="s2"&gt;&amp;#34;faces&amp;#34;&lt;/span&gt;:6&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl &lt;span class="s2"&gt;&amp;#34;localhost:8080?faces=12&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;number&amp;#34;&lt;/span&gt;:10,&lt;span class="s2"&gt;&amp;#34;faces&amp;#34;&lt;/span&gt;:12&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl &lt;span class="s2"&gt;&amp;#34;localhost:8080/cheat&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;number&amp;#34;&lt;/span&gt;:6,&lt;span class="s2"&gt;&amp;#34;faces&amp;#34;&lt;/span&gt;:6&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl &lt;span class="s2"&gt;&amp;#34;localhost:8080/cheat?number=1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;number&amp;#34;&lt;/span&gt;:1,&lt;span class="s2"&gt;&amp;#34;faces&amp;#34;&lt;/span&gt;:6&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl &lt;span class="s2"&gt;&amp;#34;localhost:8080/cheat?number=1&amp;amp;faces=18&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;number&amp;#34;&lt;/span&gt;:1,&lt;span class="s2"&gt;&amp;#34;faces&amp;#34;&lt;/span&gt;:18&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 異常系&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -i -X POST &lt;span class="s2"&gt;&amp;#34;localhost:8080&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;HTTP/1.1 &lt;span class="m"&gt;404&lt;/span&gt; Not Found
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Content-Type: application/json
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Date: Thu, &lt;span class="m"&gt;23&lt;/span&gt; Jul &lt;span class="m"&gt;2020&lt;/span&gt; 08:12:39 GMT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Content-Length: &lt;span class="m"&gt;24&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;message&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;not found&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -i -X GET &lt;span class="s2"&gt;&amp;#34;localhost:8080?faces=hoge&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;HTTP/1.1 &lt;span class="m"&gt;500&lt;/span&gt; Internal Server Error
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Content-Type: text/plain&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;charset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;utf-8
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;X-Content-Type-Options: nosniff
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Date: Thu, &lt;span class="m"&gt;23&lt;/span&gt; Jul &lt;span class="m"&gt;2020&lt;/span&gt; 08:13:04 GMT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Content-Length: &lt;span class="m"&gt;45&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;strconv.Atoi: parsing &lt;span class="s2"&gt;&amp;#34;hoge&amp;#34;&lt;/span&gt;: invalid syntax
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -i -X POST &lt;span class="s2"&gt;&amp;#34;localhost:8080/cheat&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;HTTP/1.1 &lt;span class="m"&gt;404&lt;/span&gt; Not Found
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Content-Type: application/json
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Date: Thu, &lt;span class="m"&gt;23&lt;/span&gt; Jul &lt;span class="m"&gt;2020&lt;/span&gt; 08:13:58 GMT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Content-Length: &lt;span class="m"&gt;24&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;message&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;not found&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -i -X GET &lt;span class="s2"&gt;&amp;#34;localhost:8080/cheat?number=hoge&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;HTTP/1.1 &lt;span class="m"&gt;500&lt;/span&gt; Internal Server Error
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Content-Type: text/plain&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;charset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;utf-8
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;X-Content-Type-Options: nosniff
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Date: Thu, &lt;span class="m"&gt;23&lt;/span&gt; Jul &lt;span class="m"&gt;2020&lt;/span&gt; 08:14:12 GMT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Content-Length: &lt;span class="m"&gt;45&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;strconv.Atoi: parsing &lt;span class="s2"&gt;&amp;#34;hoge&amp;#34;&lt;/span&gt;: invalid syntax&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;サイコロの出目(&lt;code&gt;number&lt;/code&gt;)と面の数(&lt;code&gt;faces&lt;/code&gt;)が&lt;code&gt;JSON&lt;/code&gt;で返ってきて,&lt;br&gt;
異常なクエリパラメータやHTTPメソッドでリクエストした場合には指定したステータスコード(&lt;strong&gt;404&lt;/strong&gt;, &lt;strong&gt;500&lt;/strong&gt;)が返ってくることが確認できた.&lt;br&gt;
やったぜ.&lt;/p&gt;
&lt;p&gt;このときのリポジトリは&lt;a class="link" href="https://github.com/uzimihsr/dice-api/tree/6048bc4d6a97fdadf30feea5408b0e981335c0ec" target="_blank" rel="noopener"
 &gt;こんなかんじ&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="テストの作成"&gt;テストの作成
&lt;/h3&gt;&lt;p&gt;作りたいものは作れたのでここで終わってもいいけど, せっかくなのでテストコードを書いてみる.&lt;/p&gt;
&lt;p&gt;まずは&lt;code&gt;dice&lt;/code&gt;パッケージから.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; ./dice
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim dice_test.go&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;カバレッジ100%になるように書いたけど, 無駄なテストも含まれている.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/bd3cfcba754fa444a9cd84f69ff96bbc.js"&gt;&lt;/script&gt;
&lt;p&gt;次に&lt;code&gt;handler&lt;/code&gt;パッケージのテストを作る.&lt;br&gt;
&lt;code&gt;handler&lt;/code&gt;パッケージは自作の&lt;code&gt;dice&lt;/code&gt;パッケージに依存しているので, &lt;code&gt;dice&lt;/code&gt;パッケージのmockを用意したい.&lt;br&gt;
(今回はDBとかに接続してないので&lt;code&gt;dice&lt;/code&gt;を直接呼び出してもいいんだけど, サイコロの出目が確率で変わっちゃうのでテストがしづらい)&lt;/p&gt;
&lt;p&gt;こんなときには&lt;a class="link" href="https://github.com/golang/mock" target="_blank" rel="noopener"
 &gt;gomock&lt;/a&gt;を使う.&lt;br&gt;
mockしたい&lt;code&gt;interface&lt;/code&gt;のファイルを指定するだけでmock用のコードを作成してくれるのでめちゃ便利.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# mockパッケージのインストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; ..
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go get github.com/golang/mock/mockgen
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# diceのmockを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mockgen -source ./dice/dice.go -destination ./mock_dice/mock_dice.go&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;script src="https://gist.github.com/uzimihsr/9d9ffc5382c8597eeee941e1058ebf10.js"&gt;&lt;/script&gt;
&lt;p&gt;このmockを使ったテストを書いてみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; handler
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim handler_test.go&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;準備したmockを各ハンドラ関数の引数に渡してやることで, 実際の&lt;code&gt;dice&lt;/code&gt;を呼び出すことなくハンドラ関数のテストができるようになる.&lt;br&gt;
ハンドラ関数を作るときに&lt;code&gt;dice&lt;/code&gt;の&lt;code&gt;interface&lt;/code&gt;を引数で受けるようにしたのはこのため.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/9fdf8338eb7487cf58da661766b98b88.js"&gt;&lt;/script&gt;
&lt;p&gt;テストコードが作れたので, 実際にテストを実行する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; ..
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# diceパッケージのテスト&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go &lt;span class="nb"&gt;test&lt;/span&gt; -cover ./dice
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ok 	github.com/uzimihsr/dice-api/dice	0.006s	coverage: 100.0% of statements
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# handlerパッケージのテスト&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go &lt;span class="nb"&gt;test&lt;/span&gt; -cover ./handler
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ok 	github.com/uzimihsr/dice-api/handler	0.016s	coverage: 100.0% of statements
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 全部まとめてテスト&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go &lt;span class="nb"&gt;test&lt;/span&gt; -cover ./...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;? 	github.com/uzimihsr/dice-api	&lt;span class="o"&gt;[&lt;/span&gt;no &lt;span class="nb"&gt;test&lt;/span&gt; files&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ok 	github.com/uzimihsr/dice-api/dice	&lt;span class="o"&gt;(&lt;/span&gt;cached&lt;span class="o"&gt;)&lt;/span&gt;	coverage: 100.0% of statements
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ok 	github.com/uzimihsr/dice-api/handler	&lt;span class="o"&gt;(&lt;/span&gt;cached&lt;span class="o"&gt;)&lt;/span&gt;	coverage: 100.0% of statements
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;? 	github.com/uzimihsr/dice-api/mock_dice	&lt;span class="o"&gt;[&lt;/span&gt;no &lt;span class="nb"&gt;test&lt;/span&gt; files&lt;span class="o"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;これでテストも(一応)できた.&lt;/p&gt;
&lt;p&gt;最終的なディレクトリの構成はこんなかんじ.&lt;br&gt;
テストを実行したのでパッケージの依存関係を管理するためのファイル&lt;code&gt;go.mod&lt;/code&gt;と&lt;code&gt;go.sum&lt;/code&gt;が修正/追加されている.&lt;br&gt;
こいつらも一緒に&lt;code&gt;Git&lt;/code&gt;で管理しておくと, 別の環境でこれをビルドするときに便利だったりする. らしい.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ tree .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── README.md
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── dice
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   ├── dice.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   └── dice_test.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── go.mod
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── go.sum
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── handler
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   ├── handler.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   └── handler_test.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── main.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── mock_dice
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └── mock_dice.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;3&lt;/span&gt; directories, &lt;span class="m"&gt;9&lt;/span&gt; files&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;最終的なリポジトリは&lt;a class="link" href="https://github.com/uzimihsr/dice-api/tree/07e945bed60205b936e9ca3511cf1dafe8881ab8" target="_blank" rel="noopener"
 &gt;こんなかんじ&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;Web APIっぽいものを0から作ってみた. テストまでやったのでけっこうしんどかった.&lt;br&gt;
あとは&lt;a class="link" href="https://uzimihsr.github.io/post/2020-03-15-golang-build-image/" target="_blank" rel="noopener"
 &gt;ビルド&lt;/a&gt;すれば普通に動くはずなので,&lt;br&gt;
暇があったら&lt;code&gt;Kubernetes&lt;/code&gt;で動かすところまでやってみたい.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="おすわりするねこ(ごはんがほしい)" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-07-23-golang-dice-api/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-07-23-golang-dice-api/sotochan_hu_6b5edc519419462e.jpg 800w, https://blog.uzimihsr.com/post/2020-07-23-golang-dice-api/sotochan_hu_7e72aa2f06ed6f.jpg 1600w, https://blog.uzimihsr.com/post/2020-07-23-golang-dice-api/sotochan_hu_5e44e066cd7a8bb5.jpg 2400w, https://blog.uzimihsr.com/post/2020-07-23-golang-dice-api/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;h2 id="参考にしたもの"&gt;参考にしたもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/golang/go/wiki/Modules#example" target="_blank" rel="noopener"
 &gt;https://github.com/golang/go/wiki/Modules#example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://book.impress.co.jp/books/1115101145" target="_blank" rel="noopener"
 &gt;Goプログラミング実践入門 標準ライブラリでゼロからWebアプリを作る&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/golang/mock/blob/master/README.md" target="_blank" rel="noopener"
 &gt;https://github.com/golang/mock/blob/master/README.md&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Prometheusで不要なメトリクスを除外する</title><link>https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/</link><pubDate>Tue, 14 Jul 2020 22:49:32 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sotochan.jpg" alt="Featured image of post Prometheusで不要なメトリクスを除外する" /&gt;&lt;h2 id="いらないメトリクスは拾いたくない"&gt;いらないメトリクスは拾いたくない
&lt;/h2&gt;&lt;p&gt;Prometheusでスクレイプする対象にいらないメトリクスがあったときに無視したかった.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;特定のメトリクスだけ除外したいときは&lt;code&gt;metric_relabel_configs&lt;/code&gt;で除外したいメトリクスのラベルを正規表現で記述してdropするのが良さそう.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# メトリクス名がnode_cpu_seconds_totalでmode=&amp;#34;idle&amp;#34;のラベルを持つメトリクスを除外する例&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;scrape_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;node&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;localhost:9100&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;metric_relabel_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;source_labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="l"&gt;__name__, mode]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;node_cpu_seconds_total;idle&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;drop&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Raspberry Pi 3 Model B+
&lt;ul&gt;
&lt;li&gt;OSはRaspbian(10.0)&lt;/li&gt;
&lt;li&gt;監視サーバとして使用&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/prometheus/prometheus" target="_blank" rel="noopener"
 &gt;Prometheus&lt;/a&gt; version 2.15.2
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2020-01-15-prometheus-grafana-raspberry-pi/" target="_blank" rel="noopener"
 &gt;インストール済み&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/prometheus/node_exporter" target="_blank" rel="noopener"
 &gt;Node exporter&lt;/a&gt; version 0.18.1
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2020-01-15-prometheus-grafana-raspberry-pi/" target="_blank" rel="noopener"
 &gt;インストール済み&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やりかた"&gt;やりかた
&lt;/h2&gt;&lt;p&gt;例えば&lt;code&gt;Node exporter&lt;/code&gt;で取れるCPU時間のメトリクス&lt;code&gt;node_cpu_seconds_total&lt;/code&gt;を&lt;code&gt;Prometheus&lt;/code&gt;で見ているとき,&lt;br&gt;
普通はこんな感じで&lt;code&gt;mode&lt;/code&gt;ラベルの値が異なる複数のメトリクスが取れる.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;node_cpu_seconds_total{cpu=&amp;#34;0&amp;#34;}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img alt="Prometheus" class="gallery-image" data-flex-basis="570px" data-flex-grow="237" height="1212" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sc01.png" srcset="https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sc01_hu_19f38c4ed28fdfce.png 800w, https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sc01_hu_7ec79454c231d893.png 1600w, https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sc01_hu_9d413686ceef6374.png 2400w, https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sc01.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;メトリクスの用途はさておき, この中で&lt;code&gt;mode=&amp;quot;idle&amp;quot;&lt;/code&gt;のラベルがついているメトリクスだけを除外したいとする.&lt;/p&gt;
&lt;p&gt;そんなときは&lt;code&gt;Prometheus&lt;/code&gt;のスクレイプ設定で&lt;code&gt;metric_relabel_configs&lt;/code&gt;の設定を追加する.&lt;br&gt;
この設定により, &lt;code&gt;__name__&lt;/code&gt;ラベル(メトリクス名)が&lt;code&gt;node_cpu_seconds_total&lt;/code&gt;かつ&lt;code&gt;mode&lt;/code&gt;ラベルが&lt;code&gt;idle&lt;/code&gt;であるメトリクスだけが除外(drop)される.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/47cbde957d57c5fc8a78d02e681460f3.js"&gt;&lt;/script&gt;
&lt;p&gt;設定変更後, &lt;code&gt;Prometheus&lt;/code&gt;を再起動する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# prometheusのスクレイプ設定を変更して再起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim /usr/local/prometheus/prometheus.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl restart prometheus&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;再度&lt;code&gt;Prometheus&lt;/code&gt;で先程と同じクエリを投げると, &lt;code&gt;mode=&amp;quot;idle&amp;quot;&lt;/code&gt;のラベルがついたメトリクスだけがなくなっていることがわかる.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Prometheus" class="gallery-image" data-flex-basis="592px" data-flex-grow="246" height="1166" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sc02.png" srcset="https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sc02_hu_cee5eeb0f5345bc4.png 800w, https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sc02_hu_132016dea3008213.png 1600w, https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sc02_hu_7953052411fe98d8.png 2400w, https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sc02.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;今度は逆に&lt;code&gt;mode=&amp;quot;idle&amp;quot;&lt;/code&gt;のラベルがついているメトリクスだけを残して, 他のメトリクスを拾わないようにしてみる.&lt;br&gt;
この設定により, &lt;code&gt;__name__=&amp;quot;node_cpu_seconds_total&amp;quot;&lt;/code&gt;と&lt;code&gt;mode=&amp;quot;idle&amp;quot;&lt;/code&gt;の両方のラベルを持つメトリクスのみが保持(keep)され,&lt;br&gt;
それ以外のメトリクスがすべて除外される.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/cb14c21ba82985b58834994f20f3f100.js"&gt;&lt;/script&gt;
&lt;p&gt;&lt;img alt="Prometheus" class="gallery-image" data-flex-basis="832px" data-flex-grow="346" height="830" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sc03.png" srcset="https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sc03_hu_543180357e29588d.png 800w, https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sc03_hu_504b3ae80c0a3317.png 1600w, https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sc03_hu_354b4634514e440d.png 2400w, https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sc03.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;これでも問題なさそうだけど, 実はこの設定を入れるとメトリクス名(&lt;code&gt;__name__&lt;/code&gt;)が&lt;code&gt;node_cpu_seconds_total&lt;/code&gt;でないメトリクスがすべて捨てられてしまうので,&lt;br&gt;
&lt;code&gt;node_filesystem_free_bytes&lt;/code&gt;(ファイルシステムの空き容量)のような&lt;code&gt;Node exporter&lt;/code&gt;の他のメトリクスが取れなくなってしまう.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Prometheus" class="gallery-image" data-flex-basis="838px" data-flex-grow="349" height="824" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sc04.png" srcset="https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sc04_hu_3b7173615e28fed5.png 800w, https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sc04_hu_2afdf945e26e90a1.png 1600w, https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sc04_hu_bce15b4af4387793.png 2400w, https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sc04.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;うまいこと&lt;code&gt;__name__=&amp;quot;node_cpu_seconds_total&amp;quot;&lt;/code&gt;かつ&lt;code&gt;mode!=&amp;quot;idle&amp;quot;&lt;/code&gt;のような条件を正規表現で書ければいいんだけど,&lt;br&gt;
&lt;code&gt;Prometheus&lt;/code&gt;で使うRE2正規表現は&lt;code&gt;(?!idle)&lt;/code&gt;みたいな否定先読みに対応していないらしいのでちょっと難しい.&lt;/p&gt;
&lt;p&gt;よくわかんなかったので苦肉の策として除外したい個別のラベルを列挙してみた.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/ee45b5d477ac9f415db214cca5db9f54.js"&gt;&lt;/script&gt;
&lt;p&gt;これなら&lt;code&gt;__name__=&amp;quot;node_filesystem_free_bytes&amp;quot;&lt;/code&gt;のような他のメトリクスを捨てずに&lt;code&gt;__name__=&amp;quot;node_cpu_seconds_total&amp;quot;&lt;/code&gt;のメトリクスの中で&lt;code&gt;mode=&amp;quot;idle&amp;quot;&lt;/code&gt;なものだけを残せるけど,&lt;br&gt;
除外するラベルを全部列挙するのはあんまり現実的じゃないような気がする&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Prometheus" class="gallery-image" data-flex-basis="832px" data-flex-grow="346" height="830" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sc03.png" srcset="https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sc03_hu_543180357e29588d.png 800w, https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sc03_hu_504b3ae80c0a3317.png 1600w, https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sc03_hu_354b4634514e440d.png 2400w, https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sc03.png 2880w" width="2880"&gt;&lt;br&gt;
&lt;img alt="Prometheus" class="gallery-image" data-flex-basis="663px" data-flex-grow="276" height="1042" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sc05.png" srcset="https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sc05_hu_3ec87aca02599b2.png 800w, https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sc05_hu_416487d966ce61a2.png 1600w, https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sc05_hu_76f4661a289d3cd8.png 2400w, https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sc05.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;正規表現にマッチするメトリクスだけ除外するdropとその逆のkeepだと本当は除外対象を列挙しないで済むkeepを使いたくなるけど,&lt;br&gt;
現状は正規表現の仕様でdropのほうが使いやすいという感じがする.&lt;br&gt;
そもそもそこまで排除対象のメトリクスが多いようなスクレイプ対象だったらそれ自体を見直したほうがいいのだろうか.&lt;/p&gt;
&lt;p&gt;とりあえずはdropで頑張ってみて, keepでいい感じに他のメトリクスを残せるような方法があったら試してみたい.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="人間用まくらが好きなねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sotochan_hu_d54eac8bb8a0c827.jpg 800w, https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sotochan_hu_4e40c04751822692.jpg 1600w, https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sotochan_hu_e17dbeca6c32c5d3.jpg 2400w, https://blog.uzimihsr.com/post/2020-07-14-prometheus-metric-relabel/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;h2 id="参考"&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.robustperception.io/dropping-metrics-at-scrape-time-with-prometheus" target="_blank" rel="noopener"
 &gt;https://www.robustperception.io/dropping-metrics-at-scrape-time-with-prometheus&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config" target="_blank" rel="noopener"
 &gt;https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/google/re2/wiki/Syntax" target="_blank" rel="noopener"
 &gt;https://github.com/google/re2/wiki/Syntax&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>yq(v3)でKubernetesのYAMLをいじる</title><link>https://blog.uzimihsr.com/post/2020-07-06-yq-kubernetes-yaml/</link><pubDate>Mon, 06 Jul 2020 17:58:37 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-07-06-yq-kubernetes-yaml/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-07-06-yq-kubernetes-yaml/sotochan.jpg" alt="Featured image of post yq(v3)でKubernetesのYAMLをいじる" /&gt;&lt;p&gt;&lt;em&gt;&lt;strong&gt;[注意]この記事の執筆時点では&lt;a class="link" href="https://github.com/mikefarah/yq" target="_blank" rel="noopener"
 &gt;yq&lt;/a&gt; version3系を使用していたため、コマンド例にversion4系で使用できないオプションが含まれています。&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;→&lt;a class="link" href="https://uzimihsr.github.io/post/2022-04-14-yq-v4-kubernetes-yaml/" target="_blank" rel="noopener"
 &gt;yq(v4)でKubernetesのYAMLをいじる&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="yqすごい"&gt;yqすごい
&lt;/h2&gt;&lt;p&gt;yqでKubernetesのYAMLから値を抽出したり値を書き換えたりした.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;yq&lt;/code&gt;はべんり.&lt;br&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# YAMLの値(key=spec.containers[0].image)を抽出&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ yq &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;pod.yaml&amp;#39;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;spec.containers[0].image&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 正規表現でimageとtagを抜き出す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ yq &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;pod.yaml&amp;#39;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;spec.containers[0].image&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; grep -o &lt;span class="s1"&gt;&amp;#39;^[^:]\+&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ yq &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;pod.yaml&amp;#39;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;spec.containers[0].image&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; grep -o &lt;span class="s1"&gt;&amp;#39;[^:]\+$&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# YAMLの値(key=spec.containers[0].image)を上書き&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ yq write -i &lt;span class="s1"&gt;&amp;#39;pod.yaml&amp;#39;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;spec.containers[0].image&amp;#39;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;nginx:1.19.0&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Mojave 10.14&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mikefarah/yq" target="_blank" rel="noopener"
 &gt;yq&lt;/a&gt; version 3.3.2&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やりかた"&gt;やりかた
&lt;/h2&gt;&lt;p&gt;こんな感じの&lt;code&gt;Kubernetes&lt;/code&gt;のマニフェストファイル(&lt;code&gt;YAML&lt;/code&gt;)を扱っていたときに,&lt;br&gt;
使用している&lt;code&gt;image&lt;/code&gt;(&lt;a class="link" href="https://hub.docker.com/_/nginx?tab=tags" target="_blank" rel="noopener"
 &gt;nginx&lt;/a&gt;)の&lt;code&gt;tag&lt;/code&gt;が &lt;strong&gt;latest&lt;/strong&gt; だったのを &lt;strong&gt;1.19.0&lt;/strong&gt; みたいな&lt;code&gt;image&lt;/code&gt;の&lt;code&gt;digest&lt;/code&gt;が一意に定まるようなバージョンごとの&lt;code&gt;tag&lt;/code&gt;に変更したくなった.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pod.yaml&lt;/code&gt;&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/3717717a866f8373755a2384426c89c4.js"&gt;&lt;/script&gt;
&lt;p&gt;手で直接編集するのもいいんだけど,&lt;br&gt;
ゆくゆくは自動化したりしたいので&lt;code&gt;yq&lt;/code&gt;を使ってスクリプトを書いてみる.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;image-tag-fix.sh&lt;/code&gt;&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/d15238c659548c585731c6484a3c2aec.js"&gt;&lt;/script&gt;
&lt;p&gt;作成したスクリプトを実行する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;image-tag-fix.sh pod.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# タグ置換スクリプト実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ chmod +x ./image-tag-fix.sh
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ./image-tag-fix.sh
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;image : nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tag : latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;replaced: nginx:latest &lt;span class="o"&gt;=&lt;/span&gt;&amp;gt; nginx:1.19.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 内容確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat pod.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apiVersion: v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kind: Pod
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: nginx-pod
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; containers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - name: nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; image: nginx:1.19.0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;いい感じ.&lt;br&gt;
&lt;code&gt;yq&lt;/code&gt;を使って&lt;code&gt;YAML&lt;/code&gt;の値を書き換えることができた.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;yq&lt;/code&gt;は&lt;a class="link" href="https://github.com/stedolan/jq" target="_blank" rel="noopener"
 &gt;jq&lt;/a&gt;みたいな感じで&lt;code&gt;YAML&lt;/code&gt;を扱えるのでかなり便利.&lt;br&gt;
うまく使いこなせるようになりたい.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="ほっぺがかわいいねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-07-06-yq-kubernetes-yaml/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-07-06-yq-kubernetes-yaml/sotochan_hu_7149aacc521d93d3.jpg 800w, https://blog.uzimihsr.com/post/2020-07-06-yq-kubernetes-yaml/sotochan_hu_2e268bfee1605864.jpg 1600w, https://blog.uzimihsr.com/post/2020-07-06-yq-kubernetes-yaml/sotochan_hu_42f7aaf77d5c786a.jpg 2400w, https://blog.uzimihsr.com/post/2020-07-06-yq-kubernetes-yaml/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;h2 id="参考"&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mikefarah/yq/blob/master/README.md" target="_blank" rel="noopener"
 &gt;https://github.com/mikefarah/yq/blob/master/README.md&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>6月のそとちゃんまとめ(2020)</title><link>https://blog.uzimihsr.com/post/2020-07-01-sotochan/</link><pubDate>Wed, 01 Jul 2020 22:33:16 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-07-01-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-07-01-sotochan/sotochan03.jpg" alt="Featured image of post 6月のそとちゃんまとめ(2020)" /&gt;&lt;h2 id="じめじめするけど"&gt;じめじめするけど
&lt;/h2&gt;&lt;p&gt;6月もそとちゃんは元気だった.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%8a%e3%82%82%e3%81%a1%e3%82%83%e3%81%8c%e3%81%9f%e3%81%8f%e3%81%95%e3%82%93" &gt;おもちゃがたくさん&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%ad%e3%81%93%e3%81%8c%e3%81%8a%e3%81%a1%e3%81%a6%e3%81%84%e3%82%8b" &gt;ねこがおちている&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%af%e3%81%bf%e3%81%8c%e3%81%8d%e3%81%a7%e3%81%8d%e3%81%aa%e3%81%84" &gt;はみがきできない&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="おもちゃがたくさん"&gt;おもちゃがたくさん
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2020-05-31-sotochan/#%E5%85%83%E6%B0%97%E3%81%8C%E6%9C%89%E3%82%8A%E4%BD%99%E3%81%A3%E3%81%A6%E3%81%84%E3%82%8B" target="_blank" rel="noopener"
 &gt;先月はあまり遊んであげられなかった&lt;/a&gt;ので,&lt;br&gt;
今月はおもちゃでたくさん遊んであげた.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ペットショップ行けたのでバチクソおもちゃ買ってあげた(失くしたねずみのおもちゃ含む) &lt;a href="https://t.co/k4CZJNWD8r"&gt;pic.twitter.com/k4CZJNWD8r&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1267819167975002113?ref_src=twsrc%5Etfw"&gt;June 2, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;特に小さいねずみのおもちゃが最近のお気に入りらしい.&lt;br&gt;
箱の中に入れるとずっといじって遊んでる.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ねずみの入った箱に夢中 &lt;a href="https://t.co/Za5H5Iy7Ym"&gt;pic.twitter.com/Za5H5Iy7Ym&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1268336287729086465?ref_src=twsrc%5Etfw"&gt;June 4, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;頭突っ込んでるのかわいい &lt;a href="https://t.co/MtEJgOL3Go"&gt;pic.twitter.com/MtEJgOL3Go&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1268693976590118913?ref_src=twsrc%5Etfw"&gt;June 4, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;この大玉のおもちゃはそんなに食いつかなかった&amp;hellip;&lt;br&gt;
自分で持ち上げられるくらいの軽さのおもちゃが好きみたい.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;あたらしいおもちゃ &lt;a href="https://t.co/EqbMGAtRMg"&gt;pic.twitter.com/EqbMGAtRMg&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1276513662564331521?ref_src=twsrc%5Etfw"&gt;June 26, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;運動量を増やそうとしてねこじゃらしのレベルを上げると&lt;a class="link" href="https://www.instagram.com/p/CBuOCauFvUb/?utm_source=ig_web_copy_link" target="_blank" rel="noopener"
 &gt;すぐ諦めちゃう&lt;/a&gt;のがかわいかった.&lt;/p&gt;
&lt;p&gt;今月買ったおもちゃたちの現在.&lt;br&gt;
じゃらしは3/5が破壊, ねずみは4つ出して2つが行方不明&amp;hellip;&lt;br&gt;
遊び方が激しすぎませんかね&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="おもちゃ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-07-01-sotochan/sotochan01.jpg" srcset="https://blog.uzimihsr.com/post/2020-07-01-sotochan/sotochan01_hu_99b1a0d485f5d66d.jpg 800w, https://blog.uzimihsr.com/post/2020-07-01-sotochan/sotochan01_hu_3b30a90d12a978be.jpg 1600w, https://blog.uzimihsr.com/post/2020-07-01-sotochan/sotochan01_hu_664763318d99f959.jpg 2400w, https://blog.uzimihsr.com/post/2020-07-01-sotochan/sotochan01.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;h3 id="ねこがおちている"&gt;ねこがおちている
&lt;/h3&gt;&lt;p&gt;梅雨でじめじめしているのと関係があるかはわからないけど,&lt;br&gt;
家にねこがおちていることが多くなった.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;人間のベッドにねこが落ちてた &lt;a href="https://t.co/EtDdIRFwrY"&gt;pic.twitter.com/EtDdIRFwrY&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1269440688959090690?ref_src=twsrc%5Etfw"&gt;June 7, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;バテた &lt;a href="https://t.co/JbcVqTDykU"&gt;pic.twitter.com/JbcVqTDykU&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1269982773525151744?ref_src=twsrc%5Etfw"&gt;June 8, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;元気がないわけじゃないのでそこまで気にしてないけど,&lt;br&gt;
あんまりひなたぼっこできないから退屈なのかもしれない.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;朝 &lt;a href="https://t.co/DwSURYPUcd"&gt;pic.twitter.com/DwSURYPUcd&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1273407419813486594?ref_src=twsrc%5Etfw"&gt;June 18, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;のびる &lt;a href="https://t.co/XQTgzSD7T4"&gt;pic.twitter.com/XQTgzSD7T4&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1275993295974354945?ref_src=twsrc%5Etfw"&gt;June 25, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;あとは単純に遊びすぎて疲れてる説もある.&lt;br&gt;
&lt;a class="link" href="https://www.instagram.com/p/CCDknQElZ_m/?utm_source=ig_web_copy_link" target="_blank" rel="noopener"
 &gt;溶けてるみたい&lt;/a&gt;でかわいい.&lt;/p&gt;
&lt;h3 id="はみがきできない"&gt;はみがきできない
&lt;/h3&gt;&lt;p&gt;将来のためにはみがきの練習を始めたんだけど, めちゃくちゃ嫌いみたい&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://www.lion-pet.jp/product/petkiss/kinou_finger_sheet_apple.htm" target="_blank" rel="noopener"
 &gt;はみがきシート&lt;/a&gt;の匂いを嗅ぐだけで嫌な顔する.&lt;/p&gt;
&lt;p&gt;&lt;img alt="はみがきシート" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-07-01-sotochan/sotochan02.jpg" srcset="https://blog.uzimihsr.com/post/2020-07-01-sotochan/sotochan02_hu_12048cd77eaf4162.jpg 800w, https://blog.uzimihsr.com/post/2020-07-01-sotochan/sotochan02_hu_dbda97eb71863c93.jpg 1600w, https://blog.uzimihsr.com/post/2020-07-01-sotochan/sotochan02_hu_e1d621c46d781e17.jpg 2400w, https://blog.uzimihsr.com/post/2020-07-01-sotochan/sotochan02.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;大好物のにぼしで釣ってなんとか歯には触らせてくれるようにはなったけど,&lt;br&gt;
終わった後はいつもいじける.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;おやつで釣られて歯みがきさせられたからもう何も信じたくなくなったねこ(日課) &lt;a href="https://t.co/eaWzS1wXge"&gt;pic.twitter.com/eaWzS1wXge&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1273262094947766278?ref_src=twsrc%5Etfw"&gt;June 17, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;↓の動画を参考にちょっとずつやってるけど,&lt;br&gt;
成猫になってからなのでなかなか慣れてくれない.&lt;/p&gt;
&lt;div class="video-wrapper"&gt;
 &lt;iframe loading="lazy" 
 src="https://www.youtube.com/embed/teloWX6iabQ" 
 allowfullscreen 
 title="YouTube Video"
 &gt;
 &lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;こればかりは気長に頑張るしかないのかもしれない&amp;hellip;&lt;/p&gt;
&lt;p&gt;しもべはこんなにそとちゃんの健康を考えているのに,&lt;br&gt;
そとちゃんはお手入れのたびにしもべのことが嫌いになっていく. かなしい😭&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;そとちゃんは6月も元気だった.&lt;/p&gt;
&lt;p&gt;ひなたぼっこできないのはかわいそうなので, はやく梅雨明けしてほしい.&lt;/p&gt;
&lt;p&gt;はみがきできるようになる日は来るのか&amp;hellip;?&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="どや顔?するねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-07-01-sotochan/sotochan03.jpg" srcset="https://blog.uzimihsr.com/post/2020-07-01-sotochan/sotochan03_hu_614ec468d1c1da87.jpg 800w, https://blog.uzimihsr.com/post/2020-07-01-sotochan/sotochan03_hu_91e6cfef3e07d87c.jpg 1600w, https://blog.uzimihsr.com/post/2020-07-01-sotochan/sotochan03_hu_3a9f2419f0386623.jpg 2400w, https://blog.uzimihsr.com/post/2020-07-01-sotochan/sotochan03.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>awkコマンドを使って文字列の先頭と末尾を削除する</title><link>https://blog.uzimihsr.com/post/2020-06-29-print-string-awk/</link><pubDate>Mon, 29 Jun 2020 21:19:05 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-06-29-print-string-awk/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-06-29-print-string-awk/sotochan.jpg" alt="Featured image of post awkコマンドを使って文字列の先頭と末尾を削除する" /&gt;&lt;h2 id="awkすき"&gt;awkすき
&lt;/h2&gt;&lt;p&gt;Shellで文字列を扱うときにちょっとだけ困ったのでメモ.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;substr()&lt;/code&gt;と&lt;code&gt;length()&lt;/code&gt;を使う.&lt;br&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 先頭から1文字削除&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;abcdefghijkl&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; awk &lt;span class="s1"&gt;&amp;#39;{print substr($0, 2)}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bcdefghijkl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 末尾から1文字削除&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;abcdefghijkl&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; awk &lt;span class="s1"&gt;&amp;#39;{print substr($0, 1, length($0)-1)}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;abcdefghijk
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 先頭と末尾から1文字ずつ削除&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;abcdefghijkl&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; awk &lt;span class="s1"&gt;&amp;#39;{print substr($0, 2, length($0)-2)}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bcdefghijk&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Mojave 10.14&lt;/li&gt;
&lt;li&gt;awk version 20070501&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やりかた"&gt;やりかた
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;substr(string, start, length)&lt;/code&gt;は文字列(&lt;code&gt;string&lt;/code&gt;)の頭n文字目(&lt;code&gt;start&lt;/code&gt;)からm文字(&lt;code&gt;length&lt;/code&gt;)を抜き出して表示する.&lt;br&gt;
引数の&lt;code&gt;length&lt;/code&gt;は省略可能で, 省略した場合は文末まで表示される.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# qwerty の2文字目(w)から末尾まで抽出&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ awk &lt;span class="s1"&gt;&amp;#39;BEGIN {print substr(&amp;#34;qwerty&amp;#34;, 2)}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;werty
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# qwerty の2文字目(w)から4文字ぶんを抽出&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ awk &lt;span class="s1"&gt;&amp;#39;BEGIN {print substr(&amp;#34;qwerty&amp;#34;, 2, 4)}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;wert&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;先頭から文字を抜き出せたが, 末尾から文字を抜き出したい場合もある.&lt;br&gt;
&lt;code&gt;length(string)&lt;/code&gt;は文字列(&lt;code&gt;string&lt;/code&gt;)の文字数を数えてくれるので, これと&lt;code&gt;substr()&lt;/code&gt;を組み合わせてみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# qwertyの文字数は6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ awk &lt;span class="s1"&gt;&amp;#39;BEGIN {print length(&amp;#34;qwerty&amp;#34;)}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# qwerty の1文字目(q)から(length-1=5)文字ぶんを抽出&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ awk &lt;span class="s1"&gt;&amp;#39;BEGIN {print substr(&amp;#34;qwerty&amp;#34;, 1, length(&amp;#34;qwerty&amp;#34;)-1)}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;qwert&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;あとはパイプでつないでいい感じにすればいい.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ダブルクォート(&amp;#34;&amp;#34;)で囲まれた文字列(&amp;#34;qwerty&amp;#34;)から文字列(qwerty)のみを抽出&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#34;qwerty&amp;#34;&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; awk &lt;span class="s1"&gt;&amp;#39;{print substr($0, 2, length($0)-2)}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;qwerty&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;やったぜ.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;やっぱり&lt;code&gt;awk&lt;/code&gt;は神.&lt;br&gt;
もっと使いこなしていきたい.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="テレワーク中のしもべの真似をするねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-06-29-print-string-awk/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-06-29-print-string-awk/sotochan_hu_da38362a25655d2b.jpg 800w, https://blog.uzimihsr.com/post/2020-06-29-print-string-awk/sotochan_hu_f16e1f40c7d130d1.jpg 1600w, https://blog.uzimihsr.com/post/2020-06-29-print-string-awk/sotochan_hu_828c45206f465e4d.jpg 2400w, https://blog.uzimihsr.com/post/2020-06-29-print-string-awk/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;h2 id="参考"&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.gnu.org/software/gawk/manual/html_node/String-Functions.html" target="_blank" rel="noopener"
 &gt;https://www.gnu.org/software/gawk/manual/html_node/String-Functions.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>nginxとOpenSSLでクライアント認証を行う</title><link>https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/</link><pubDate>Fri, 26 Jun 2020 23:32:10 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/sotochan.jpg" alt="Featured image of post nginxとOpenSSLでクライアント認証を行う" /&gt;&lt;h2 id="特定の人だけ許可したい"&gt;特定の人だけ許可したい
&lt;/h2&gt;&lt;p&gt;サーバー証明書のしくみを学んだので, 今度はクライアント認証のしくみを作ってみる.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;認証局を立ててクライアント証明書を作成した&lt;/li&gt;
&lt;li&gt;nginxでクライアント認証の設定をした&lt;/li&gt;
&lt;li&gt;MacからcurlとChromeでクライアント認証のかかったnginxに接続した&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="ざっくりとしたしくみ" class="gallery-image" data-flex-basis="356px" data-flex-grow="148" height="994" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/component.png" srcset="https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/component_hu_404aa2cafd384472.png 800w, https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/component.png 1477w" width="1477"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2020-06-03-server-certification-practice/" target="_blank" rel="noopener"
 &gt;サーバー証明書&lt;/a&gt;がサーバーの正当性を証明してクライアントがサーバーを信頼するためのものであるのに対し,&lt;br&gt;
クライアント証明書はその逆でクライアントの正当性を証明してサーバーがクライアントを信頼するためのもの.&lt;/p&gt;
&lt;p&gt;不特定多数の相手に公開したくないサーバーにクライアント認証をかけることで,&lt;br&gt;
有効なクライアント証明書を持つ特定の相手だけにこれを公開することができる.&lt;/p&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Raspberry Pi 3 Model B+
&lt;ul&gt;
&lt;li&gt;OSはRaspbian(10.0)&lt;/li&gt;
&lt;li&gt;SSLサーバーとして使用&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2020-01-07-raspberry-pi-static-id/" target="_blank" rel="noopener"
 &gt;IP固定済み&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;OpenSSL
&lt;ul&gt;
&lt;li&gt;OpenSSL 1.1.1c 28 May 2019&lt;/li&gt;
&lt;li&gt;ラズパイの初期装備&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;nginx
&lt;ul&gt;
&lt;li&gt;version 1.14.2&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2020-01-29-nginx/" target="_blank" rel="noopener"
 &gt;ラズパイにインストール済み&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;macOS Mojave 10.14
&lt;ul&gt;
&lt;li&gt;クライアントとして使用&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Google Chrome
&lt;ul&gt;
&lt;li&gt;バージョン: 83.0.4103.61（Official Build） （64 ビット）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%af%e3%83%a9%e3%82%a4%e3%82%a2%e3%83%b3%e3%83%88%e8%a8%bc%e6%98%8e%e6%9b%b8%e3%81%ae%e4%bd%9c%e6%88%90" &gt;クライアント証明書の作成&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#nginx%e3%81%ae%e8%a8%ad%e5%ae%9a" &gt;nginxの設定&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%af%e3%83%a9%e3%82%a4%e3%82%a2%e3%83%b3%e3%83%88%e8%a8%bc%e6%98%8e%e6%9b%b8%e3%82%92%e7%94%a8%e3%81%84%e3%81%9f%e6%8e%a5%e7%b6%9a" &gt;クライアント証明書を用いた接続&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="クライアント証明書の作成"&gt;クライアント証明書の作成
&lt;/h3&gt;&lt;p&gt;まずはクライアント証明書を作成する.&lt;br&gt;
といっても途中までの手順は&lt;a class="link" href="https://uzimihsr.github.io/post/2020-06-03-server-certification-practice/" target="_blank" rel="noopener"
 &gt;サーバー証明書&lt;/a&gt;を作成したときとほとんど同じ.&lt;/p&gt;
&lt;p&gt;まずはオレオレ認証局を建てる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;## 以下すべてラズパイで実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# オレオレ認証局用ディレクトリ(ClientCA)で作業&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mkdir ClientCA &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; ClientCA
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 認証局用の秘密鍵(ClientCA-private-key.pem)を作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl genpkey -algorithm RSA -out ClientCA-private-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 認証局の秘密鍵(ClientCA-private-key.pem)を使ったオレオレ証明書(ClientCA.pem)の作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl req -x509 -key ClientCA-private-key.pem -out ClientCA.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;You are about to be asked to enter information that will be incorporated
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;into your certificate request.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;What you are about to enter is what is called a Distinguished Name or a DN.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;There are quite a few fields but you can leave some blank
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;For some fields there will be a default value,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;If you enter &lt;span class="s1"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;, the field will be left blank.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-----
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Country Name &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; letter code&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;AU&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;State or Province Name &lt;span class="o"&gt;(&lt;/span&gt;full name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Some-State&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Locality Name &lt;span class="o"&gt;(&lt;/span&gt;eg, city&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Organization Name &lt;span class="o"&gt;(&lt;/span&gt;eg, company&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Internet Widgits Pty Ltd&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Organizational Unit Name &lt;span class="o"&gt;(&lt;/span&gt;eg, section&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Common Name &lt;span class="o"&gt;(&lt;/span&gt;e.g. server FQDN or YOUR name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:ClientCA
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Email Address &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 署名のための準備&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mkdir -p demoCA/newcerts
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ touch ./demoCA/index.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="m"&gt;01&lt;/span&gt; &amp;gt; ./demoCA/serial&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;次にクライアント証明書用の秘密鍵と証明書署名要求(&lt;code&gt;CSR&lt;/code&gt;)を作成する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# クライアント用ディレクトリ(Client)で作業&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; ../
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mkdir Client &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; Client
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# クライアント用の秘密鍵(Client-private-key.pem)を作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl genpkey -algorithm RSA -out Client-private-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# クライアントの秘密鍵(Client-private-key.pem)からCSR(Client-csr.pem)を作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl req -new -key Client-private-key.pem -out Client-csr.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;You are about to be asked to enter information that will be incorporated
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;into your certificate request.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;What you are about to enter is what is called a Distinguished Name or a DN.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;There are quite a few fields but you can leave some blank
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;For some fields there will be a default value,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;If you enter &lt;span class="s1"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;, the field will be left blank.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-----
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Country Name &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; letter code&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;AU&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;State or Province Name &lt;span class="o"&gt;(&lt;/span&gt;full name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Some-State&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Locality Name &lt;span class="o"&gt;(&lt;/span&gt;eg, city&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Organization Name &lt;span class="o"&gt;(&lt;/span&gt;eg, company&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Internet Widgits Pty Ltd&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Organizational Unit Name &lt;span class="o"&gt;(&lt;/span&gt;eg, section&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Common Name &lt;span class="o"&gt;(&lt;/span&gt;e.g. server FQDN or YOUR name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:Client
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Email Address &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Please enter the following &lt;span class="s1"&gt;&amp;#39;extra&amp;#39;&lt;/span&gt; attributes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;to be sent with your certificate request
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;A challenge password &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;An optional company name &lt;span class="o"&gt;[]&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;次はクライアントの&lt;code&gt;CSR&lt;/code&gt;を認証局で署名してクライアント証明書を作成する.&lt;br&gt;
これによりこの証明書を持つクライアントの正当性を認証局(&lt;strong&gt;ClientCA&lt;/strong&gt;)が証明したことになる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# クライアントのCSR(Client-csr.pem)を認証局(ClientCA)に渡す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cp Client-csr.pem ../ClientCA/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 認証局の秘密鍵(ClientCA-private-key.pem)と証明書(ClientCA.pem)で&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# クライアントのCSR(Client-csr.pem)に署名してクライアント証明書(Client.pem)を作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; ../ClientCA
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl ca -in Client-csr.pem -out Client.pem -keyfile ClientCA-private-key.pem -cert ClientCA.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Using configuration from /usr/lib/ssl/openssl.cnf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Check that the request matches the signature
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Signature ok
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Certificate Details:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Serial Number: &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;0x1&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Validity
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Not Before: Jun &lt;span class="m"&gt;24&lt;/span&gt; 14:02:29 &lt;span class="m"&gt;2020&lt;/span&gt; GMT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Not After : Jun &lt;span class="m"&gt;24&lt;/span&gt; 14:02:29 &lt;span class="m"&gt;2021&lt;/span&gt; GMT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Subject:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;countryName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; AU
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;stateOrProvinceName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; Some-State
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;organizationName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; Internet Widgits Pty Ltd
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;commonName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; Client
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; X509v3 extensions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; X509v3 Basic Constraints:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; CA:FALSE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Netscape Comment:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; OpenSSL Generated Certificate
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; X509v3 Subject Key Identifier:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 13:E6:B2:5D:88:06:CC:2C:17:BE:AA:98:92:B2:09:C3:BF:D4:AA:A4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; X509v3 Authority Key Identifier:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; keyid:9C:C0:54:1F:93:4C:F1:F9:0A:6D:2B:AF:8E:B0:80:54:F1:2A:EC:F3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Certificate is to be certified &lt;span class="k"&gt;until&lt;/span&gt; Jun &lt;span class="m"&gt;24&lt;/span&gt; 14:02:29 &lt;span class="m"&gt;2021&lt;/span&gt; GMT &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;365&lt;/span&gt; days&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Sign the certificate? &lt;span class="o"&gt;[&lt;/span&gt;y/n&lt;span class="o"&gt;]&lt;/span&gt;:y
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;1&lt;/span&gt; out of &lt;span class="m"&gt;1&lt;/span&gt; certificate requests certified, commit? &lt;span class="o"&gt;[&lt;/span&gt;y/n&lt;span class="o"&gt;]&lt;/span&gt;y
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Write out database with &lt;span class="m"&gt;1&lt;/span&gt; new entries
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Data Base Updated
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# クライアントに証明書(Client.pem)を渡す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mv ./Client.pem ../Client/&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;さいごにクライアントの秘密鍵と証明書をくっつけて&lt;code&gt;PKCS#12&lt;/code&gt;形式に変換する.&lt;br&gt;
なんかしらんけどクライアント認証で使うときに一番メジャーなフォーマットらしい.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 証明書(Client.pem)と秘密鍵(Client-private-key.pem)からPKCS#12形式のファイル(Client.p12)を作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; ../Client/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl pkcs12 -export -clcerts -in Client.pem -inkey Client-private-key.pem -out Client.p12
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Enter Export Password: &lt;span class="c1"&gt;# 任意のパスワードを設定する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Verifying - Enter Export Password: &lt;span class="c1"&gt;# 再度パスワードを入力&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;以上の手順でクライアント証明書と秘密鍵をあわせた&lt;code&gt;PKCS#12&lt;/code&gt;形式ファイルが作成できた.&lt;br&gt;
これでクライアント側の準備は完了.&lt;/p&gt;
&lt;h3 id="nginxの設定"&gt;nginxの設定
&lt;/h3&gt;&lt;p&gt;次に&lt;code&gt;nginx&lt;/code&gt;でクライアント認証の設定を行う.&lt;/p&gt;
&lt;p&gt;まずはクライアント証明書を発行した認証局の証明書を&lt;code&gt;nginx&lt;/code&gt;用のディレクトリに配置する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# CA証明書(ClientCA.pem)をnginx用ディレクトリに配置&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; ..
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo cp ClientCA/ClientCA.pem /etc/nginx/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls /etc/nginx/ClientCA.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/etc/nginx/ClientCA.pem&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;次に&lt;code&gt;nginx&lt;/code&gt;の設定を変更して再起動する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# nginxの設定ファイル(https.conf)を編集&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo vim /etc/nginx/conf.d/https.conf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# nginx再起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo nginx -t
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nginx: configuration file /etc/nginx/nginx.conf &lt;span class="nb"&gt;test&lt;/span&gt; is successful
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl restart nginx&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;script src="https://gist.github.com/uzimihsr/7f71a9cb3fcadf64c1e09cac808105a9.js"&gt;&lt;/script&gt;
&lt;p&gt;今回変更した部分以外(サーバー証明書など)は&lt;a class="link" href="https://uzimihsr.github.io/post/2020-06-03-server-certification-practice/#nginx%E3%81%AB%E8%A8%BC%E6%98%8E%E6%9B%B8%E3%82%92%E6%8C%81%E3%81%9F%E3%81%9B%E3%82%8B" target="_blank" rel="noopener"
 &gt;前回&lt;/a&gt;と全く同じ状態.&lt;/p&gt;
&lt;p&gt;これで&lt;code&gt;nginx&lt;/code&gt;にはクライアント認証がかかり,&lt;br&gt;
信頼しているCA証明書(&lt;strong&gt;ClientCA.pem&lt;/strong&gt;)の認証局によって署名されたクライアント証明書を持つ相手のみを信頼して内容を公開するようになった.&lt;/p&gt;
&lt;h3 id="クライアント証明書を用いた接続"&gt;クライアント証明書を用いた接続
&lt;/h3&gt;&lt;p&gt;サーバー(&lt;code&gt;nginx&lt;/code&gt;)側の設定が終わったので, 試しに&lt;code&gt;Mac&lt;/code&gt;から&lt;code&gt;nginx&lt;/code&gt;に接続してみる.&lt;/p&gt;
&lt;p&gt;なにもしない状態で&lt;code&gt;curl&lt;/code&gt;で &lt;strong&gt;https://&amp;lt;ラズパイのIP&amp;gt;/&lt;/strong&gt; をたたくとクライアント証明書がないので怒られる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;## 以下はすべてMacから実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# nginx(ラズパイ)にcurlしてみる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# nginxの持ってるサーバーの証明書が信頼できないものなので --insecure をつけて実行する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl https://raspberrypi --insecure
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;html&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;400 No required SSL certificate was sent&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;body &lt;span class="nv"&gt;bgcolor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;white&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;center&amp;gt;&amp;lt;h1&amp;gt;400 Bad Request&amp;lt;/h1&amp;gt;&amp;lt;/center&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;center&amp;gt;No required SSL certificate was sent&amp;lt;/center&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;hr&amp;gt;&amp;lt;center&amp;gt;nginx/1.14.2&amp;lt;/center&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;/body&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;/html&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# クライアント証明書がないので怒られる&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;次に&lt;code&gt;Mac&lt;/code&gt;に&lt;code&gt;PKCS#12&lt;/code&gt;形式のクライアント証明書をもたせた状態で接続してみる.&lt;br&gt;
今度は&lt;code&gt;nginx&lt;/code&gt;側が持つCA証明書と&lt;code&gt;Mac&lt;/code&gt;が持つクライアント証明書の照合が行われ,&lt;br&gt;
問題がなければクライアント認証を突破できる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ラズパイからMacにPKCS#12のクライアント証明書を持ってくる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ scp pi@raspberrypi://path/to/Client/Client.p12 ./
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# PKCS#12形式のファイル(Client.p12)からクライアント証明書(Client.pem)を取り出す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl pkcs12 -in ./Client.p12 -out Client.pem -clcerts -nokeys
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Enter Import Password: &lt;span class="c1"&gt;# pkcs12作成時に設定したパスワードを入力&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;MAC verified OK
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# PKCS#12形式のファイル(Client.p12)からクライアント秘密鍵(Client-private-key.pem)を取り出す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 秘密鍵にパスフレーズをつけていないので -nodes をつける&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl pkcs12 -in ./Client.p12 -out Client-private-key.pem -nocerts -nodes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Enter Import Password: &lt;span class="c1"&gt;# pkcs12作成時に設定したパスワードを入力&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;MAC verified OK
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# クライアントの証明書(Client.pem)と秘密鍵(Client-private-key.pem)をもたせた状態でcurlしてみると認証に成功してHTMLが表示される&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl --key ./Client-private-key.pem --cert ./Client.pem https://raspberrypi --insecure
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;!DOCTYPE html&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;html&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;head&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;title&amp;gt;Welcome to nginx!&amp;lt;/title&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;style&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; body &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; width: 35em&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; margin: &lt;span class="m"&gt;0&lt;/span&gt; auto&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; font-family: Tahoma, Verdana, Arial, sans-serif&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;/style&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;/head&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;body&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;h1&amp;gt;Welcome to nginx!&amp;lt;/h1&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;p&amp;gt;If you see this page, the nginx web server is successfully installed and
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;working. Further configuration is required.&amp;lt;/p&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;p&amp;gt;For online documentation and support please refer to
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;a &lt;span class="nv"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;http://nginx.org/&amp;#34;&lt;/span&gt;&amp;gt;nginx.org&amp;lt;/a&amp;gt;.&amp;lt;br/&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Commercial support is available at
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;a &lt;span class="nv"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;http://nginx.com/&amp;#34;&lt;/span&gt;&amp;gt;nginx.com&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;Thank you &lt;span class="k"&gt;for&lt;/span&gt; using nginx.&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;/body&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;ついでにブラウザでも試してみる.&lt;/p&gt;
&lt;p&gt;何もしない状態で &lt;strong&gt;https://&amp;lt;ラズパイのIP&amp;gt;/&lt;/strong&gt; を&lt;code&gt;Chrome&lt;/code&gt;で開くと証明書がないから怒られる.&lt;/p&gt;
&lt;p&gt;&lt;img alt="怒られる" class="gallery-image" data-flex-basis="1363px" data-flex-grow="568" height="507" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/sc01.png" srcset="https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/sc01_hu_cb29ed5f8a4fe254.png 800w, https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/sc01_hu_546bcbaea2da264b.png 1600w, https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/sc01_hu_26afe97995e9cbb1.png 2400w, https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/sc01.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Mac&lt;/code&gt;にクライアント証明書をもたせてみる.&lt;br&gt;
先程ラズパイから持ってきた&lt;code&gt;PKCS#12&lt;/code&gt;のファイルをダブルクリックする.&lt;/p&gt;
&lt;p&gt;&lt;img alt="クライアント証明書(.p12)" class="gallery-image" data-flex-basis="217px" data-flex-grow="90" height="214" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/icon01.png" width="194"&gt;&lt;/p&gt;
&lt;p&gt;パスワードを求められるので&lt;code&gt;PKCS#12&lt;/code&gt;の作成時に設定したパスワードを入力する.&lt;/p&gt;
&lt;p&gt;&lt;img alt="パスワードを入力" class="gallery-image" data-flex-basis="438px" data-flex-grow="182" height="608" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/sc02.png" srcset="https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/sc02_hu_fd235fbc6ebebcf6.png 800w, https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/sc02.png 1112w" width="1112"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;キーチェーンアクセス&lt;/code&gt;が開くので, この画面で&lt;code&gt;PKCS#12&lt;/code&gt;ファイルをダブルクリック.&lt;/p&gt;
&lt;p&gt;&lt;img alt="キーチェーンアクセス" class="gallery-image" data-flex-basis="336px" data-flex-grow="140" height="1410" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/sc03.png" srcset="https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/sc03_hu_671d75aeee8d9646.png 800w, https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/sc03_hu_6a32712290fa21cf.png 1600w, https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/sc03.png 1978w" width="1978"&gt;&lt;/p&gt;
&lt;p&gt;詳細画面が開くので, &lt;code&gt;信頼&lt;/code&gt;-&amp;gt;&lt;code&gt;この証明書を信頼するとき&lt;/code&gt;を&lt;code&gt;常に信頼&lt;/code&gt;に変更してウィンドウを閉じる.&lt;br&gt;
これで&lt;code&gt;Mac&lt;/code&gt;がこのクライアント証明書を使えるようになった.&lt;/p&gt;
&lt;p&gt;&lt;img alt="証明書を信頼する" class="gallery-image" data-flex-basis="275px" data-flex-grow="114" height="1088" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/sc04.png" srcset="https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/sc04_hu_7cbfdf4851db3a40.png 800w, https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/sc04.png 1250w" width="1250"&gt;&lt;/p&gt;
&lt;p&gt;再度 &lt;strong&gt;https://&amp;lt;ラズパイのIP&amp;gt;/&lt;/strong&gt; を&lt;code&gt;Chrome&lt;/code&gt;で開く.&lt;br&gt;
今度はこのサーバー(&lt;code&gt;nginx&lt;/code&gt;)のクライアント認証に使用するクライアント証明書を選択する画面が開くので, &lt;strong&gt;OK&lt;/strong&gt; を選択する.&lt;br&gt;
これで&lt;code&gt;Chrome&lt;/code&gt;がクライアント証明書を持って&lt;code&gt;nginx&lt;/code&gt;にアクセスするようになる.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Chromeでクライアント証明書を選択" class="gallery-image" data-flex-basis="733px" data-flex-grow="305" height="942" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/sc05.png" srcset="https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/sc05_hu_d29c7d397d40ae1c.png 800w, https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/sc05_hu_23d7d616ff392d4a.png 1600w, https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/sc05_hu_abd50bd2485c9f5a.png 2400w, https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/sc05.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;クライアント認証に成功し,&lt;br&gt;
&lt;code&gt;nginx&lt;/code&gt;のスタートページのHTMLが表示された.&lt;/p&gt;
&lt;p&gt;&lt;img alt="nginx" class="gallery-image" data-flex-basis="1136px" data-flex-grow="473" height="608" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/sc06.png" srcset="https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/sc06_hu_23d228e0ac93b31.png 800w, https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/sc06_hu_9499c6f45572f02e.png 1600w, https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/sc06_hu_a6ae30b82f24ffd6.png 2400w, https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/sc06.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;やったぜ.&lt;br&gt;
これでクライアント認証のしくみを実装することができた.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;以上の手順で&lt;code&gt;OpenSSL&lt;/code&gt;と&lt;code&gt;nginx&lt;/code&gt;を使ったクライアント認証のしくみを試してみた.&lt;br&gt;
不特定多数に公開したくない独自APIをチーム内だけに公開するときとかにサクッと作れると便利そう.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="このあと洗濯機に落ちておこられるねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/sotochan_hu_ffc57b51b97f8c80.jpg 800w, https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/sotochan_hu_4ec3320e9ab3e224.jpg 1600w, https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/sotochan_hu_3dba1dcb09f6c46c.jpg 2400w, https://blog.uzimihsr.com/post/2020-06-26-client-certification-practice/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;h2 id="参考"&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%af%e3%83%a9%e3%82%a4%e3%82%a2%e3%83%b3%e3%83%88%e8%a8%bc%e6%98%8e%e6%9b%b8%e3%81%ae%e4%bd%9c%e6%88%90" &gt;クライアント証明書の作成&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2020-06-03-server-certification-practice/" target="_blank" rel="noopener"
 &gt;nginxとOpenSSLでHTTPSサーバーを立てる&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.openssl.org/docs/man1.1.0/man1/pkcs12.html" target="_blank" rel="noopener"
 &gt;https://www.openssl.org/docs/man1.1.0/man1/pkcs12.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#nginx%e3%81%ae%e8%a8%ad%e5%ae%9a" &gt;nginxの設定&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_client_certificate" target="_blank" rel="noopener"
 &gt;https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_client_certificate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_verify_client" target="_blank" rel="noopener"
 &gt;https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_verify_client&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%af%e3%83%a9%e3%82%a4%e3%82%a2%e3%83%b3%e3%83%88%e8%a8%bc%e6%98%8e%e6%9b%b8%e3%82%92%e7%94%a8%e3%81%84%e3%81%9f%e6%8e%a5%e7%b6%9a" &gt;クライアント証明書を用いた接続&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://curl.haxx.se/docs/manpage.html" target="_blank" rel="noopener"
 &gt;https://curl.haxx.se/docs/manpage.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://support.apple.com/ja-jp/guide/keychain-access/kyca2431/10.5/mac/10.14" target="_blank" rel="noopener"
 &gt;https://support.apple.com/ja-jp/guide/keychain-access/kyca2431/10.5/mac/10.14&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>nginxとOpenSSLでHTTPSサーバーを立てる</title><link>https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/</link><pubDate>Wed, 03 Jun 2020 22:17:33 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sotochan.jpg" alt="Featured image of post nginxとOpenSSLでHTTPSサーバーを立てる" /&gt;&lt;h2 id="オレオレ証明書でhttps"&gt;オレオレ証明書でHTTPS
&lt;/h2&gt;&lt;p&gt;OpenSSLで証明書を作る方法を勉強したので, nginxと組み合わせてHTTPSサーバーを立ててみる.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;オレオレ証明書を使ってルート認証局を立てた&lt;/li&gt;
&lt;li&gt;ルート認証局を使って中間認証局を立てた&lt;/li&gt;
&lt;li&gt;中間認証局でサーバー証明書に署名した&lt;/li&gt;
&lt;li&gt;サーバー証明書をnginxにインストールしてブラウザで確認した&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="ざっくりとしたしくみ" class="gallery-image" data-flex-basis="447px" data-flex-grow="186" height="1161" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/components.png" srcset="https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/components_hu_798df1e9e971836a.png 800w, https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/components_hu_e3d111c1bce0aef9.png 1600w, https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/components.png 2167w" width="2167"&gt;&lt;/p&gt;
&lt;p&gt;サーバー証明書とはHTTPSで通信する際にサーバーの正当性を認証局が証明していることを示すもの.&lt;/p&gt;
&lt;p&gt;クライアントがHTTPSサーバーと通信する際はサーバーの証明書を確認してサーバーの正当性を誰(認証局)が証明しているのかを確認する.&lt;br&gt;
さらにその認証局(中間認証局)の正当性を証明するのがルート認証局で,&lt;br&gt;
クライアントは最初から信頼できるルート認証局の情報を持っているので証明書の発行者をたどることでそのサーバーの正当性を確認することができる.&lt;/p&gt;
&lt;p&gt;今回はこのしくみをローカルでつくって試してみる.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;OpenSSL&lt;/code&gt;の使い方とかは既にメモを作成済み.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2020-05-20-public-key-practice/" target="_blank" rel="noopener"
 &gt;OpenSSLで秘密鍵と公開鍵を作る&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2020-05-24-hybrid-encryption-practice/" target="_blank" rel="noopener"
 &gt;OpenSSLで共通鍵暗号方式とハイブリッド暗号方式を試す&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2020-05-30-certification-practice/" target="_blank" rel="noopener"
 &gt;OpenSSLでデジタル証明書を試す&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Raspberry Pi 3 Model B+
&lt;ul&gt;
&lt;li&gt;OSはRaspbian(10.0)&lt;/li&gt;
&lt;li&gt;SSLサーバーとして使用&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;OpenSSL
&lt;ul&gt;
&lt;li&gt;OpenSSL 1.1.1c 28 May 2019&lt;/li&gt;
&lt;li&gt;ラズパイの初期装備&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;nginx
&lt;ul&gt;
&lt;li&gt;version 1.14.2&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2020-01-29-nginx/" target="_blank" rel="noopener"
 &gt;インストール済み&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;macOS Mojave 10.14
&lt;ul&gt;
&lt;li&gt;ブラウザ用&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Google Chrome
&lt;ul&gt;
&lt;li&gt;バージョン: 83.0.4103.61（Official Build） （64 ビット）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%aa%e3%83%ac%e3%82%aa%e3%83%ac%e8%a8%bc%e6%98%8e%e6%9b%b8%e3%81%a8%e3%83%ab%e3%83%bc%e3%83%88%e8%aa%8d%e8%a8%bc%e5%b1%80%e3%81%ae%e4%bd%9c%e6%88%90" &gt;オレオレ証明書とルート認証局の作成&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e4%b8%ad%e9%96%93%e8%a8%bc%e6%98%8e%e6%9b%b8%e3%81%a8%e4%b8%ad%e9%96%93%e8%aa%8d%e8%a8%bc%e5%b1%80%e3%81%ae%e4%bd%9c%e6%88%90" &gt;中間証明書と中間認証局の作成&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%b5%e3%83%bc%e3%83%90%e3%83%bc%e8%a8%bc%e6%98%8e%e6%9b%b8%e3%81%ae%e4%bd%9c%e6%88%90" &gt;サーバー証明書の作成&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#nginx%e3%81%ab%e8%a8%bc%e6%98%8e%e6%9b%b8%e3%82%92%e6%8c%81%e3%81%9f%e3%81%9b%e3%82%8b" &gt;nginxに証明書を持たせる&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="オレオレ証明書とルート認証局の作成"&gt;オレオレ証明書とルート認証局の作成
&lt;/h3&gt;&lt;p&gt;本来であれば正式な認証局に依頼してちゃんとしたサーバー証明書を作ってもらうべきなんだけど,&lt;br&gt;
お金もかかるし自分で遊ぶだけなのでオレオレ証明書でルート認証局を立ててみる.&lt;/p&gt;
&lt;p&gt;まずは&lt;code&gt;OpenSSL&lt;/code&gt;でオレオレ証明書用の秘密鍵を作成する.&lt;br&gt;
普段は&lt;code&gt;genrsa&lt;/code&gt;を使ってるんだけど&lt;code&gt;genpkey&lt;/code&gt;のほうが新しくてオススメされているみたいなのでそちらで作ってみる.&lt;br&gt;
(&lt;code&gt;OpenSSL&lt;/code&gt;のサブコマンド多すぎ問題)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;## 以下すべてラズパイで実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ルート認証局用ディレクトリ(RootCA)で作業&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mkdir RootCA &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; RootCA
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ルート認証局用の秘密鍵(RootCA-private-key.pem)を作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl genpkey -algorithm RSA -out RootCA-private-key.pem&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;秘密鍵からルート認証局の正当性を主張するためのオレオレ証明書を作成する.&lt;br&gt;
質問の内容は適当でいい. はず&amp;hellip;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ルート認証局の秘密鍵(RootCA-private-key.pem)を使ったオレオレ証明書(RootCA.pem)の作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl req -x509 -key RootCA-private-key.pem -out RootCA.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;You are about to be asked to enter information that will be incorporated
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;into your certificate request.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;What you are about to enter is what is called a Distinguished Name or a DN.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;There are quite a few fields but you can leave some blank
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;For some fields there will be a default value,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;If you enter &lt;span class="s1"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;, the field will be left blank.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-----
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Country Name &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; letter code&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;AU&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;State or Province Name &lt;span class="o"&gt;(&lt;/span&gt;full name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Some-State&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Locality Name &lt;span class="o"&gt;(&lt;/span&gt;eg, city&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Organization Name &lt;span class="o"&gt;(&lt;/span&gt;eg, company&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Internet Widgits Pty Ltd&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Organizational Unit Name &lt;span class="o"&gt;(&lt;/span&gt;eg, section&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Common Name &lt;span class="o"&gt;(&lt;/span&gt;e.g. server FQDN or YOUR name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:RootCA &lt;span class="c1"&gt;# ここだけ入れてみる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Email Address &lt;span class="o"&gt;[]&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;オレオレ証明書ができたので, これでルート認証局ができた.&lt;/p&gt;
&lt;p&gt;この認証局は自分で自分の正当性を主張しているだけで公的な信頼は一切ないので注意.&lt;br&gt;
繰り返しになるけどちゃんとしたSSLサーバーを立てたいならここは公的な認証局にお願いするべき.&lt;/p&gt;
&lt;h3 id="中間証明書と中間認証局の作成"&gt;中間証明書と中間認証局の作成
&lt;/h3&gt;&lt;p&gt;作成したルート認証局でそのままサーバー証明書を作ってもいいんだけど,&lt;br&gt;
今回は勉強のために中間認証局を立てて, その正当性を先程作ったルート認証局で証明する.&lt;/p&gt;
&lt;p&gt;まずは中間認証局用の秘密鍵を作成する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 中間認証局用ディレクトリ(IntermediateCA)で作業&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; ..
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mkdir IntermediateCA &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; IntermediateCA
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 中間認証局用の秘密鍵(RootCA-private-key.pem)を作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl genpkey -algorithm RSA -out IntermediateCA-private-key.pem&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;この中間認証局の正当性をオレオレ証明書以外で証明するには他の認証局にお願いするしかないので,&lt;br&gt;
証明書署名要求(&lt;code&gt;CSR&lt;/code&gt;)を作成する.&lt;br&gt;
質問の内容はこちらも適当でいい. はず&amp;hellip;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 中間認証局の秘密鍵(IntermediateCA-private-key.pem)から中間認証局のCSR(IntermediateCA-csr.pem)を作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl req -new -key IntermediateCA-private-key.pem -out IntermediateCA-csr.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;You are about to be asked to enter information that will be incorporated
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;into your certificate request.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;What you are about to enter is what is called a Distinguished Name or a DN.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;There are quite a few fields but you can leave some blank
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;For some fields there will be a default value,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;If you enter &lt;span class="s1"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;, the field will be left blank.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-----
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Country Name &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; letter code&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;AU&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;State or Province Name &lt;span class="o"&gt;(&lt;/span&gt;full name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Some-State&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Locality Name &lt;span class="o"&gt;(&lt;/span&gt;eg, city&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Organization Name &lt;span class="o"&gt;(&lt;/span&gt;eg, company&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Internet Widgits Pty Ltd&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Organizational Unit Name &lt;span class="o"&gt;(&lt;/span&gt;eg, section&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Common Name &lt;span class="o"&gt;(&lt;/span&gt;e.g. server FQDN or YOUR name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:IntermediateCA &lt;span class="c1"&gt;# ここだけ入れてみる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Email Address &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Please enter the following &lt;span class="s1"&gt;&amp;#39;extra&amp;#39;&lt;/span&gt; attributes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;to be sent with your certificate request
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;A challenge password &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;An optional company name &lt;span class="o"&gt;[]&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;作成した中間認証局の&lt;code&gt;CSR&lt;/code&gt;をルート認証局に渡し, ルート認証局はそれに署名して中間認証局の正当性を証明する&amp;hellip;&lt;br&gt;
つもりだったのに怒られてしまった.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 中間認証局のCSR(IntermediateCA-csr.pem)をルート認証局に渡す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mv IntermediateCA-csr.pem ../RootCA/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ルート認証局の秘密鍵(RootCA-private-key.pem)とルート証明書(RootCA.pem)で&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 中間認証局のCSR(IntermediateCA-csr.pem)に署名して中間証明書(IntermediateCA-certicifation.pem)を作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# したかったけど怒られた...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; ../RootCA
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl ca -in IntermediateCA-csr.pem -out IntermediateCA-certicifation.pem -keyfile RootCA-private-key.pem -cert RootCA.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Using configuration from /usr/lib/ssl/openssl.cnf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ca: ./demoCA/newcerts is not a directory
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;./demoCA/newcerts: No such file or directory&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;なんかディレクトリ&lt;code&gt;./demoCA/newcerts&lt;/code&gt;が足りてないらしいので作って再挑戦.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ディレクトリを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mkdir -p demoCA/newcerts
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 再挑戦したけどだめ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl ca -in IntermediateCA-csr.pem -out IntermediateCA-certicifation.pem -keyfile RootCA-private-key.pem -cert RootCA.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Using configuration from /usr/lib/ssl/openssl.cnf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1996152848:error:02001002:system library:fopen:No such file or directory:../crypto/bio/bss_file.c:72:fopen&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;./demoCA/index.txt&amp;#39;&lt;/span&gt;,&lt;span class="s1"&gt;&amp;#39;r&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1996152848:error:2006D080:BIO routines:BIO_new_file:no such file:../crypto/bio/bss_file.c:79:&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;また怒られた.&lt;br&gt;
ファイル&lt;code&gt;./demoCA/index.txt&lt;/code&gt;が足りてないみたいなので空ファイルを作る.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 空ファイルを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ touch ./demoCA/index.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 再挑戦したけどだめ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl ca -in IntermediateCA-csr.pem -out IntermediateCA-certicifation.pem -keyfile RootCA-private-key.pem -cert RootCA.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Using configuration from /usr/lib/ssl/openssl.cnf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;./demoCA/serial: No such file or directory
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;error &lt;span class="k"&gt;while&lt;/span&gt; loading serial number
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1995452432:error:02001002:system library:fopen:No such file or directory:../crypto/bio/bss_file.c:72:fopen&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;./demoCA/serial&amp;#39;&lt;/span&gt;,&lt;span class="s1"&gt;&amp;#39;r&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1995452432:error:2006D080:BIO routines:BIO_new_file:no such file:../crypto/bio/bss_file.c:79:&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;またまた怒られた. つらい.&lt;br&gt;
ファイル&lt;code&gt;/demoCA/serial&lt;/code&gt;が足りてないらしい.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 空ファイルを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ touch ./demoCA/serial
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 再挑戦したけどだめ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl ca -in IntermediateCA-csr.pem -out IntermediateCA-certicifation.pem -keyfile RootCA-private-key.pem -cert RootCA.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Using configuration from /usr/lib/ssl/openssl.cnf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;unable to load number from ./demoCA/serial
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;error &lt;span class="k"&gt;while&lt;/span&gt; loading serial number
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1995870224:error:0D066096:asn1 encoding routines:a2i_ASN1_INTEGER:short line:../crypto/asn1/f_int.c:140:&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;またまたまた怒られた. キレそう.&lt;br&gt;
今度はシリアルナンバーが読めないよ的なエラーが出ているので, 適当な数字を入れてあげる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 空ファイルに適当な数字を書き込む&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="m"&gt;00&lt;/span&gt; &amp;gt;&amp;gt; ./demoCA/serial
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# いけた&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl ca -in IntermediateCA-csr.pem -out IntermediateCA-certicifation.pem -keyfile RootCA-private-key.pem -cert RootCA.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Using configuration from /usr/lib/ssl/openssl.cnf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Check that the request matches the signature
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Signature ok
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Certificate Details:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Serial Number: &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;0x0&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Validity
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Not Before: Jun &lt;span class="m"&gt;1&lt;/span&gt; 14:24:19 &lt;span class="m"&gt;2020&lt;/span&gt; GMT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Not After : Jun &lt;span class="m"&gt;1&lt;/span&gt; 14:24:19 &lt;span class="m"&gt;2021&lt;/span&gt; GMT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Subject:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;countryName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; AU
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;stateOrProvinceName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; Some-State
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;organizationName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; Internet Widgits Pty Ltd
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;commonName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; IntermediateCA
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; X509v3 extensions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; X509v3 Basic Constraints:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; CA:FALSE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Netscape Comment:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; OpenSSL Generated Certificate
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; X509v3 Subject Key Identifier:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; FF:A3:92:E0:F3:10:A9:28:AC:5F:4A:D2:BE:FD:D7:2B:19:EC:DD:02
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; X509v3 Authority Key Identifier:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; keyid:A9:96:E7:CD:B2:77:F2:8F:CA:4C:4A:E9:75:52:91:3E:6C:53:42:0B
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Certificate is to be certified &lt;span class="k"&gt;until&lt;/span&gt; Jun &lt;span class="m"&gt;1&lt;/span&gt; 14:24:19 &lt;span class="m"&gt;2021&lt;/span&gt; GMT &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;365&lt;/span&gt; days&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Sign the certificate? &lt;span class="o"&gt;[&lt;/span&gt;y/n&lt;span class="o"&gt;]&lt;/span&gt;:y
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;1&lt;/span&gt; out of &lt;span class="m"&gt;1&lt;/span&gt; certificate requests certified, commit? &lt;span class="o"&gt;[&lt;/span&gt;y/n&lt;span class="o"&gt;]&lt;/span&gt;y
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Write out database with &lt;span class="m"&gt;1&lt;/span&gt; new entries
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Data Base Updated&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;こんどは成功した.&lt;/p&gt;
&lt;p&gt;ちなみに&lt;code&gt;./demoCA/index.txt&lt;/code&gt;は証明書発行の記録を残すためのファイルで,&lt;br&gt;
&lt;code&gt;/demoCA/serial&lt;/code&gt;はシリアルナンバーを設定するためのファイルだったらしい.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# index.txtの内容を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat ./demoCA/index.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;V	210601142419Z		00	unknown	/C&lt;span class="o"&gt;=&lt;/span&gt;AU/ST&lt;span class="o"&gt;=&lt;/span&gt;Some-State/O&lt;span class="o"&gt;=&lt;/span&gt;Internet Widgits Pty Ltd/CN&lt;span class="o"&gt;=&lt;/span&gt;IntermediateCA&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;あとはルート認証局で作成した中間認証局の証明書(中間証明書)を中間認証局に渡す.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 中間証明書(IntermediateCA-certicifation.pem)を中間認証局に返す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mv IntermediateCA-certicifation.pem ../IntermediateCA/&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;これで中間認証局の正当性をルート認証局が証明したことになる.&lt;/p&gt;
&lt;h3 id="サーバー証明書の作成"&gt;サーバー証明書の作成
&lt;/h3&gt;&lt;p&gt;認証局の準備ができたので,&lt;br&gt;
いよいよHTTPSで使うためのサーバー証明書を作る.&lt;/p&gt;
&lt;p&gt;まずは中間認証局を立てたときと同じようにサーバーの正当性を証明するための&lt;code&gt;CSR&lt;/code&gt;を作成する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# サーバー用ディレクトリ(Server)で作業&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; ..
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mkdir Server &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; Server
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# サーバー用の秘密鍵(Server-private-key.pem)を作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl genpkey -algorithm RSA -out Server-private-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# サーバーの秘密鍵(Server-private-key.pem)からCSR(Server-csr.pem)を作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl req -new -key Server-private-key.pem -out Server-csr.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;You are about to be asked to enter information that will be incorporated
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;into your certificate request.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;What you are about to enter is what is called a Distinguished Name or a DN.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;There are quite a few fields but you can leave some blank
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;For some fields there will be a default value,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;If you enter &lt;span class="s1"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;, the field will be left blank.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-----
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Country Name &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; letter code&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;AU&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;State or Province Name &lt;span class="o"&gt;(&lt;/span&gt;full name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Some-State&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Locality Name &lt;span class="o"&gt;(&lt;/span&gt;eg, city&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Organization Name &lt;span class="o"&gt;(&lt;/span&gt;eg, company&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Internet Widgits Pty Ltd&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Organizational Unit Name &lt;span class="o"&gt;(&lt;/span&gt;eg, section&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Common Name &lt;span class="o"&gt;(&lt;/span&gt;e.g. server FQDN or YOUR name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:uzimihsr.example.com &lt;span class="c1"&gt;# ここだけ入れてみる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Email Address &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Please enter the following &lt;span class="s1"&gt;&amp;#39;extra&amp;#39;&lt;/span&gt; attributes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;to be sent with your certificate request
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;A challenge password &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;An optional company name &lt;span class="o"&gt;[]&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;サーバーの&lt;code&gt;CSR&lt;/code&gt;を中間認証局に渡し,&lt;br&gt;
中間認証局は受け取った&lt;code&gt;CSR&lt;/code&gt;に署名してサーバー証明書を作成する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# サーバーのCSR(Server-csr.pem)を中間認証局に渡す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mv Server-csr.pem ../IntermediateCA/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 署名のための準備&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; ../IntermediateCA
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mkdir -p demoCA/newcerts
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ touch ./demoCA/index.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="m"&gt;01&lt;/span&gt; &amp;gt; ./demoCA/serial
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 中間認証局の秘密鍵(IntermediateCA-private-key.pem)と中間証明書(IntermediateCA-certicifation.pem)で&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# サーバーのCSR(Server-csr.pem)に署名してサーバー証明書(Server-certicifation.pem)を作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl ca -in Server-csr.pem -out Server-certicifation.pem -keyfile IntermediateCA-private-key.pem -cert IntermediateCA-certicifation.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Using configuration from /usr/lib/ssl/openssl.cnf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Check that the request matches the signature
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Signature ok
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Certificate Details:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Serial Number: &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;0x1&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Validity
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Not Before: Jun &lt;span class="m"&gt;1&lt;/span&gt; 14:49:49 &lt;span class="m"&gt;2020&lt;/span&gt; GMT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Not After : Jun &lt;span class="m"&gt;1&lt;/span&gt; 14:49:49 &lt;span class="m"&gt;2021&lt;/span&gt; GMT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Subject:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;countryName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; AU
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;stateOrProvinceName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; Some-State
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;organizationName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; Internet Widgits Pty Ltd
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;commonName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; uzimihsr.example.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; X509v3 extensions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; X509v3 Basic Constraints:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; CA:FALSE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Netscape Comment:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; OpenSSL Generated Certificate
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; X509v3 Subject Key Identifier:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 67:F1:62:B9:B4:FB:81:BD:E9:11:55:45:CF:43:D1:59:0B:66:D9:10
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; X509v3 Authority Key Identifier:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; keyid:FF:A3:92:E0:F3:10:A9:28:AC:5F:4A:D2:BE:FD:D7:2B:19:EC:DD:02
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Certificate is to be certified &lt;span class="k"&gt;until&lt;/span&gt; Jun &lt;span class="m"&gt;1&lt;/span&gt; 14:49:49 &lt;span class="m"&gt;2021&lt;/span&gt; GMT &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;365&lt;/span&gt; days&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Sign the certificate? &lt;span class="o"&gt;[&lt;/span&gt;y/n&lt;span class="o"&gt;]&lt;/span&gt;:y
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;1&lt;/span&gt; out of &lt;span class="m"&gt;1&lt;/span&gt; certificate requests certified, commit? &lt;span class="o"&gt;[&lt;/span&gt;y/n&lt;span class="o"&gt;]&lt;/span&gt;y
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Write out database with &lt;span class="m"&gt;1&lt;/span&gt; new entries
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Data Base Updated
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# サーバーに証明書(Server-certicifation.pem)を渡す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mv ./Server-certicifation.pem ../Server/&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;以上の手順でサーバーの正当性を中間認証局が証明したことになる.&lt;/p&gt;
&lt;h3 id="nginxに証明書を持たせる"&gt;nginxに証明書を持たせる
&lt;/h3&gt;&lt;p&gt;サーバーの証明書ができたので,&lt;br&gt;
これを&lt;code&gt;nginx&lt;/code&gt;に持たせてHTTPSサーバーを建てる.&lt;/p&gt;
&lt;p&gt;まずはサーバー証明書の発行元の正当性を証明するために,&lt;br&gt;
ルート証明書と中間証明書とサーバー証明書をくっつける.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# サーバー証明書(Server-certicifation.pem), 中間証明書(IntermediateCA-certicifation.pem), ルート証明書(RootCA.pem)をくっつける(cert.pem)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; ../Server
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat Server-certicifation.pem ../IntermediateCA/IntermediateCA-certicifation.pem ../RootCA/RootCA.pem &amp;gt; cert.pem&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;次に&lt;code&gt;nginx&lt;/code&gt;にHTTPSサーバーとして動かすための設定を追加する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# nginx設定ファイルの作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo vim /etc/nginx/conf.d/https.conf&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;script src="https://gist.github.com/uzimihsr/7e4c3134a7d0d768896993344bfadc4f.js"&gt;&lt;/script&gt;
&lt;p&gt;&lt;code&gt;nginx.conf&lt;/code&gt;は初期設定のまま.&lt;/p&gt;
&lt;script src="https://gist.github.com/uzimihsr/7bb2bd80d55a2bc75fad0842e63df881.js"&gt;&lt;/script&gt;
&lt;p&gt;&lt;code&gt;https.conf&lt;/code&gt;で指定している場所にサーバーの証明書と秘密鍵を配置する.&lt;br&gt;
これにより, &lt;code&gt;nginx&lt;/code&gt;がHTTPSでリクエストを受けたときにクライアントにこの証明書を提示できるようになる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# サーバー証明書(cert.pem)と秘密鍵(Server-private-key.pem)の配置&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo mkdir /etc/nginx/https
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo cp ./cert.pem /etc/nginx/https/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo cp ./Server-private-key.pem /etc/nginx/https/&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;ここまでできたら,&lt;br&gt;
&lt;code&gt;nginx&lt;/code&gt;を再起動する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# nginxの設定を確認して再起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo nginx -t
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nginx: configuration file /etc/nginx/nginx.conf &lt;span class="nb"&gt;test&lt;/span&gt; is successful
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl restart nginx&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;ここまでできたら, Macのブラウザで &lt;strong&gt;https://&amp;lt;ラズパイのIP&amp;gt;/&lt;/strong&gt; を開く.&lt;br&gt;
しかしこのサーバー(&lt;code&gt;nginx&lt;/code&gt;)から提示された証明書がMacに信頼されていないため, 警告が出てしまう.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Chromeの警告" class="gallery-image" data-flex-basis="384px" data-flex-grow="160" height="1800" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc01.png" srcset="https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc01_hu_cbeda749c4887dc5.png 800w, https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc01_hu_649c2948de034036.png 1600w, https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc01_hu_bce7de91b7c1e845.png 2400w, https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc01.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;左上の鍵マークから証明書を表示して確認する.&lt;/p&gt;
&lt;p&gt;&lt;img alt="証明書の確認" class="gallery-image" data-flex-basis="556px" data-flex-grow="231" height="1243" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc02.png" srcset="https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc02_hu_bad3158f88e78c02.png 800w, https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc02_hu_57d6856c90364b17.png 1600w, https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc02_hu_679886e903e60c29.png 2400w, https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc02.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;サーバー証明書(&lt;strong&gt;uzimihsr.example.com&lt;/strong&gt;)が表示される.&lt;br&gt;
この証明書は中間認証局(&lt;strong&gt;IntermediateCA&lt;/strong&gt;)が発行者になっているが,&lt;br&gt;
これが公的な認証局でないために信頼できない状態であることがわかる.&lt;/p&gt;
&lt;p&gt;&lt;img alt="証明書の内容" class="gallery-image" data-flex-basis="557px" data-flex-grow="232" height="1239" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc03.png" srcset="https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc03_hu_68bbb3396f1de96c.png 800w, https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc03_hu_3bf4a952c68b882d.png 1600w, https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc03_hu_9b8ac589340dcd9.png 2400w, https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc03.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;nginx&lt;/code&gt;に持たせた証明書はサーバー証明書の他に中間証明書とルート証明書が連結してあるので,&lt;br&gt;
これらの内容も確認できる.&lt;/p&gt;
&lt;p&gt;中間証明書(&lt;strong&gt;IntermediateCA&lt;/strong&gt;)を確認する.&lt;br&gt;
こちらはルート認証局(&lt;strong&gt;RootCA&lt;/strong&gt;)によって発行されているが,&lt;br&gt;
これも公的な認証局でないために信頼されていない.&lt;/p&gt;
&lt;p&gt;&lt;img alt="証明書の内容" class="gallery-image" data-flex-basis="562px" data-flex-grow="234" height="1228" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc04.png" srcset="https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc04_hu_7034dd1de26c5c63.png 800w, https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc04_hu_d14531b7141186df.png 1600w, https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc04_hu_a578af8f0a31091c.png 2400w, https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc04.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;ルート証明書(&lt;strong&gt;RootCA&lt;/strong&gt;)についても同様.&lt;br&gt;
ルート認証局はどれもオレオレ証明書で自分の正当性を主張しているが,&lt;br&gt;
Macはこのルート認証局が信頼できる認証局のリストにないため,&lt;br&gt;
この認証局が発行した証明書を信頼していない状態であることがわかる.&lt;/p&gt;
&lt;p&gt;&lt;img alt="証明書の内容" class="gallery-image" data-flex-basis="559px" data-flex-grow="233" height="1236" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc05.png" srcset="https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc05_hu_f36b1ee8098edee0.png 800w, https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc05_hu_a29a79d24620316b.png 1600w, https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc05_hu_499c1fa457d06ff5.png 2400w, https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc05.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;このままだと&lt;code&gt;nginx&lt;/code&gt;の画面が開けないので,&lt;br&gt;
サーバー証明書をMacに信頼させるようにする.&lt;/p&gt;
&lt;p&gt;まずはChromeの証明書を開いている画面からサーバー証明書のアイコンをデスクトップにドラッグ&amp;amp;ドロップする.&lt;/p&gt;
&lt;p&gt;&lt;img alt="証明書の取得" class="gallery-image" data-flex-basis="345px" data-flex-grow="144" height="1888" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc06.png" srcset="https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc06_hu_7a21f456617f0a12.png 800w, https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc06_hu_c691956b0ce0c176.png 1600w, https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc06_hu_2f7a3b209f3b2cdb.png 2400w, https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc06.png 2720w" width="2720"&gt;&lt;/p&gt;
&lt;p&gt;デスクトップに落ちた証明書をダブルクリックすると,&lt;br&gt;
&lt;code&gt;キーチェーンアクセス&lt;/code&gt;が開く.&lt;/p&gt;
&lt;p&gt;&lt;img alt="キーチェーンアクセス" class="gallery-image" data-flex-basis="336px" data-flex-grow="140" height="1410" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc07.png" srcset="https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc07_hu_b3c93a41ff45149f.png 800w, https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc07_hu_8bfc7017e25016ae.png 1600w, https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc07.png 1978w" width="1978"&gt;&lt;/p&gt;
&lt;p&gt;サーバー証明書をダブルクリックすると詳細画面が開くので,&lt;br&gt;
&lt;code&gt;信頼&lt;/code&gt;-&amp;gt;&lt;code&gt;この証明書を信頼するとき&lt;/code&gt;を&lt;code&gt;常に信頼&lt;/code&gt;に変更してウィンドウを閉じる.&lt;br&gt;
これでMacがこの証明書を信頼するようになった.&lt;/p&gt;
&lt;p&gt;&lt;img alt="証明書を信頼する" class="gallery-image" data-flex-basis="275px" data-flex-grow="114" height="1088" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc08.png" srcset="https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc08_hu_bae3edaf4a27a66a.png 800w, https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc08.png 1250w" width="1250"&gt;&lt;/p&gt;
&lt;p&gt;再度Macのブラウザで &lt;strong&gt;https://&amp;lt;ラズパイのIP&amp;gt;/&lt;/strong&gt; を開く.&lt;br&gt;
今度は&lt;code&gt;nginx&lt;/code&gt;のデフォルト画面が開けた.&lt;/p&gt;
&lt;p&gt;&lt;img alt="nginx" class="gallery-image" data-flex-basis="1091px" data-flex-grow="454" height="633" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc09.png" srcset="https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc09_hu_46d5127b28aa01d1.png 800w, https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc09_hu_1e8b57b1fdf4e19d.png 1600w, https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc09_hu_cefa94f6f285f052.png 2400w, https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc09.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;サーバー証明書を確認すると, 確かにこれが信頼されていることがわかる.&lt;/p&gt;
&lt;p&gt;&lt;img alt="証明書" class="gallery-image" data-flex-basis="635px" data-flex-grow="264" height="1088" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc10.png" srcset="https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc10_hu_cfc850d5a8cb0da6.png 800w, https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc10_hu_9ddac081b4b686c2.png 1600w, https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc10_hu_2775b3d0ef6879d1.png 2400w, https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sc10.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;やったぜ.&lt;br&gt;
&lt;code&gt;OpenSSL&lt;/code&gt;と&lt;code&gt;nginx&lt;/code&gt;でHTTPSサーバーを建てることができた.&lt;/p&gt;
&lt;p&gt;本当は他のHTTPSで提供されているサイトみたいにアドレスの左側に緑の鍵マークを表示させたいんだけど,&lt;br&gt;
&lt;code&gt;Chrome&lt;/code&gt;はちょっと厳しくて発行時に&lt;code&gt;CN&lt;/code&gt;だけじゃなくて&lt;code&gt;SANs&lt;/code&gt;もちゃんと設定した証明書じゃないといけないらしい&amp;hellip;&lt;br&gt;
とりあえず今回はサーバー証明書の練習が目的だったのでここまでで終わりにする.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;以上の手順で&lt;code&gt;OpenSSL&lt;/code&gt;でサーバー証明書を作って&lt;code&gt;nginx&lt;/code&gt;にもたせてHTTPSサーバーを建てることができた.&lt;br&gt;
時間とレンタルサーバーを借りるお金の余裕があれば,&lt;br&gt;
無料で証明書を発行できる&lt;a class="link" href="https://letsencrypt.org/ja/" target="_blank" rel="noopener"
 &gt;Let’s Encrypt&lt;/a&gt;とかでちゃんとしたHTTPSサーバーを立ててみたい.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="バチクソに遊んで疲れ果てたねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sotochan_hu_4e7d9e1a3d650034.jpg 800w, https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sotochan_hu_420fd089e2bfa0a6.jpg 1600w, https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sotochan_hu_a4eaef40aaeb2fc8.jpg 2400w, https://blog.uzimihsr.com/post/2020-06-03-server-certification-practice/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;h2 id="参考"&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%aa%e3%83%ac%e3%82%aa%e3%83%ac%e8%a8%bc%e6%98%8e%e6%9b%b8%e3%81%a8%e3%83%ab%e3%83%bc%e3%83%88%e8%aa%8d%e8%a8%bc%e5%b1%80%e3%81%ae%e4%bd%9c%e6%88%90" &gt;オレオレ証明書とルート認証局の作成&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.openssl.org/docs/man1.1.0/man1/genpkey.html" target="_blank" rel="noopener"
 &gt;https://www.openssl.org/docs/man1.1.0/man1/genpkey.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://wiki.openssl.org/index.php/Command_Line_Utilities" target="_blank" rel="noopener"
 &gt;https://wiki.openssl.org/index.php/Command_Line_Utilities&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.openssl.org/docs/man1.1.0/man1/x509.html" target="_blank" rel="noopener"
 &gt;https://www.openssl.org/docs/man1.1.0/man1/x509.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e4%b8%ad%e9%96%93%e8%a8%bc%e6%98%8e%e6%9b%b8%e3%81%a8%e4%b8%ad%e9%96%93%e8%aa%8d%e8%a8%bc%e5%b1%80%e3%81%ae%e4%bd%9c%e6%88%90" &gt;中間証明書と中間認証局の作成&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%b5%e3%83%bc%e3%83%90%e3%83%bc%e8%a8%bc%e6%98%8e%e6%9b%b8%e3%81%ae%e4%bd%9c%e6%88%90" &gt;サーバー証明書の作成&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.openssl.org/docs/man1.1.0/man1/req.html" target="_blank" rel="noopener"
 &gt;https://www.openssl.org/docs/man1.1.0/man1/req.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.openssl.org/docs/man1.1.0/man1/ca.html" target="_blank" rel="noopener"
 &gt;https://www.openssl.org/docs/man1.1.0/man1/ca.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#nginx%e3%81%ab%e8%a8%bc%e6%98%8e%e6%9b%b8%e3%82%92%e6%8c%81%e3%81%9f%e3%81%9b%e3%82%8b" &gt;nginxに証明書を持たせる&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://nginx.org/en/docs/http/configuring_https_servers.html" target="_blank" rel="noopener"
 &gt;https://nginx.org/en/docs/http/configuring_https_servers.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://support.apple.com/ja-jp/guide/keychain-access/kyca11871/mac" target="_blank" rel="noopener"
 &gt;https://support.apple.com/ja-jp/guide/keychain-access/kyca11871/mac&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>5月のそとちゃんまとめ(2020)</title><link>https://blog.uzimihsr.com/post/2020-05-31-sotochan/</link><pubDate>Sun, 31 May 2020 21:57:23 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-05-31-sotochan/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-05-31-sotochan/sotochan.jpg" alt="Featured image of post 5月のそとちゃんまとめ(2020)" /&gt;&lt;h2 id="記念日だったりした"&gt;記念日だったりした
&lt;/h2&gt;&lt;p&gt;今月のそとちゃんはいろいろあったのでまとめ.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#1%e5%91%a8%e5%b9%b4" &gt;1周年&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e6%9c%9d%e3%81%ae%e3%83%ab%e3%83%bc%e3%83%86%e3%82%a3%e3%83%b3" &gt;朝のルーティン&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%8f%e3%83%b3%e3%83%a2%e3%83%83%e3%82%af" &gt;ハンモック&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e5%85%83%e6%b0%97%e3%81%8c%e6%9c%89%e3%82%8a%e4%bd%99%e3%81%a3%e3%81%a6%e3%81%84%e3%82%8b" &gt;元気が有り余っている&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="1周年"&gt;1周年
&lt;/h3&gt;&lt;p&gt;まずはなんといっても1周年記念日.&lt;br&gt;
そとちゃんは&lt;a class="link" href="https://uzimihsr.github.io/post/2019-08-24-sotochan-story/" target="_blank" rel="noopener"
 &gt;元号が令和に変わった日&lt;/a&gt;にうちに来たので,&lt;br&gt;
5/1で一緒に暮らし始めてからちょうど1年になった.&lt;br&gt;
本当の年齢も誕生日もわからないので, この日で&lt;code&gt;たぶん4さい&lt;/code&gt;ということにした.&lt;/p&gt;
&lt;p&gt;本当は&lt;code&gt;たぶん4さい&lt;/code&gt;をちゃんと猫用ケーキでお祝いしたかったんだけど,&lt;br&gt;
コロナうんぬんで慌ただしい時期だったのでそとちゃんのお気に入りおやつ全部乗せをプレゼントした.&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://www.instagram.com/p/B_pQQ6IlSB4/?utm_source=ig_web_copy_link" target="_blank" rel="noopener"
 &gt;Instagram&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;余裕でカロリーオーバーなのでかわいそうだけど次の日はおやつ抜きだった&amp;hellip;&lt;/p&gt;
&lt;p&gt;来年こそはカロリーに配慮したおいしいケーキでお祝いしてあげたい.&lt;/p&gt;
&lt;h3 id="朝のルーティン"&gt;朝のルーティン
&lt;/h3&gt;&lt;p&gt;理由は謎だけど,&lt;br&gt;
先月の終わり頃から朝お腹の上に乗ってきておしりを見せてくれることが多くなった.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;朝 &lt;a href="https://t.co/1LinJL4LyT"&gt;pic.twitter.com/1LinJL4LyT&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1255999383885066240?ref_src=twsrc%5Etfw"&gt;April 30, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;朝だからおしり見せにきた &lt;a href="https://t.co/QmhZQlE5wy"&gt;pic.twitter.com/QmhZQlE5wy&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1262526817593769985?ref_src=twsrc%5Etfw"&gt;May 18, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;おはようございます &lt;a href="https://t.co/zg3nprMEgC"&gt;pic.twitter.com/zg3nprMEgC&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1262893440804646913?ref_src=twsrc%5Etfw"&gt;May 19, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;朝だからおしり見せてくれる &lt;a href="https://t.co/8smYOnYCDi"&gt;pic.twitter.com/8smYOnYCDi&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1266146877541462016?ref_src=twsrc%5Etfw"&gt;May 28, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;まるいおしりがおまんじゅうみたいでかわいいけどちょっとくさい.&lt;br&gt;
でも猫がおしりを向けてくるのは信頼の証らしいので嬉しくもある.&lt;/p&gt;
&lt;p&gt;けどやっぱりちょっとくさい.&lt;br&gt;
うんちのにおいで起こされると気分があまりよくない.&lt;br&gt;
でもかわいいからしょうがないね.&lt;/p&gt;
&lt;h3 id="ハンモック"&gt;ハンモック
&lt;/h3&gt;&lt;p&gt;そとちゃんは窓から外の景色を眺めるのが好きなので,&lt;br&gt;
外が見やすくなるように窓に取り付けるタイプの猫用ハンモックを買ってみた.&lt;/p&gt;
&lt;p&gt;最初はやっぱり警戒しておやつで釣らないと乗ってくれなかったんだけど,&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://www.instagram.com/p/CAWr_1jh7UY/?utm_source=ig_web_copy_link" target="_blank" rel="noopener"
 &gt;instagram&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;1週間くらいしたら慣れて自分で乗るようになった.&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://twitter.com/uzimihsr/status/1264456579127971841" target="_blank" rel="noopener"
 &gt;https://twitter.com/uzimihsr/status/1264456579127971841&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;特に夜は車が走ってるのを見るのがトレンドらしい.&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://www.instagram.com/p/CAdFGQ-g0LK/?utm_source=ig_web_copy_link" target="_blank" rel="noopener"
 &gt;Instagram&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;うちはちょっと日当たりが悪いので, これで思う存分ひなたぼっこを楽しんでほしい.&lt;/p&gt;
&lt;p&gt;そろそろ暑くなってくるので熱中症がちょっとだけ心配.&lt;br&gt;
(ねこ, 暑さよりも居心地の良さを優先して動かないんだとか)&lt;/p&gt;
&lt;h3 id="元気が有り余っている"&gt;元気が有り余っている
&lt;/h3&gt;&lt;p&gt;今月も健康面では特に問題なく, なんかやたら元気だった.&lt;/p&gt;
&lt;p&gt;動画は撮れてないけど,&lt;br&gt;
テレビ会議してるときは特に運動会とコンサートが始まってかなりうるさい.&lt;br&gt;
そとちゃん賢いのでかまってもらうためにわざとやってるまである(親馬鹿).&lt;/p&gt;
&lt;p&gt;あとは風呂待ちがエスカレートして洗濯物になったり,&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;謎の落ち着きポイント &lt;a href="https://t.co/g9WyAtNlZ4"&gt;pic.twitter.com/g9WyAtNlZ4&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1265293775825440769?ref_src=twsrc%5Etfw"&gt;May 26, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ねこが洗濯物になった &lt;a href="https://t.co/5d1aT4m46r"&gt;pic.twitter.com/5d1aT4m46r&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1266714852573057024?ref_src=twsrc%5Etfw"&gt;May 30, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;ふとんを攻撃したりしてた.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ふとん絶対バリバリにするマン(ねこ) &lt;a href="https://t.co/1Mzv2CWfcT"&gt;pic.twitter.com/1Mzv2CWfcT&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1262960534187651072?ref_src=twsrc%5Etfw"&gt;May 20, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;朝からふとんバリバリ&lt;br&gt;しっぽの躍動感 &lt;a href="https://t.co/5ffteQh617"&gt;pic.twitter.com/5ffteQh617&lt;/a&gt;&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1265799070032859136?ref_src=twsrc%5Etfw"&gt;May 28, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;最近家にいても仕事でなかなか遊んであげられなかったり,&lt;br&gt;
新しいおもちゃも買ってあげられてないので刺激が足りないのかもしれない&amp;hellip;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;そとちゃんは5月も元気だった.&lt;/p&gt;
&lt;p&gt;1年も一緒にいればお互いのことがわかってくると思ったらそんなことはなく,&lt;br&gt;
毎日新しい発見があるので本当にかわいくて面白い.&lt;/p&gt;
&lt;p&gt;ちょっと運動が足りてない感じはするので, 6月はもっと遊ぶ時間を確保してあげて,&lt;br&gt;
あとは暑さ対策も気をつけてあげたい.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="SNSに上げてない中で今月のベストショット(かわいい)" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-31-sotochan/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-05-31-sotochan/sotochan_hu_6e9fa02b3647eab8.jpg 800w, https://blog.uzimihsr.com/post/2020-05-31-sotochan/sotochan_hu_ae0db5bf03949b97.jpg 1600w, https://blog.uzimihsr.com/post/2020-05-31-sotochan/sotochan_hu_35529c8f69b05c0d.jpg 2400w, https://blog.uzimihsr.com/post/2020-05-31-sotochan/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>OpenSSLでデジタル証明書を試す</title><link>https://blog.uzimihsr.com/post/2020-05-30-certification-practice/</link><pubDate>Sat, 30 May 2020 19:58:15 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-05-30-certification-practice/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-05-30-certification-practice/sotochan.jpg" alt="Featured image of post OpenSSLでデジタル証明書を試す" /&gt;&lt;h2 id="身元を証明する"&gt;身元を証明する
&lt;/h2&gt;&lt;p&gt;デジタル署名とデジタル証明書についても実際に触りながらまとめる.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;デジタル署名&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# メッセージ(message)のハッシュ値を秘密鍵(private-key.pem)で暗号化して署名(signature)を作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl dgst -sha256 -sign private-key.pem -out signature message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 署名(signature)を公開鍵(public-key.pem)で復号化してメッセージ(message)のハッシュ値と照合&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl dgst -sha256 -verify public-key.pem -signature signature message
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;デジタル証明書&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 秘密鍵(private-key.pem)から証明書署名要求(req.pem)を作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 証明書署名要求には公開鍵と, 自身の身元を証明する情報が含まれている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl req -new -key private-key.pem -out req.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 証明書署名要求(req.pem)の内容確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl req -in req.pem -text -verify -noout
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 証明書署名要求(req.pem)に認証局の証明書(ca.pem)と秘密鍵(private-key-CA.pem)で署名して証明書を作成(cert.pem)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 証明書には証明書署名要求の公開鍵の内容と認証局の署名が含まれている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl ca -policy policy_anything -in req.pem -out cert.pem -keyfile private-key-CA.pem -cert ca.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 証明書(cert.pem)の内容確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl x509 -in cert.pem -noout -text
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 証明書(cert.pem)を信頼できる認証局の証明書(ca.pem)で検証する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl verify -CAfile ca.pem cert.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 証明書(cert.pem)に含まれる公開鍵の確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl x509 -in cert.pem -pubkey -noout
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Raspberry Pi 3 Model B+
&lt;ul&gt;
&lt;li&gt;OSはRaspbian(10.0)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;openssl
&lt;ul&gt;
&lt;li&gt;OpenSSL 1.1.1c 28 May 2019&lt;/li&gt;
&lt;li&gt;ラズパイの初期装備&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="もくじ"&gt;もくじ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%87%e3%82%b8%e3%82%bf%e3%83%ab%e7%bd%b2%e5%90%8d" &gt;デジタル署名&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%87%e3%82%b8%e3%82%bf%e3%83%ab%e8%a8%bc%e6%98%8e%e6%9b%b8" &gt;デジタル証明書&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="デジタル署名"&gt;デジタル署名
&lt;/h3&gt;&lt;p&gt;デジタル証明書の前に, デジタル署名について確認する.&lt;/p&gt;
&lt;p&gt;デジタル署名とは次のような流れでデータの送信者が秘密鍵を持つ本人であることとそれが途中で改ざんされていないことを証明する仕組み.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;送信側で秘密鍵と公開鍵を作成し, 受信側に公開鍵を渡す&lt;/li&gt;
&lt;li&gt;送信側でメッセージを作成し, それをハッシュ化する&lt;/li&gt;
&lt;li&gt;送信側で得られたハッシュ値を秘密鍵で暗号化(署名)する&lt;/li&gt;
&lt;li&gt;送信側はメッセージ, 署名, 公開鍵を受信側に渡す&lt;/li&gt;
&lt;li&gt;受信側は受け取った署名を公開鍵で復号化し, 受け取ったメッセージをハッシュ化したものと照合する&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;また, これを実現するためデジタル署名には次の特徴がある.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;秘密鍵でしか暗号化できない&lt;/li&gt;
&lt;li&gt;公開鍵で復号化すると元のメッセージに戻る&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;実際にやってみる.&lt;/p&gt;
&lt;p&gt;まずは送信側で秘密鍵と公開鍵を作成し, メッセージを暗号化(署名)する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2つのディレクトリを送信側(dirX), 受信側(dirY)に見立てて作業&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mkdir dirX dirY
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 送信側(dirX)で秘密鍵(private-key.pem)と公開鍵(public-key.pem)を作成して公開鍵を受信側(dirY)に渡す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; dirX
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl genrsa -out private-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl rsa -in private-key.pem -pubout -out public-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cp ./public-key.pem ../dirY
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;次にメッセージを作成し, ハッシュ化する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# メッセージ(message)を作成してSHA-256でハッシュ化(hashed-message)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; qwerty &amp;gt; message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl sha256 -out hashed-message message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat hashed-message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;SHA256&lt;span class="o"&gt;(&lt;/span&gt;message&lt;span class="o"&gt;)=&lt;/span&gt; 9ceece10cf8b97d1f1924dae5d14c137fd144ce999ede85f48be6d7582e2dd23
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ハッシュ値を秘密鍵で暗号化(署名)する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ハッシュ値(hashed_message)を秘密鍵(private-key.pem)で暗号化して署名(signature)を作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl rsautl -sign -in hashed-message -out signature -inkey private-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat signature
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;����������������
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;メッセージ, 署名を受信側に渡す.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# メッセージ(message), 署名(signature)を受信側(dirY)に渡す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cp ./message ../dirY
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cp ./signature ../dirY/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; ../dirY
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;message public-key.pem signature
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;受信側で署名を復号化して, メッセージをハッシュ化したものと照合する.&lt;br&gt;
一致すればメッセージが改ざんされておらず, 送り主が秘密鍵の持ち主であることを証明できる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 署名(signature)を公開鍵(public-key.pem)で復号化(signature-verify)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl rsautl -verify -in signature -out signature-verify -inkey public-key.pem -pubin
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# メッセージ(message)をハッシュ化(hashed-message-verify)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl sha256 -out hashed-message-verify message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 復号化した署名(signature-verify)とメッセージのハッシュ値(hashed-message-verify)を照合&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat signature-verify
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;SHA256&lt;span class="o"&gt;(&lt;/span&gt;message&lt;span class="o"&gt;)=&lt;/span&gt; 9ceece10cf8b97d1f1924dae5d14c137fd144ce999ede85f48be6d7582e2dd23
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat hashed-message-verify
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;SHA256&lt;span class="o"&gt;(&lt;/span&gt;message&lt;span class="o"&gt;)=&lt;/span&gt; 9ceece10cf8b97d1f1924dae5d14c137fd144ce999ede85f48be6d7582e2dd23
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ diff signature-verify hashed-message-verify
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;メッセージのハッシュと署名を復号化した値が一致する組み合わせを作れるのは公開鍵に対応する秘密鍵を持つ者だけなので,&lt;br&gt;
仮にメッセージが改ざんされたり, 同じメッセージが別の秘密鍵で署名された場合は&lt;br&gt;
受信側で照合したときに一致せず, 異常を検知することができる.&lt;/p&gt;
&lt;p&gt;以上の手順を踏むことで, 通信時のなりすましや改ざん, 事後否認を防ぐことができる.&lt;/p&gt;
&lt;p&gt;また, ハッシュ計算と署名を1つのコマンドで実行することもできる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# メッセージ(message)のハッシュ値を秘密鍵(private-key.pem)で暗号化して署名(signature)を作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl dgst -sha256 -sign private-key.pem -out signature message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 署名(signature)を公開鍵(public-key.pem)で復号化してメッセージ(message)のハッシュ値と照合&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl dgst -sha256 -verify public-key.pem -signature signature message
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="デジタル証明書"&gt;デジタル証明書
&lt;/h3&gt;&lt;p&gt;盗聴を防ぐための方法として用いる&lt;a class="link" href="https://uzimihsr.github.io/post/2020-05-20-public-key-practice/" target="_blank" rel="noopener"
 &gt;公開鍵暗号方式&lt;/a&gt;や&lt;a class="link" href="https://uzimihsr.github.io/post/2020-05-24-hybrid-encryption-practice/" target="_blank" rel="noopener"
 &gt;ハイブリッド暗号方式&lt;/a&gt;,&lt;br&gt;
そしてなりすまし, 改ざん, 事後否認を防ぐために用いる&lt;a class="link" href="#%e3%83%87%e3%82%b8%e3%82%bf%e3%83%ab%e7%bd%b2%e5%90%8d" &gt;デジタル署名&lt;/a&gt;だが,&lt;br&gt;
これらはすべて受信側が受け取った公開鍵を信頼できるという条件の上で成り立っている.&lt;/p&gt;
&lt;p&gt;仮に公開鍵を受け取る際にそれが悪意のある第三者によってすり替えられていた場合,&lt;br&gt;
これらの仕組みが全く意味を持たなくなってしまう(公開鍵の信頼性の問題).&lt;/p&gt;
&lt;p&gt;この問題を解決し, 公開鍵の正当性を証明するのがデジタル証明書.&lt;br&gt;
以下の流れで証明書の作成と検証を行う.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;自分の身分を証明したい人(A)が秘密鍵と公開鍵を用意する.&lt;/li&gt;
&lt;li&gt;Aは自分の公開鍵と自分の身元を証明できる情報を用意(証明書署名要求)して認証局(CA)に送る.&lt;/li&gt;
&lt;li&gt;CAはAの証明書署名要求からAの身元を確認した後それらの情報にCA自身の秘密鍵で署名して証明書を作成し, Aに渡す.&lt;/li&gt;
&lt;li&gt;Aは通信したい人(B)に自分の証明書を渡す.&lt;/li&gt;
&lt;li&gt;BはCA自体の証明書(公開鍵)でAの証明書を検証する.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;また, この仕組みを実現するために証明書には次の性質がある.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Aの証明書署名要求はA本人しか作れない&lt;/li&gt;
&lt;li&gt;証明書には身元が証明される人の公開鍵情報とそれに署名した認証局の情報が含まれる&lt;/li&gt;
&lt;li&gt;信頼している認証局が署名した証明書であれば信頼性が保証される&lt;/li&gt;
&lt;li&gt;認証局自身の信頼性はさらに上位の認証局が発行する証明書で保証する&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;実際にやってみて確認する.&lt;br&gt;
まずはAとCAの秘密鍵, 公開鍵を用意する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 3つのディレクトリを通信者(dirA, dirB), 認証局(dirCA)に見立てて作業する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mkdir dirA dirB dirCA
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# CAとAはそれぞれ秘密鍵を持っている状態&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; dirCA
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl genrsa -out private-key-CA.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl rsa -in private-key-CA.pem -pubout -out public-key-CA.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; ../dirA
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl genrsa -out private-key-A.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl rsa -in private-key-A.pem -pubout -out public-key-A.pem
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;次にAは自分の公開鍵と身元を証明する情報を合わせたデータ(証明書署名要求)を作成し,&lt;br&gt;
CAに渡す.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Aの秘密鍵(private-key-A.pem)から証明書署名要求(req.pem)を作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 実際は秘密鍵から公開鍵を取り出して使っている(秘密鍵そのものを渡すわけではない)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl req -new -key private-key-A.pem -out req.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;You are about to be asked to enter information that will be incorporated
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;into your certificate request.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;What you are about to enter is what is called a Distinguished Name or a DN.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;There are quite a few fields but you can leave some blank
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;For some fields there will be a default value,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;If you enter &lt;span class="s1"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;, the field will be left blank.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;----- &lt;span class="c1"&gt;# 以下, 身元を証明するための情報を入力する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Country Name &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; letter code&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;AU&lt;span class="o"&gt;]&lt;/span&gt;:JP &lt;span class="c1"&gt;#国&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;State or Province Name &lt;span class="o"&gt;(&lt;/span&gt;full name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Some-State&lt;span class="o"&gt;]&lt;/span&gt;:Tokyo &lt;span class="c1"&gt;# 都道府県&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Locality Name &lt;span class="o"&gt;(&lt;/span&gt;eg, city&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;: &lt;span class="c1"&gt;# 市区町村&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Organization Name &lt;span class="o"&gt;(&lt;/span&gt;eg, company&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Internet Widgits Pty Ltd&lt;span class="o"&gt;]&lt;/span&gt;: &lt;span class="c1"&gt;# 組織名&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Organizational Unit Name &lt;span class="o"&gt;(&lt;/span&gt;eg, section&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;: &lt;span class="c1"&gt;# 部署名&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Common Name &lt;span class="o"&gt;(&lt;/span&gt;e.g. server FQDN or YOUR name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:uzimihsr.example.com &lt;span class="c1"&gt;# 名前&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Email Address &lt;span class="o"&gt;[]&lt;/span&gt;:example@mail.com &lt;span class="c1"&gt;# メールアドレス&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Please enter the following &lt;span class="s1"&gt;&amp;#39;extra&amp;#39;&lt;/span&gt; attributes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;to be sent with your certificate request
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;A challenge password &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;An optional company name &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat req.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-----BEGIN CERTIFICATE REQUEST-----
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;MIICxjCCAa4CAQAwgYAxCzAJBgNVBAYTAkpQMQ4wDAYDVQQIDAVUb2t5bzEhMB8G
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cH32EBVTnecz4nSPVYHwr9xcgKi+i0ol4ea0lMNWz5m0O0dYOc6H0Qqc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-----END CERTIFICATE REQUEST-----
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 証明書署名要求(req.pem)をCAに渡す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cp req.pem ../dirCA/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;CAは受け取ったAの証明書署名要求の内容を確認する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 証明書署名要求(req.pem)の内容を検証する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; ../dirCA
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl req -in req.pem -text -verify -noout
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;verify OK
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Certificate Request:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Data: &lt;span class="c1"&gt;# Aの公開鍵と身元の情報&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Version: &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;0x0&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Subject: &lt;span class="nv"&gt;C&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; JP, &lt;span class="nv"&gt;ST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; Tokyo, &lt;span class="nv"&gt;O&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; Internet Widgits Pty Ltd, &lt;span class="nv"&gt;CN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; uzimihsr.example.com, &lt;span class="nv"&gt;emailAddress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; example@mail.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Subject Public Key Info:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Public Key Algorithm: rsaEncryption
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; RSA Public-Key: &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2048&lt;/span&gt; bit&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Modulus:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 00:b7:51:7c:41:9c:c9:f2:4d:c0:a8:43:bb:96:2a:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 0c:d7
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Exponent: &lt;span class="m"&gt;65537&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;0x10001&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Attributes:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; a0:00
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Signature Algorithm: sha256WithRSAEncryption
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 26:88:97:d7:c4:57:da:24:1b:d5:b4:e2:e8:82:23:b5:1c:e0:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 87:d1:0a:9c
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;証明書署名要求の内容に問題がなければ署名してAの証明書を作る&amp;hellip;前に認証局もそれ自身の身元を証明する必要があるので,&lt;br&gt;
自己証明証明書(オレオレ証明書)を作ってCAを認証局として動かすための設定をする.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# CA自身の身元を証明し鍵(private-key-CA.pem)の正当性を保証するためのオレオレ証明書(ca.pem)を作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# こちらも内部で秘密鍵から公開鍵を取り出して使用している(証明書に秘密鍵を埋め込むわけではない)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl req -x509 -key private-key-CA.pem -out ca.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;You are about to be asked to enter information that will be incorporated
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;into your certificate request.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;What you are about to enter is what is called a Distinguished Name or a DN.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;There are quite a few fields but you can leave some blank
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;For some fields there will be a default value,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;If you enter &lt;span class="s1"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;, the field will be left blank.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;----- &lt;span class="c1"&gt;# その場しのぎの証明書なので何も入れなくてもOK&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Country Name &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; letter code&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;AU&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;State or Province Name &lt;span class="o"&gt;(&lt;/span&gt;full name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Some-State&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Locality Name &lt;span class="o"&gt;(&lt;/span&gt;eg, city&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Organization Name &lt;span class="o"&gt;(&lt;/span&gt;eg, company&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Internet Widgits Pty Ltd&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Organizational Unit Name &lt;span class="o"&gt;(&lt;/span&gt;eg, section&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Common Name &lt;span class="o"&gt;(&lt;/span&gt;e.g. server FQDN or YOUR name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Email Address &lt;span class="o"&gt;[]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 証明書に署名するために必要な設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mkdir -p demoCA/newcerts
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ touch demoCA/index.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="m"&gt;01&lt;/span&gt; &amp;gt; demoCA/serial
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;CAはAの証明書署名要求に署名してAの証明書を作成し, Aに渡す.&lt;br&gt;
これによりAの身元と公開鍵の正当性をCAが保証することになる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Aの証明書署名要求(req.pem)にCA自身の秘密鍵(private-key-CA.pem)と証明書(ca.pem)を使って署名する(cert-A.pem)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl ca -policy policy_anything -in req.pem -out cert-A.pem -keyfile private-key-CA.pem -cert ca.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Using configuration from /usr/lib/ssl/openssl.cnf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Check that the request matches the signature
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Signature ok
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Certificate Details:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Serial Number: &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;0x1&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Validity
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Not Before: May &lt;span class="m"&gt;30&lt;/span&gt; 09:15:17 &lt;span class="m"&gt;2020&lt;/span&gt; GMT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Not After : May &lt;span class="m"&gt;30&lt;/span&gt; 09:15:17 &lt;span class="m"&gt;2021&lt;/span&gt; GMT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Subject:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;countryName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; JP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;stateOrProvinceName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; Tokyo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;organizationName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; Internet Widgits Pty Ltd
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;commonName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; uzimihsr.example.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;emailAddress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; example@mail.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; X509v3 extensions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; X509v3 Basic Constraints:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; CA:FALSE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Netscape Comment:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; OpenSSL Generated Certificate
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; X509v3 Subject Key Identifier:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; F2:CC:D3:94:F9:57:AE:F3:4E:A9:12:1F:15:29:87:8C:58:4B:6C:56
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; X509v3 Authority Key Identifier:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; keyid:57:A6:BC:47:C9:76:6C:E3:93:48:D7:09:9E:03:8A:86:3F:A5:08:80
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Sign the certificate? &lt;span class="o"&gt;[&lt;/span&gt;y/n&lt;span class="o"&gt;]&lt;/span&gt;:y
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;1&lt;/span&gt; out of &lt;span class="m"&gt;1&lt;/span&gt; certificate requests certified, commit? &lt;span class="o"&gt;[&lt;/span&gt;y/n&lt;span class="o"&gt;]&lt;/span&gt;y
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Write out database with &lt;span class="m"&gt;1&lt;/span&gt; new entries
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Data Base Updated
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 証明書をAに渡す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cp cert-A.pem ../dirA/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Aは通信を行いたい相手(B)に自分の証明書を渡す.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Bに証明書を渡す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; ../dirA
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cp cert-A.pem ../dirB
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;BはAの証明書の内容を確認する.&lt;br&gt;
BはCAを信頼しているので,&lt;br&gt;
Aの証明書にCAが署名していることを確認できればこれを信頼し, 証明書から取り出したAの公開鍵を安心して利用することができる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Aの証明書(cert-A.pem)の内容を確認する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; ../dirB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl x509 -in cert-A.pem -noout -text
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Certificate:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Data:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Version: &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;0x2&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Serial Number: &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;0x1&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Signature Algorithm: sha256WithRSAEncryption
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Issuer: &lt;span class="nv"&gt;C&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; AU, &lt;span class="nv"&gt;ST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; Some-State, &lt;span class="nv"&gt;O&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; Internet Widgits Pty Ltd &lt;span class="c1"&gt;# 認証局(CA)の情報&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Validity
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Not Before: May &lt;span class="m"&gt;30&lt;/span&gt; 09:15:17 &lt;span class="m"&gt;2020&lt;/span&gt; GMT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Not After : May &lt;span class="m"&gt;30&lt;/span&gt; 09:15:17 &lt;span class="m"&gt;2021&lt;/span&gt; GMT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Subject: &lt;span class="nv"&gt;C&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; JP, &lt;span class="nv"&gt;ST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; Tokyo, &lt;span class="nv"&gt;O&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; Internet Widgits Pty Ltd, &lt;span class="nv"&gt;CN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; uzimihsr.example.com, &lt;span class="nv"&gt;emailAddress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; example@mail.com &lt;span class="c1"&gt;# Aの身元情報&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Subject Public Key Info:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Public Key Algorithm: rsaEncryption
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; RSA Public-Key: &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2048&lt;/span&gt; bit&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Modulus: &lt;span class="c1"&gt;# Aの公開鍵情報&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 00:b7:51:7c:41:9c:c9:f2:4d:c0:a8:43:bb:96:2a:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 0c:d7
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Exponent: &lt;span class="m"&gt;65537&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;0x10001&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; X509v3 extensions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; X509v3 Basic Constraints:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; CA:FALSE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Netscape Comment:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; OpenSSL Generated Certificate
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; X509v3 Subject Key Identifier:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; F2:CC:D3:94:F9:57:AE:F3:4E:A9:12:1F:15:29:87:8C:58:4B:6C:56
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; X509v3 Authority Key Identifier:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; keyid:57:A6:BC:47:C9:76:6C:E3:93:48:D7:09:9E:03:8A:86:3F:A5:08:80
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Signature Algorithm: sha256WithRSAEncryption
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 39:a3:7f:a3:dd:9c:ff:21:b7:b3:1b:44:07:c1:38:e0:ae:7a:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; bc:d0:36:70
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 信頼している認証局(CA)の証明書(ca.pem)を使ってAの証明書(cert-A.pem)が正しいか検証する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl verify -CAfile ../dirCA/ca.pem cert-A.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cert-A.pem: OK
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 検証が成功したので証明書からAの公開鍵を取り出す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl x509 -in cert-A.pem -pubkey -noout
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-----BEGIN PUBLIC KEY-----
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt1F8QZzJ8k3AqEO7liqz
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1wIDAQAB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-----END PUBLIC KEY-----
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 以降はAの公開鍵を信頼して通信する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Bが信頼できる証明書はBが信頼している認証局とA本人によってのみ作成できるので,&lt;br&gt;
悪意のある第三者がAになりすましてBに自身の公開鍵を渡すことはできない.&lt;br&gt;
したがって, 証明書を使うことで公開鍵の正当性を保証することができる.&lt;/p&gt;
&lt;p&gt;以上の手順で公開鍵の信頼性を保証することができた.&lt;br&gt;
やることが多くて混乱するけど,&lt;br&gt;
要は信頼できる認証局が相手の身元を保証していれば自分も相手を信頼する, という仕組み.&lt;/p&gt;
&lt;p&gt;今回は認証局(CA)の身元を自身で保証したけど(オレオレ証明書),&lt;br&gt;
実際は上位の認証局がその正当性を保証する.&lt;br&gt;
その上位の認証局の正当性はさらに上位の認証局が保証し&amp;hellip; というように,&lt;br&gt;
認証局の保証は木構造になっている.&lt;br&gt;
最上位の認証局の正当性は自身の証明書では保証できないので,&lt;br&gt;
公的に信頼できる政府関連の機関などが最上位の認証局を努めている.&lt;br&gt;
以上が公開鍵基盤(PKI)の仕組み.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2020-05-20-public-key-practice/" target="_blank" rel="noopener"
 &gt;公開鍵暗号方式&lt;/a&gt;, &lt;a class="link" href="https://uzimihsr.github.io/post/2020-05-24-hybrid-encryption-practice/" target="_blank" rel="noopener"
 &gt;ハイブリッド暗号方式&lt;/a&gt;に続いてデジタル証明書を実際に試してみた.&lt;br&gt;
証明書署名要求から証明書の作成までの手順も確認できたので,&lt;br&gt;
機会があればオレオレ証明書でSSL通信したり, クライアント認証とかを試してみたい.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="ちょっと怒ってるねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-30-certification-practice/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-05-30-certification-practice/sotochan_hu_24e002c1b5757515.jpg 800w, https://blog.uzimihsr.com/post/2020-05-30-certification-practice/sotochan_hu_c64262065c06eca1.jpg 1600w, https://blog.uzimihsr.com/post/2020-05-30-certification-practice/sotochan_hu_2b43d4df1dd8c54.jpg 2400w, https://blog.uzimihsr.com/post/2020-05-30-certification-practice/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;h2 id="参考"&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%87%e3%82%b8%e3%82%bf%e3%83%ab%e7%bd%b2%e5%90%8d" &gt;デジタル署名&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.openssl.org/docs/man1.1.0/man1/dgst.html" target="_blank" rel="noopener"
 &gt;https://www.openssl.org/docs/man1.1.0/man1/dgst.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.openssl.org/docs/man1.1.0/man1/rsautl.html" target="_blank" rel="noopener"
 &gt;https://www.openssl.org/docs/man1.1.0/man1/rsautl.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%87%e3%82%b8%e3%82%bf%e3%83%ab%e8%a8%bc%e6%98%8e%e6%9b%b8" &gt;デジタル証明書&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.openssl.org/docs/man1.1.0/man1/req.html" target="_blank" rel="noopener"
 &gt;https://www.openssl.org/docs/man1.1.0/man1/req.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.openssl.org/docs/man1.1.0/man1/ca.html" target="_blank" rel="noopener"
 &gt;https://www.openssl.org/docs/man1.1.0/man1/ca.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.openssl.org/docs/man1.1.0/man1/x509.html" target="_blank" rel="noopener"
 &gt;https://www.openssl.org/docs/man1.1.0/man1/x509.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.openssl.org/docs/man1.1.0/man1/verify.html" target="_blank" rel="noopener"
 &gt;https://www.openssl.org/docs/man1.1.0/man1/verify.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>OpenSSLで共通鍵暗号方式とハイブリッド暗号方式を試す</title><link>https://blog.uzimihsr.com/post/2020-05-24-hybrid-encryption-practice/</link><pubDate>Sun, 24 May 2020 17:09:44 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-05-24-hybrid-encryption-practice/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-05-24-hybrid-encryption-practice/sotochan.jpg" alt="Featured image of post OpenSSLで共通鍵暗号方式とハイブリッド暗号方式を試す" /&gt;&lt;h2 id="欠点を補いあう"&gt;欠点を補いあう
&lt;/h2&gt;&lt;p&gt;共通鍵暗号方式とハイブリッド暗号方式についても実際に触りながらまとめる.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;共通鍵でのデータの暗号化と復号化&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 32bytesの乱数パスワードファイル(password)の作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl rand -base64 -out password &lt;span class="m"&gt;32&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 平文データ(data)を公開鍵(password)を使ってaes256で暗号化(encrypted-data)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl enc -aes256 -in data -out encrypted-data -pass file:password -base64
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 暗号データ(encrypted-data)を公開鍵(password)を使ってaes256で復号化(decrypted-data)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl enc -d -aes256 -in encrypted-data -out decrypted-data -pass file:password -base64
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;ハイブリッド暗号方式&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 秘密鍵(private-key.pem)と公開鍵(public-key.pem)の作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 作成した公開鍵はもう片方に渡す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl genrsa -out private-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl rsa -in private-key.pem -pubout -out public-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 共通鍵(password)の作成 (秘密鍵を持たない方が実行)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl rand -base64 -out password &lt;span class="m"&gt;32&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 公開鍵(public-key.pem)を使って共通鍵(password)を暗号化(encrypted-password) (秘密鍵を持たない方が実行)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 暗号化した共通鍵をもう片方に渡す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl rsautl -encrypt -in password -out encrypted-password -inkey public-key.pem -pubin
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 秘密鍵(private-key.pem)を使って暗号化された共通鍵(encrypted-password)を復号化(decrypted-password) (秘密鍵を持つ方が実行)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl rsautl -decrypt -in encrypted-password -out decrypted-password -inkey private-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 以降は共通鍵で暗号化したデータをやりとりする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Raspberry Pi 3 Model B+
&lt;ul&gt;
&lt;li&gt;OSはRaspbian(10.0)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;openssl
&lt;ul&gt;
&lt;li&gt;OpenSSL 1.1.1c 28 May 2019&lt;/li&gt;
&lt;li&gt;ラズパイの初期装備&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="もくじ"&gt;もくじ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e5%85%b1%e9%80%9a%e9%8d%b5%e6%9a%97%e5%8f%b7%e6%96%b9%e5%bc%8f" &gt;共通鍵暗号方式&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e5%85%ac%e9%96%8b%e9%8d%b5%e6%9a%97%e5%8f%b7%e6%96%b9%e5%bc%8f%e3%81%a8%e5%85%b1%e9%80%9a%e9%8d%b5%e6%9a%97%e5%8f%b7%e6%96%b9%e5%bc%8f%e3%81%ae%e6%af%94%e8%bc%83" &gt;公開鍵暗号方式と共通鍵暗号方式の比較&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%8f%e3%82%a4%e3%83%96%e3%83%aa%e3%83%83%e3%83%89%e6%9a%97%e5%8f%b7%e6%96%b9%e5%bc%8f" &gt;ハイブリッド暗号方式&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="共通鍵暗号方式"&gt;共通鍵暗号方式
&lt;/h3&gt;&lt;p&gt;共通鍵暗号方式と言っても,&lt;br&gt;
(誤解を恐れずに言えば)パスワードでデータを暗号化/復号化する方式のこと.&lt;/p&gt;
&lt;p&gt;共通鍵暗号方式の通信の簡単な流れとしては&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;送信側と受信側で事前に同じ共通鍵(パスワード)を持っておく&lt;/li&gt;
&lt;li&gt;送信側は平文データを共通鍵で暗号化する&lt;/li&gt;
&lt;li&gt;送信側は受信側に暗号データを渡す&lt;/li&gt;
&lt;li&gt;受信側は暗号データを共通鍵で復号化する&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;たったこれだけ.&lt;br&gt;
暗号化/復号化に同じ鍵を使うことが大きな特徴.&lt;/p&gt;
&lt;p&gt;実際にやってみる.&lt;/p&gt;
&lt;p&gt;まずはじめに共通鍵(パスワード)を作成して送信側と受信側で共有する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ディレクトリを送信側(dirA)と受信側(dirB)に見立てて作業&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mkdir dirA dirB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; dirA
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 共通鍵(password)を作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 本当はこんな適当な値ではなく乱数が望ましい&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="m"&gt;1234567&lt;/span&gt; &amp;gt; password
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat password
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;1234567&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 共通鍵(password)を受信側(dirB)に共有&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cp password ../dirB/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;password
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls ../dirB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;password
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;次に平文データを共通鍵で暗号化する.&lt;br&gt;
これにより, 共通鍵がわからない場合はデータの内容を読むことができなくなる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 送信側(dirA)で作業&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;pwd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/path/to/dirA
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 平文データ(data.txt)を作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; abcdefg &amp;gt; data.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 暗号化アルゴリズム(aes256)を使って平文データ(data.txt)を暗号化(encrypted-data.txt)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# アルゴリズムが非推奨のものなので警告が出ているがとりあえずはOK&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl enc -aes256 -in data.txt -out encrypted-data.txt -pass file:password
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;*** WARNING : deprecated key derivation used.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Using -iter or -pbkdf2 would be better.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;data.txt encrypted-data.txt password
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 暗号化されているので読めない&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat encrypted-data.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Salted__aGo�r�ʵ�3�Z��ċ�D
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;暗号データを受信側に渡し,&lt;br&gt;
受信側で共通鍵を使って復号化する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 暗号データ(encrypted-data.txt)を受信側(dirB)に渡す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;pwd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/path/to/dirA
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cp encrypted-data.txt ../dirB/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 受信側(dirB)で作業&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; ../dirB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;encrypted-data.txt password
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 暗号データ(encrypted-data.txt)を共通鍵(password)で復号化(decrypted-data.txt)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl enc -d -aes256 -in encrypted-data.txt -out decrypted-data.txt -pass file:password
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;*** WARNING : deprecated key derivation used.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Using -iter or -pbkdf2 would be better.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat decrypted-data.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;abcdefg
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;こんな感じでデータの暗号化と復号化ができる.&lt;/p&gt;
&lt;p&gt;重要なのは, 送信側と受信側の間で暗号データの他に共通鍵の受け渡しをしていること.&lt;br&gt;
共通鍵暗号方式では同じ鍵で暗号化と復号化が行われるため,&lt;br&gt;
通信が傍受され共通鍵が流出した場合は簡単に平文データが取り出されてしまう.&lt;br&gt;
(いわゆる鍵配送問題)&lt;/p&gt;
&lt;h3 id="公開鍵暗号方式と共通鍵暗号方式の比較"&gt;公開鍵暗号方式と共通鍵暗号方式の比較
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2020-05-20-public-key-practice/" target="_blank" rel="noopener"
 &gt;公開鍵暗号方式&lt;/a&gt;と共通鍵暗号方式の大きな違いとしては&lt;br&gt;
公開鍵暗号方式が暗号化/復号化を &lt;strong&gt;別々の鍵&lt;/strong&gt; で行うのに対し,&lt;br&gt;
共通鍵暗号方式では暗号化/復号化を &lt;strong&gt;同じ鍵&lt;/strong&gt; で行うこと.&lt;/p&gt;
&lt;p&gt;これらの特徴を比較すると次のようになる.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;共通鍵暗号方式
&lt;ul&gt;
&lt;li&gt;公開鍵暗号方式よりも暗号化/復号化が高速
&lt;ul&gt;
&lt;li&gt;アルゴリズムが簡単なため&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;通信を傍受されると無力&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;公開鍵暗号方式
&lt;ul&gt;
&lt;li&gt;暗号化/復号化が遅い&lt;/li&gt;
&lt;li&gt;通信を傍受されても問題ない&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これらの特徴をうまく組み合わせて高速で安全な通信を行うのがハイブリッド暗号方式.&lt;/p&gt;
&lt;h3 id="ハイブリッド暗号方式"&gt;ハイブリッド暗号方式
&lt;/h3&gt;&lt;p&gt;ハイブリッド暗号方式の大きな特徴は,&lt;br&gt;
&lt;strong&gt;共通鍵そのものを公開鍵暗号方式で渡すこと&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;主な流れはこんな感じ.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;送信側で共通鍵を作成&lt;/li&gt;
&lt;li&gt;受信側で秘密鍵と公開鍵を作成, 送信側に公開鍵を渡す&lt;/li&gt;
&lt;li&gt;送信側は受け取った公開鍵で共通鍵を暗号化して受信側に渡す&lt;/li&gt;
&lt;li&gt;受信側は暗号化された共通鍵を秘密鍵で復号化&lt;/li&gt;
&lt;li&gt;以降は2者間で共通鍵で暗号化したデータをやり取りする&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;最初の1回だけ公開鍵暗号方式で共通鍵を渡した後は高速な共通鍵暗号方式を使うことができるので,&lt;br&gt;
高速で安全にデータをやり取りするためのSSL/TLS通信では公開鍵暗号方式単体ではなくこちらが使用されている.&lt;/p&gt;
&lt;p&gt;実際にやってみる.&lt;/p&gt;
&lt;p&gt;まずは送信側で共通鍵を作成する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ディレクトリを送信側(dir1)と受信側(dir2)に見立てて作業&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mkdir dir1 dir2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 送信側(dir1)で共通鍵(password)を作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 今回はちゃんと32bytesの乱数で作成する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; dir1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl rand -base64 -out password &lt;span class="m"&gt;32&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat password
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;VAJhXVUt7aRxfFs5ba7SNkjWyIqOaI8E10t0tnmF7as&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;次に受信側で秘密鍵と公開鍵を作成して公開鍵を送信側に渡す.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 受信側(dir2)で秘密鍵(private-key.pem)と公開鍵(public-key.pem)を作成, 送信側(dir1)に公開鍵を渡す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; ../dir2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl genrsa -out private-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl rsa -in private-key.pem -pubout -out public-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cp ./public-key.pem ../dir1/ &lt;span class="c1"&gt;# 公開鍵を渡す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;送信側は受け取った公開鍵で共通鍵を暗号化して受信側に渡す.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 送信側(dir1)は受け取った公開鍵(public-key.pem)で共通鍵(password)を暗号化(encrypted-password)して受信側に渡す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; ../dir1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl rsautl -encrypt -in password -out encrypted-password -inkey public-key.pem -pubin
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat encrypted-password
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;��ʞ��...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cp ./encrypted-password ../dir2/ &lt;span class="c1"&gt;# 暗号化された共通鍵を渡す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;最後に受信側は暗号化された共通鍵を秘密鍵で復号化する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 受信側(dir2)は暗号化された共通鍵(encrypted-password)を秘密鍵(private-key.pem)で復号化(decrypted-password)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; ../dir2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl rsautl -decrypt -in encrypted-password -out decrypted-password -inkey private-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat decrypted-password
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;VAJhXVUt7aRxfFs5ba7SNkjWyIqOaI8E10t0tnmF7as&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以上の手順で送信側, 受信側双方に共通鍵が存在する状態になったので,&lt;br&gt;
以降は2者間で共通鍵暗号方式で通信する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 以降は2者間で共通鍵で暗号化したデータをやり取りする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; hello &amp;gt; file1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl enc -aes256 -in file1 -out encrypted-file1 -pass file:decrypted-password -base64
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cp ./encrypted-file1 ../dir1/ &lt;span class="c1"&gt;# 暗号データを渡す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; ../dir1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl enc -d -aes256 -in encrypted-file1 -out decrypted-file1 -pass file:password -base64
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat decrypted-file1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hello
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; world &amp;gt; file2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl enc -aes256 -in file2 -out encrypted-file2 -pass file:password -base64
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cp ./encrypted-file2 ../dir2/ &lt;span class="c1"&gt;# 暗号データを渡す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; ../dir2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl enc -d -aes256 -in encrypted-file2 -out decrypted-file2 -pass file:decrypted-password -base64
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat decrypted-file2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;world
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;重要なのは暗号データの他に2者間でやり取りされるデータが &lt;strong&gt;公開鍵, 公開鍵で暗号化された共通鍵のみ&lt;/strong&gt; であること.&lt;br&gt;
&lt;a class="link" href="https://uzimihsr.github.io/post/2020-05-20-public-key-practice/" target="_blank" rel="noopener"
 &gt;公開鍵暗号方式&lt;/a&gt;の性質として公開鍵では暗号化された共通鍵の復号化ができず,&lt;br&gt;
暗号化された状態の共通鍵では暗号データを復号化できないため,&lt;br&gt;
仮に悪意のある第三者がこれらの通信を傍受してもやりとりされる平文データの内容を読むことはできない(秘密が守られる).&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2020-05-20-public-key-practice/" target="_blank" rel="noopener"
 &gt;公開鍵暗号方式&lt;/a&gt;に続いて共通鍵暗号方式とハイブリッド暗号方式を実際に試してみた.&lt;br&gt;
これでも十分そうに見えるけど, まだ公開鍵の信頼性にまつわる問題があるので次はデジタル証明書について触ってみたい.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="あくびねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-24-hybrid-encryption-practice/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-05-24-hybrid-encryption-practice/sotochan_hu_f8a3a58f60e78ee4.jpg 800w, https://blog.uzimihsr.com/post/2020-05-24-hybrid-encryption-practice/sotochan_hu_cd3fc595b0a54137.jpg 1600w, https://blog.uzimihsr.com/post/2020-05-24-hybrid-encryption-practice/sotochan_hu_f6c2b354a7de5b58.jpg 2400w, https://blog.uzimihsr.com/post/2020-05-24-hybrid-encryption-practice/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;h2 id="参考"&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e5%85%b1%e9%80%9a%e9%8d%b5%e6%9a%97%e5%8f%b7%e6%96%b9%e5%bc%8f" &gt;共通鍵暗号方式&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.openssl.org/docs/man1.1.0/man1/enc.html" target="_blank" rel="noopener"
 &gt;https://www.openssl.org/docs/man1.1.0/man1/enc.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.openssl.org/docs/man1.1.0/man1/openssl.html" target="_blank" rel="noopener"
 &gt;https://www.openssl.org/docs/man1.1.0/man1/openssl.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e5%85%ac%e9%96%8b%e9%8d%b5%e6%9a%97%e5%8f%b7%e6%96%b9%e5%bc%8f%e3%81%a8%e5%85%b1%e9%80%9a%e9%8d%b5%e6%9a%97%e5%8f%b7%e6%96%b9%e5%bc%8f%e3%81%ae%e6%af%94%e8%bc%83" &gt;公開鍵暗号方式と共通鍵暗号方式の比較&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.shoeisha.co.jp/book/detail/9784798149776" target="_blank" rel="noopener"
 &gt;アルゴリズム図鑑 絵で見てわかる26のアルゴリズム&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;ほんとにわかりやすい&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%8f%e3%82%a4%e3%83%96%e3%83%aa%e3%83%83%e3%83%89%e6%9a%97%e5%8f%b7%e6%96%b9%e5%bc%8f" &gt;ハイブリッド暗号方式&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.openssl.org/docs/man1.1.0/man1/rand.html" target="_blank" rel="noopener"
 &gt;https://www.openssl.org/docs/man1.1.0/man1/rand.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>OpenSSLで秘密鍵と公開鍵を作る</title><link>https://blog.uzimihsr.com/post/2020-05-20-public-key-practice/</link><pubDate>Wed, 20 May 2020 20:18:54 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-05-20-public-key-practice/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-05-20-public-key-practice/sotochan.jpg" alt="Featured image of post OpenSSLで秘密鍵と公開鍵を作る" /&gt;&lt;h2 id="暗号わかんね"&gt;暗号わかんね
&lt;/h2&gt;&lt;p&gt;公開鍵暗号方式についてよくわかってないままだったので実際に触りながら自分なりにまとめる.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;秘密鍵と公開鍵の作成&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 秘密鍵(private-key.pem)を作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;## パスフレーズなし&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl genrsa -out private-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;## パスフレーズあり(aes256で暗号化)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl genrsa -out private-key.pem -aes256
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 秘密鍵(private-key.pem)から公開鍵(public-key.pem)を作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl rsa -in private-key.pem -pubout -out public-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;データの暗号化と復号化&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 公開鍵(public-key.pem)を使ってデータ(data.txt)を暗号化(encrypted-data.txt)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl rsautl -encrypt -in data.txt -out encrypted-data.txt -inkey public-key.pem -pubin
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 秘密鍵(private-key.pem)を使って暗号データ(encrypted-data.txt)を復号化(decrypted-data.txt)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl rsautl -decrypt -in encrypted-data.txt -out decrypted-data.txt -inkey private-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;秘密鍵のパスフレーズ&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 秘密鍵(private-key.pem)にパスフレーズをつける(private-key-with-pass-phrase.pem)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl rsa -in private-key.pem -out private-key-with-pass-phrase.pem -aes256
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 秘密鍵(private-key-with-pass-phrase.pem)のパスフレーズを外す(private-key-without-pass-phrase.pem)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl rsa -in private-key-with-pass-phrase.pem -out private-key-without-pass-phrase.pem
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Raspberry Pi 3 Model B+
&lt;ul&gt;
&lt;li&gt;OSはRaspbian(10.0)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;openssl
&lt;ul&gt;
&lt;li&gt;OpenSSL 1.1.1c 28 May 2019&lt;/li&gt;
&lt;li&gt;ラズパイの初期装備&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="もくじ"&gt;もくじ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e7%a7%98%e5%af%86%e9%8d%b5%e3%81%a8%e5%85%ac%e9%96%8b%e9%8d%b5%e3%81%ae%e6%80%a7%e8%b3%aa" &gt;秘密鍵と公開鍵の性質&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e7%a7%98%e5%af%86%e9%8d%b5%e3%81%a8%e5%85%ac%e9%96%8b%e9%8d%b5%e3%82%92%e4%bd%9c%e3%82%8b" &gt;秘密鍵と公開鍵を作る&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e5%85%ac%e9%96%8b%e9%8d%b5%e3%81%a7%e6%9a%97%e5%8f%b7%e5%8c%96%e3%81%99%e3%82%8b" &gt;公開鍵で暗号化する&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e7%a7%98%e5%af%86%e9%8d%b5%e3%81%a7%e5%be%a9%e5%8f%b7%e5%8c%96%e3%81%99%e3%82%8b" &gt;秘密鍵で復号化する&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%91%e3%82%b9%e3%83%95%e3%83%ac%e3%83%bc%e3%82%ba%e3%82%92%e3%81%a4%e3%81%91%e3%82%8b" &gt;パスフレーズをつける&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="秘密鍵と公開鍵の性質"&gt;秘密鍵と公開鍵の性質
&lt;/h3&gt;&lt;p&gt;まず秘密鍵と公開鍵の性質について.&lt;br&gt;
数学が苦手なので詳細なアルゴリズムとか数式とかは抜きにして次の性質がある前提で進める.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;秘密鍵と公開鍵は鍵生成アルゴリズムによって作成される数値&lt;/li&gt;
&lt;li&gt;公開鍵から秘密鍵を逆算することはできない&lt;/li&gt;
&lt;li&gt;公開鍵を用いてデータを暗号化する&lt;/li&gt;
&lt;li&gt;暗号化されたデータは秘密鍵によってのみ復号化できる&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;とはいえ, 言葉だとよくわかんないので実際に作ってみるのが手っ取り早い.&lt;/p&gt;
&lt;h3 id="秘密鍵と公開鍵を作る"&gt;秘密鍵と公開鍵を作る
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;openssl&lt;/code&gt;を使ってまずは秘密鍵と公開鍵を作ってみる.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;秘密鍵と公開鍵は鍵生成アルゴリズムによって作成される&lt;/strong&gt; のだが,&lt;br&gt;
今回は鍵生成アルゴリズムとして&lt;code&gt;RSA&lt;/code&gt;を使う.&lt;br&gt;
アルゴリズムの詳細は省くけど, 素数が関係しているくらいは覚えておいてもいいはず.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;RSA&lt;/code&gt;の秘密鍵の作成自体はかんたんで, コマンド1行でできる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 適当なディレクトリを作って作業&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mkdir dirA
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; dirA
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# パスフレーズなしの秘密鍵(private-key.pem)を作成する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl genrsa -out private-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Generating RSA private key, &lt;span class="m"&gt;2048&lt;/span&gt; bit long modulus &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; primes&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.........................................+++++
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...............................+++++
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;e is &lt;span class="m"&gt;65537&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;0x010001&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 秘密鍵が生成される&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;private-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# そのまま表示しても読めない&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat private-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-----BEGIN RSA PRIVATE KEY-----
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;MIIEowIBAAKCAQEA58HW0I+9qZiHopidx7pUuxNzVuobgzgp7OswlvgSHn2/BbKL
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;fSy2dXrjU08OXro9YHz0d6XESG3feSinK0ND0sbsrKTD+4j7fetk
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-----END RSA PRIVATE KEY-----
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;次に秘密鍵の内容を確認してみる.&lt;/p&gt;
&lt;p&gt;秘密鍵には公開鍵の情報と鍵を作成したときの情報とかが入ってる.&lt;br&gt;
(例: &lt;code&gt;modulus&lt;/code&gt;が公開鍵の情報で, &lt;code&gt;prime1&lt;/code&gt;とか&lt;code&gt;prime2&lt;/code&gt;とあるのが鍵生成時に使用した素数の情報)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 秘密鍵(private-key.pem)の中身を確認する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl rsa -in private-key.pem -text -noout
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;RSA Private-Key: &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2048&lt;/span&gt; bit, &lt;span class="m"&gt;2&lt;/span&gt; primes&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;modulus:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 00:e7:c1:d6:d0:8f:bd:a9:98:87:a2:98:9d:c7:ba:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 54:bb:13:73:56:ea:1b:83:38:29:ec:eb:30:96:f8:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 12:1e:7d:bf:05:b2:8b:c5:ff:33:fb:b1:7d:be:a6:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 7b:ec:62:5c:b2:d3:dd:b7:34:ec:5f:b2:1a:56:63:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 27:d4:f4:e0:7d:10:2b:29:8b:16:6e:f1:ce:7b:73:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 31:67:39:ca:cf:df:d3:fb:14:15:94:85:80:f4:2a:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ee:c6:93:79:ff:81:09:51:55:29:14:e7:d3:dd:87:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; d4:82:2f:c2:80:5c:e3:89:60:c6:a7:9a:43:b3:0d:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 33:98:d1:05:1c:20:38:a4:dd:19:39:b8:0b:d1:6e:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 84:8f:e9:55:df:fd:70:16:c5:f8:5d:66:6a:03:13:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 36:7b:ab:e1:7e:30:7e:76:6b:e0:50:2d:cb:ad:59:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 9c:db:66:ba:2e:9d:61:50:ad:0f:2f:fe:22:7f:bb:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ef:91:f5:70:02:bd:71:2f:6a:93:2f:db:85:fd:3e:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 28:cf:39:d1:d4:39:32:e8:c7:a0:3b:10:98:36:44:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 69:d3:15:57:bf:59:53:0c:88:01:02:78:9f:69:f6:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 1b:c2:20:5a:e0:0e:b2:1f:ed:10:c1:bf:9d:d0:17:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 9d:0a:7a:25:8d:84:bc:39:f1:1b:74:11:47:e0:68:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 03:21
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;publicExponent: &lt;span class="m"&gt;65537&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;0x10001&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;privateExponent:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 79:5d:79:31:1f:15:23:8b:4c:fc:49:0f:d7:58:2c:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;prime1:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 00:fc:4f:d2:2b:d8:79:fa:6d:ca:c4:3f:b1:fe:67:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;prime2:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 00:eb:25:19:b7:ca:02:f0:9a:09:ea:7f:19:03:40:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;exponent1:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 00:e8:69:5e:5f:a4:f8:37:06:0b:50:da:9b:4a:8c:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;exponent2:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 22:f6:11:2c:d2:4c:3d:99:a9:7f:c4:05:e4:05:db:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;coefficient:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 4a:9f:3d:f5:6f:b6:83:02:f0:57:47:03:c3:d5:8c:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;次に秘密鍵のデータから公開鍵を取り出してみる.&lt;br&gt;
公開鍵の中身が秘密鍵の中身の&lt;code&gt;modulus&lt;/code&gt;と同じになっていることが確認できる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 秘密鍵から公開鍵(public-key.pem)を出力する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl rsa -in private-key.pem -pubout -out public-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;writing RSA key
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 公開鍵が生成される&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;private-key.pem public-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 公開鍵もそのままでは読めない&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat public-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-----BEGIN PUBLIC KEY-----
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA58HW0I+9qZiHopidx7pU
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IQIDAQAB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-----END PUBLIC KEY-----
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 公開鍵の中身を確認する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl rsa -in public-key.pem -text -noout -pubin
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;RSA Public-Key: &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2048&lt;/span&gt; bit&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Modulus:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 00:e7:c1:d6:d0:8f:bd:a9:98:87:a2:98:9d:c7:ba:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 54:bb:13:73:56:ea:1b:83:38:29:ec:eb:30:96:f8:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 12:1e:7d:bf:05:b2:8b:c5:ff:33:fb:b1:7d:be:a6:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 7b:ec:62:5c:b2:d3:dd:b7:34:ec:5f:b2:1a:56:63:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 27:d4:f4:e0:7d:10:2b:29:8b:16:6e:f1:ce:7b:73:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 31:67:39:ca:cf:df:d3:fb:14:15:94:85:80:f4:2a:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ee:c6:93:79:ff:81:09:51:55:29:14:e7:d3:dd:87:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; d4:82:2f:c2:80:5c:e3:89:60:c6:a7:9a:43:b3:0d:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 33:98:d1:05:1c:20:38:a4:dd:19:39:b8:0b:d1:6e:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 84:8f:e9:55:df:fd:70:16:c5:f8:5d:66:6a:03:13:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 36:7b:ab:e1:7e:30:7e:76:6b:e0:50:2d:cb:ad:59:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 9c:db:66:ba:2e:9d:61:50:ad:0f:2f:fe:22:7f:bb:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ef:91:f5:70:02:bd:71:2f:6a:93:2f:db:85:fd:3e:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 28:cf:39:d1:d4:39:32:e8:c7:a0:3b:10:98:36:44:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 69:d3:15:57:bf:59:53:0c:88:01:02:78:9f:69:f6:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 1b:c2:20:5a:e0:0e:b2:1f:ed:10:c1:bf:9d:d0:17:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 9d:0a:7a:25:8d:84:bc:39:f1:1b:74:11:47:e0:68:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 03:21
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Exponent: &lt;span class="m"&gt;65537&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;0x10001&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このように秘密鍵からは公開鍵の中身が得られるが,&lt;br&gt;
&lt;strong&gt;公開鍵から秘密鍵を逆算することはできない&lt;/strong&gt; ので,&lt;br&gt;
公開鍵は自由に公開しても問題ない.&lt;br&gt;
(正しくは逆算は完全に不可能ではないんだけど, やろうとすると非現実的な計算時間が必要になるので誰もやろうとしない)&lt;/p&gt;
&lt;h3 id="公開鍵で暗号化する"&gt;公開鍵で暗号化する
&lt;/h3&gt;&lt;p&gt;秘密鍵と公開鍵が作成できたので,&lt;br&gt;
まずは試しに &lt;strong&gt;公開鍵を用いてデータを暗号化する&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;ここからは2つのディレクトリ(&lt;strong&gt;dirA&lt;/strong&gt;, &lt;strong&gt;dirB&lt;/strong&gt;)をデータの受信側, 送信側に見立てて進める.&lt;br&gt;
共通鍵暗号方式でデータをやり取りするには, まず受信側(&lt;strong&gt;dirA&lt;/strong&gt;)の公開鍵を送信側(&lt;strong&gt;dirB&lt;/strong&gt;)に渡す.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 秘密鍵を作ったのとは別のディレクトリで作業&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; ..
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mkdir dirB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dirA dirB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 受信側(dirA)の公開鍵を送信側(dirB)に送る&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cp dirA/public-key.pem dirB/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;次に送信側(&lt;strong&gt;dirB&lt;/strong&gt;)は受信側からもらった公開鍵でデータ(&lt;strong&gt;data.txt&lt;/strong&gt;)を暗号化する.&lt;br&gt;
公開鍵と平文データで数値計算をごにゃごにゃやった結果の値が暗号データとなる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 送信側で適当な平文データを作る&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; dirB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; abcdefg &amp;gt; data.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat data.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;abcdefg
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;data.txt public-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 公開鍵を使ってデータを暗号化する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl rsautl -encrypt -in data.txt -out encrypted-data.txt -inkey public-key.pem -pubin
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 暗号化されたデータが出力される&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;data.txt encrypted-data.txt public-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# そのまま表示しようとしても意味不明な状態&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat encrypted-data.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;�����...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;暗号化されたデータは秘密鍵によってのみ復号化できる&lt;/strong&gt; ので,&lt;br&gt;
この暗号データ(&lt;strong&gt;encrypted-data.txt&lt;/strong&gt;)を公開鍵で復号化することはできない.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 無理やり復号化を試みる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl rsautl -decrypt -in encrypted-data.txt -out decrypted-data.txt -inkey public-key.pem -pubin
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;A private key is needed &lt;span class="k"&gt;for&lt;/span&gt; this operation
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 秘密鍵じゃないとできないよって怒られる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="秘密鍵で復号化する"&gt;秘密鍵で復号化する
&lt;/h3&gt;&lt;p&gt;次に先程暗号化したデータ(&lt;strong&gt;encrypted-data.txt&lt;/strong&gt;)を送信側(&lt;strong&gt;dirB&lt;/strong&gt;)から受信側(&lt;strong&gt;dirA&lt;/strong&gt;)に渡し,&lt;br&gt;
受信側の秘密鍵で復号化してみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 送信側(dirB)から暗号データ(encrypted-data.txt)を受信側(dirA)に送る&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; ..
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cp dirB/encrypted-data.txt dirA/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 秘密鍵で復号化する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; dirA
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl rsautl -decrypt -in encrypted-data.txt -out decrypted-data.txt -inkey private-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;decrypted-data.txt encrypted-data.txt private-key.pem public-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 元のデータが復号化されている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat decrypted-data.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;abcdefg
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以上の手順で暗号化データを平文データに復号化できた.&lt;/p&gt;
&lt;p&gt;重要なのは&lt;br&gt;
&lt;strong&gt;送信側と受信側の間でやりとりされるデータが受信側の公開鍵と暗号データだけになる&lt;/strong&gt; こと.&lt;br&gt;
&lt;strong&gt;暗号化されたデータは秘密鍵によってのみ復号化できる&lt;/strong&gt; ので,&lt;br&gt;
仮に通信が傍受されても秘密鍵が盗まれない限り情報は守られる.&lt;br&gt;
これが公開鍵暗号の考え方.&lt;/p&gt;
&lt;h3 id="パスフレーズをつける"&gt;パスフレーズをつける
&lt;/h3&gt;&lt;p&gt;これまで確認したように公開鍵による暗号化で情報は守られるが,&lt;br&gt;
秘密鍵が流出した場合はそうではなくなってしまう.&lt;/p&gt;
&lt;p&gt;このため, 万が一に備えて秘密鍵自体をさらに暗号化してしまうというのがパスフレーズの考え.&lt;br&gt;
まずは確認のため, 秘密鍵にパスフレーズを追加してみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 受信側で作業&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; dirA
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;decrypted-data.txt encrypted-data.txt private-key.pem public-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 秘密鍵にパスフレーズをつける(暗号化方式はaes256を使用する)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl rsa -in private-key.pem -out private-key-with-pass-phrase.pem -aes256
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;writing RSA key
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Enter PEM pass phrase: &lt;span class="c1"&gt;# 任意のパスフレーズを入力&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Verifying - Enter PEM pass phrase: &lt;span class="c1"&gt;# パスフレーズを再入力&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;decrypted-data.txt encrypted-data.txt private-key.pem private-key-with-pass-phrase.pem public-key.pem
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;パスフレーズつきの秘密鍵を使って何かしようとすると,&lt;br&gt;
必ずパスフレーズの入力を求められる.&lt;br&gt;
このため, 万が一第三者に秘密鍵が流出してもパスフレーズがわからない限りは暗号データを復号化できない.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 秘密鍵で暗号データを復号化しようとするとパスフレーズを要求される&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl rsautl -decrypt -in encrypted-data.txt -out decrypted-data.txt -inkey private-key-with-pass-phrase.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Enter pass phrase &lt;span class="k"&gt;for&lt;/span&gt; private-key-with-pass-phrase.pem: &lt;span class="c1"&gt;# 間違ったパスフレーズを入力&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;unable to load Private Key
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# パスフレーズが違うので秘密鍵が使えない&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ただパスフレーズがあると面倒なパターンもあるので,&lt;br&gt;
これを外すこともできる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# パスフレーズを外す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl rsa -in private-key-with-pass-phrase.pem -out private-key-without-pass-phrase.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Enter pass phrase &lt;span class="k"&gt;for&lt;/span&gt; private-key-with-pass-phrase.pem: &lt;span class="c1"&gt;# 正しいパスフレーズを入力&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;writing RSA key
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# パスフレーズが要求されなくなる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ openssl rsautl -decrypt -in encrypted-data.txt -out decrypted-data.txt -inkey private-key-without-pass-phrase.pem
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;実際に手を動かして試したおかげでちょっとは理解が深まった気がする.&lt;br&gt;
公開鍵暗号方式だけではまだセキュリティに問題があるので(暗号化/復号化の計算量や公開鍵の信頼性など),&lt;br&gt;
時間があればハイブリッド暗号方式とかデジタル証明書についても実際に試してみたい.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="はらみせねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-20-public-key-practice/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-05-20-public-key-practice/sotochan_hu_a7dadfb1bb8e0b66.jpg 800w, https://blog.uzimihsr.com/post/2020-05-20-public-key-practice/sotochan_hu_522e386843bebebd.jpg 1600w, https://blog.uzimihsr.com/post/2020-05-20-public-key-practice/sotochan_hu_da6eea490de599ce.jpg 2400w, https://blog.uzimihsr.com/post/2020-05-20-public-key-practice/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;h2 id="参考"&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e7%a7%98%e5%af%86%e9%8d%b5%e3%81%a8%e5%85%ac%e9%96%8b%e9%8d%b5%e3%81%ae%e6%80%a7%e8%b3%aa" &gt;秘密鍵と公開鍵の性質&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.shoeisha.co.jp/book/detail/9784798149776" target="_blank" rel="noopener"
 &gt;アルゴリズム図鑑 絵で見てわかる26のアルゴリズム&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;めっちゃわかりやすい&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e7%a7%98%e5%af%86%e9%8d%b5%e3%81%a8%e5%85%ac%e9%96%8b%e9%8d%b5%e3%82%92%e4%bd%9c%e3%82%8b" &gt;秘密鍵と公開鍵を作る&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.openssl.org/docs/man1.1.0/man1/genrsa.html" target="_blank" rel="noopener"
 &gt;https://www.openssl.org/docs/man1.1.0/man1/genrsa.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.openssl.org/docs/man1.1.0/man1/rsa.html" target="_blank" rel="noopener"
 &gt;https://www.openssl.org/docs/man1.1.0/man1/rsa.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://wiki.openssl.org/index.php/Command_Line_Utilities#Generating_an_RSA_Private_Key" target="_blank" rel="noopener"
 &gt;https://wiki.openssl.org/index.php/Command_Line_Utilities#Generating_an_RSA_Private_Key&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e5%85%ac%e9%96%8b%e9%8d%b5%e3%81%a7%e6%9a%97%e5%8f%b7%e5%8c%96%e3%81%99%e3%82%8b" &gt;公開鍵で暗号化する&lt;/a&gt;, &lt;a class="link" href="#%e7%a7%98%e5%af%86%e9%8d%b5%e3%81%a7%e5%be%a9%e5%8f%b7%e5%8c%96%e3%81%99%e3%82%8b" &gt;秘密鍵で復号化する&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.openssl.org/docs/man1.1.0/man1/rsautl.html" target="_blank" rel="noopener"
 &gt;https://www.openssl.org/docs/man1.1.0/man1/rsautl.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%91%e3%82%b9%e3%83%95%e3%83%ac%e3%83%bc%e3%82%ba%e3%82%92%e3%81%a4%e3%81%91%e3%82%8b" &gt;パスフレーズをつける&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.openssl.org/docs/man1.1.0/man1/rsa.html" target="_blank" rel="noopener"
 &gt;https://www.openssl.org/docs/man1.1.0/man1/rsa.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Twitter APIを使ってコマンドラインからツイートする</title><link>https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/</link><pubDate>Mon, 18 May 2020 19:56:42 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sotochan.jpg" alt="Featured image of post Twitter APIを使ってコマンドラインからツイートする" /&gt;&lt;h2 id="apiからツイートしたい"&gt;APIからツイートしたい
&lt;/h2&gt;&lt;p&gt;TwitterのAPIをつかってちょっと遊んでみたくなったのでやってみた.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Twitter&lt;/code&gt;の開発者アカウントの利用申請をした&lt;/li&gt;
&lt;li&gt;APIを利用するための&lt;code&gt;Twitter app&lt;/code&gt;を作成した&lt;/li&gt;
&lt;li&gt;公式のコマンドラインツール&lt;code&gt;twurl&lt;/code&gt;を使ってAPI経由でツイートした
&lt;ul&gt;
&lt;li&gt;ついでに&lt;code&gt;anyenv&lt;/code&gt;で&lt;code&gt;Ruby&lt;/code&gt;のセットアップをした&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Mojave 10.14&lt;/li&gt;
&lt;li&gt;twurl
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/twitter/twurl" target="_blank" rel="noopener"
 &gt;https://github.com/twitter/twurl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;version 0.9.5&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;今回入れる&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;jq
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/stedolan/jq" target="_blank" rel="noopener"
 &gt;https://github.com/stedolan/jq&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;jq-1.6&lt;/li&gt;
&lt;li&gt;インストール済み&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;必須ではないがAPIレスポンスの整形に使用&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;anyenv
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/anyenv/anyenv" target="_blank" rel="noopener"
 &gt;https://github.com/anyenv/anyenv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;anyenv 1.1.1&lt;/li&gt;
&lt;li&gt;インストール済み&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;rbenv
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/rbenv/rbenv" target="_blank" rel="noopener"
 &gt;https://github.com/rbenv/rbenv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;rbenv 1.1.2-30-gc879cb0&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;twurlのために今回入れる&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Twitterのアカウント&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e9%96%8b%e7%99%ba%e8%80%85%e3%82%a2%e3%82%ab%e3%82%a6%e3%83%b3%e3%83%88%e3%81%ae%e5%88%a9%e7%94%a8%e7%94%b3%e8%ab%8b" &gt;開発者アカウントの利用申請&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#app%e3%81%ae%e4%bd%9c%e6%88%90" &gt;appの作成&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#twurl%e3%82%92%e4%bd%bf%e3%81%a3%e3%81%a6%e3%83%84%e3%82%a4%e3%83%bc%e3%83%88" &gt;twurlを使ってツイート&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="開発者アカウントの利用申請"&gt;開発者アカウントの利用申請
&lt;/h3&gt;&lt;p&gt;以前遊んだ&lt;a class="link" href="https://uzimihsr.github.io/post/2020-03-09-golang-api-client/" target="_blank" rel="noopener"
 &gt;WikipediaのAPI&lt;/a&gt;とかは誰でも自由に利用できるけど,&lt;br&gt;
&lt;a class="link" href="https://developer.twitter.com/en/docs/api-reference-index" target="_blank" rel="noopener"
 &gt;TwitterのAPI&lt;/a&gt;を使うには事前に開発者アカウントの利用申請が必要になるらしいので実際にやってみる.&lt;/p&gt;
&lt;p&gt;ブラウザで&lt;a class="link" href="https://twitter.com/login?lang=ja" target="_blank" rel="noopener"
 &gt;Twitterにログイン&lt;/a&gt;した状態で&lt;br&gt;
&lt;a class="link" href="https://developer.twitter.com/ja/apply-for-access" target="_blank" rel="noopener"
 &gt;https://developer.twitter.com/ja/apply-for-access&lt;/a&gt; を開く.&lt;br&gt;
&lt;strong&gt;開発者アカウントに申し込む&lt;/strong&gt; に進む.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Twitter" class="gallery-image" data-flex-basis="420px" data-flex-grow="175" height="1642" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc01.png" srcset="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc01_hu_c02db3b48eabc12a.png 800w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc01_hu_94f78bed4772b603.png 1600w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc01_hu_e4cbd202d44f5cb4.png 2400w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc01.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;利用目的を聞かれるので, 適当なものを選択する.&lt;br&gt;
今回は &lt;strong&gt;Exploring the API&lt;/strong&gt; にチェックをつけて進む.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Twitter" class="gallery-image" data-flex-basis="421px" data-flex-grow="175" height="1639" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc02.png" srcset="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc02_hu_f8ded4e4755e7b4c.png 800w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc02_hu_2955ff1793d42c04.png 1600w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc02_hu_d3344067866c144e.png 2400w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc02.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;開発者権限を申請するアカウント(&lt;strong&gt;@uzimihsr&lt;/strong&gt;)の情報を確認する.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Twitter" class="gallery-image" data-flex-basis="421px" data-flex-grow="175" height="1639" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc03.png" srcset="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc03_hu_5508b8c586a83898.png 800w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc03_hu_4045bcbeb69762f.png 1600w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc03_hu_7060f7f5f3d51c52.png 2400w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc03.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;住んでる国と&lt;code&gt;Twitter&lt;/code&gt;からのメールで呼ばれたい名前?を設定して次に進む.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Twitter" class="gallery-image" data-flex-basis="421px" data-flex-grow="175" height="1641" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc04.png" srcset="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc04_hu_a252946264353170.png 800w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc04_hu_7bae039048eda9e4.png 1600w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc04_hu_67e81ba2e959b878.png 2400w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc04.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;APIの使いみちを聞かれるので, &lt;strong&gt;200文字以上の英語&lt;/strong&gt; で記入する.&lt;br&gt;
自分の場合は&lt;br&gt;
&lt;em&gt;&amp;ldquo;趣味でのアプリに使用します. Linux上のコマンドラインツールからツイートの投稿, タイムラインの取得, ツイートの削除などを行う予定です. 今の所はTwitterのデータを分析して何かする予定はありません.&amp;rdquo;&lt;/em&gt;&lt;br&gt;
的な文章を埋めた.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Twitter" class="gallery-image" data-flex-basis="421px" data-flex-grow="175" height="1640" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc05.png" srcset="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc05_hu_293cc06c015cd31f.png 800w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc05_hu_2f87d5071ee56feb.png 1600w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc05_hu_55f17df14a803cd0.png 2400w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc05.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;用途が以下のどれかにあたる場合はさらに詳細な情報を追加しなきゃいけないらしい.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;Twitter&lt;/code&gt;のデータ解析を行う場合&lt;/li&gt;
&lt;li&gt;ツイート, リツイート, いいね, フォロー, DMの機能を使用する場合&lt;/li&gt;
&lt;li&gt;ツイートや&lt;code&gt;Twitter&lt;/code&gt;コンテンツの集計情報を&lt;code&gt;Twitter&lt;/code&gt;以外の場所で公開する場合&lt;/li&gt;
&lt;li&gt;用途が政府機関に関係する場合&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;自分は2のケースに該当するので,&lt;br&gt;
&lt;em&gt;&amp;ldquo;curlやjqなどのLinux上のコマンドラインツールを使ってツイートの投稿, タイムラインの取得, ツイートの検索, いいねなどを試そうと思います.&amp;rdquo;&lt;/em&gt;&lt;br&gt;
的な文章を埋めた.&lt;br&gt;
用途について記入したら次に進む.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Twitter" class="gallery-image" data-flex-basis="421px" data-flex-grow="175" height="1639" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc06.png" srcset="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc06_hu_7c51c6271aaf04eb.png 800w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc06_hu_21bfdf99238d4e6c.png 1600w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc06_hu_5ab2120a9672aded.png 2400w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc06.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;これまでの入力内容を確認して次に進む.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Twitter" class="gallery-image" data-flex-basis="421px" data-flex-grow="175" height="1639" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc07.png" srcset="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc07_hu_ce432770ee53d59a.png 800w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc07_hu_943c68773f34d524.png 1600w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc07_hu_fdbd287d30a0619e.png 2400w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc07.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;最後に利用規約を読んでチェックボックスにチェックを入れて, &lt;strong&gt;Submit Application&lt;/strong&gt; を押す.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Twitter" class="gallery-image" data-flex-basis="422px" data-flex-grow="175" height="1637" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc08.png" srcset="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc08_hu_7e5788d2536cb729.png 800w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc08_hu_1789bbf3fc4af48e.png 1600w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc08_hu_8aefe7f787472cfa.png 2400w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc08.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;確認用メールを送った旨が表示される.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Twitter" class="gallery-image" data-flex-basis="421px" data-flex-grow="175" height="1639" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc09.png" srcset="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc09_hu_d816a4f7b536aac8.png 800w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc09_hu_2e0cb4c22aeb0ef6.png 1600w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc09_hu_f08324560711a922.png 2400w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc09.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;申請したアカウントに紐付いたメールアドレスにこんな感じのメールが来るので, &lt;strong&gt;Confirm your email&lt;/strong&gt; を押す.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Mail" class="gallery-image" data-flex-basis="390px" data-flex-grow="162" height="1345" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc10.png" srcset="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc10_hu_51dee1548f0a13bc.png 800w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc10_hu_8d0f8c0c36709be8.png 1600w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc10.png 2188w" width="2188"&gt;&lt;/p&gt;
&lt;p&gt;利用申請が完了したことを示す画面が開く.&lt;br&gt;
完了までに時間がかかることもあるみたいだけど, 自分の場合は一瞬だった.&lt;br&gt;
用途とかで書いた英文を&lt;a class="link" href="https://www.grammarly.com/" target="_blank" rel="noopener"
 &gt;Grammarly&lt;/a&gt;で文法チェックしたおかげかも?&lt;/p&gt;
&lt;p&gt;&lt;img alt="Twitter" class="gallery-image" data-flex-basis="437px" data-flex-grow="182" height="1581" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc11.png" srcset="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc11_hu_6dd726bf1a0829a8.png 800w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc11_hu_298d3b63551baeea.png 1600w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc11_hu_160888ab40adb2f.png 2400w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc11.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;とりあえず, これで&lt;code&gt;Twitter&lt;/code&gt;の開発者アカウントを使えるようになった.&lt;/p&gt;
&lt;h3 id="appの作成"&gt;appの作成
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Twitter API&lt;/code&gt;の機能を使うには, &lt;code&gt;app&lt;/code&gt;を作成して認証用の&lt;code&gt;consumer key&lt;/code&gt;と&lt;code&gt;consumer secret&lt;/code&gt;を作成する必要があるらしいのでやってみる.&lt;/p&gt;
&lt;p&gt;先程の利用完了画面か,&lt;br&gt;
&lt;a class="link" href="https://developer.twitter.com/en/account/get-started" target="_blank" rel="noopener"
 &gt;https://developer.twitter.com/en/account/get-started&lt;/a&gt;&lt;br&gt;
から &lt;strong&gt;Create an app&lt;/strong&gt; に進む.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Twitter" class="gallery-image" data-flex-basis="1607px" data-flex-grow="669" height="430" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc12.png" srcset="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc12_hu_c2307eeb7419dfde.png 800w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc12_hu_4b31e38f4e0dbd84.png 1600w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc12_hu_95632a3dd24fa3a0.png 2400w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc12.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;以下の必須項目を埋めて &lt;strong&gt;Create&lt;/strong&gt; を押す.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;必須項目&lt;/th&gt;
 &lt;th&gt;詳細&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;App name&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;app&lt;/code&gt;の名前(適当につける)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Application description&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;app&lt;/code&gt;の説明&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Website URL&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;app&lt;/code&gt;に関連するウェブサイトのURL&lt;br&gt;(自分が管理しているものが望ましい)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Tell us how this app will be used&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;app&lt;/code&gt;の用途&lt;br&gt;(&lt;code&gt;Twitter&lt;/code&gt;チームがチェックするのでちゃんと書く)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;img alt="Twitter" class="gallery-image" data-flex-basis="231px" data-flex-grow="96" height="1868" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc13.png" srcset="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc13_hu_4bb4f2b119871417.png 800w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc13_hu_cb416e13fccd935e.png 1600w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc13.png 1800w" width="1800"&gt;&lt;/p&gt;
&lt;p&gt;利用規約的なやつの確認モーダルが表示されるのでちゃんと確認して &lt;strong&gt;Create&lt;/strong&gt; する.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Twitter" class="gallery-image" data-flex-basis="731px" data-flex-grow="304" height="945" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc14.png" srcset="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc14_hu_6bb7807d95363f42.png 800w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc14_hu_f3414eea5fe98e87.png 1600w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc14_hu_e35a1a44e20de9e2.png 2400w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc14.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;app&lt;/code&gt;(&lt;strong&gt;uzimihsr-twurl&lt;/strong&gt;)が作成されて詳細画面が開くので, &lt;strong&gt;Keys and tokens&lt;/strong&gt; に進む.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Twitter" class="gallery-image" data-flex-basis="436px" data-flex-grow="181" height="1584" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc15.png" srcset="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc15_hu_5ba8d9c813b50315.png 800w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc15_hu_913c096db8c22ff2.png 1600w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc15_hu_5a9a9860f12199c4.png 2400w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc15.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;表示された &lt;strong&gt;API key&lt;/strong&gt;(&lt;code&gt;consumer key&lt;/code&gt;), &lt;strong&gt;API secret key&lt;/strong&gt;(&lt;code&gt;consumer secret&lt;/code&gt;)は&lt;br&gt;
後ほど使用するのでメモしておく.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Twitter" class="gallery-image" data-flex-basis="538px" data-flex-grow="224" height="1283" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc16.png" srcset="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc16_hu_aededc07df1c1a9.png 800w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc16_hu_83dbb62155f71c94.png 1600w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc16_hu_b16a07e5b97658f5.png 2400w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc16.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;これでAPIを使うための&lt;code&gt;app&lt;/code&gt;の準備は完了.&lt;/p&gt;
&lt;h3 id="twurlを使ってツイート"&gt;twurlを使ってツイート
&lt;/h3&gt;&lt;p&gt;今回はcurlっぽく&lt;code&gt;Twitter API&lt;/code&gt;を叩くための公式のコマンドラインツール&lt;a class="link" href="https://github.com/twitter/twurl" target="_blank" rel="noopener"
 &gt;twurl&lt;/a&gt;を使って実際にツイートしてみる.&lt;/p&gt;
&lt;p&gt;まずは&lt;code&gt;twurl&lt;/code&gt;を&lt;code&gt;gem&lt;/code&gt;でインストール&amp;hellip;&lt;/p&gt;
&lt;p&gt;しようとしたら権限エラーでコケた.&lt;br&gt;
Macに最初から入ってるシステムの&lt;code&gt;Ruby&lt;/code&gt;だとうまく行かないみたい.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# twurlのインストール...に失敗&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ gem install twurl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Fetching: oauth-0.5.4.gem &lt;span class="o"&gt;(&lt;/span&gt;100%&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ERROR: While executing gem ... &lt;span class="o"&gt;(&lt;/span&gt;Gem::FilePermissionError&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以下の手順で&lt;code&gt;Ruby&lt;/code&gt;のセットアップを行う.&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;anyenvを使ったRubyのセットアップ&lt;/summary&gt;&lt;div&gt;
&lt;p&gt;&lt;code&gt;Ruby&lt;/code&gt;全然使ったことないけど&lt;code&gt;anyenv&lt;/code&gt;は神なので簡単にセットアップできる.&lt;br&gt;
&lt;a class="link" href="https://www.ruby-lang.org/ja/downloads/" target="_blank" rel="noopener"
 &gt;公式&lt;/a&gt;によると現在の安定版は &lt;strong&gt;2.7.1&lt;/strong&gt; なのでこれを入れる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# rbenvをインストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ anyenv install -l &lt;span class="p"&gt;|&lt;/span&gt; grep rbenv
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; rbenv
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ anyenv install rbenv
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Install rbenv succeeded!
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Please reload your profile &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nv"&gt;$SHELL&lt;/span&gt; -l&lt;span class="o"&gt;)&lt;/span&gt; or open a new session.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nv"&gt;$SHELL&lt;/span&gt; -l
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 動作確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ rbenv --version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rbenv 1.1.2-30-gc879cb0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Ruby(2.7.1)をインストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ rbenv install -l &lt;span class="p"&gt;|&lt;/span&gt; grep 2.7.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2.7.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ rbenv install 2.7.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ rbenv versions
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* system
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 2.7.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Rubyのバージョンを選択&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ rbenv global 2.7.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nv"&gt;$SHELL&lt;/span&gt; -l
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ rbenv versions
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; system
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 2.7.1 &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; by /Users/uzimihsr/.anyenv/envs/rbenv/version&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 動作確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ruby -v
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ruby 2.7.1p83 &lt;span class="o"&gt;(&lt;/span&gt;2020-03-31 revision a0c7c23c9c&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;x86_64-darwin18&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ gem -v
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3.1.2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;再度&lt;code&gt;twurl&lt;/code&gt;をインストール.&lt;br&gt;
今度は普通にできた.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# twurlのインストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ gem install twurl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Done installing documentation &lt;span class="k"&gt;for&lt;/span&gt; oauth, twurl after &lt;span class="m"&gt;1&lt;/span&gt; seconds
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;2&lt;/span&gt; gems installed
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 動作確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ twurl -v
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;0.9.5
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;インストールができたのでさっそく使ってみる.&lt;/p&gt;
&lt;p&gt;まずは手元の&lt;code&gt;twurl&lt;/code&gt;と先ほど作成した&lt;code&gt;app&lt;/code&gt;, そして&lt;code&gt;app&lt;/code&gt;を使用するアカウントを紐付ける.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;twurl authorize&lt;/code&gt;の引数に先程メモした&lt;code&gt;app&lt;/code&gt;の&lt;code&gt;consumer key&lt;/code&gt;と&lt;code&gt;consumer secret&lt;/code&gt;を渡すと,&lt;br&gt;
認証用のURLが表示される.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 認証画面を開く&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;keykeykeykeykeykeykeykey&amp;#39;&lt;/span&gt; &lt;span class="c1"&gt;# consumer key&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nv"&gt;secret&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;secretsecretsecretsecret&amp;#39;&lt;/span&gt; &lt;span class="c1"&gt;# consumer secret&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ twurl authorize --consumer-key &lt;span class="nv"&gt;$key&lt;/span&gt; --consumer-secret &lt;span class="nv"&gt;$secret&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Go to https://api.twitter.com/oauth/authorize?oauth_consumer_key&lt;span class="o"&gt;=&lt;/span&gt;keykeykeykeykeykeykeykey...&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;oauth_version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.0 and paste in the supplied PIN
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# メッセージに従ってURLをブラウザで開く&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;指定されたURLをブラウザで開くとアカウントに&lt;code&gt;app&lt;/code&gt;を連携させるための確認画面が表示されるので,&lt;br&gt;
&lt;strong&gt;Authorize app&lt;/strong&gt; を選択して自分のアカウントと&lt;code&gt;app&lt;/code&gt;を連携させる.&lt;br&gt;
&lt;img alt="Twitter" class="gallery-image" data-flex-basis="548px" data-flex-grow="228" height="1260" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc17.png" srcset="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc17_hu_e90ea85646b673bd.png 800w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc17_hu_218d77c62d6aa729.png 1600w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc17_hu_e0797ad3ad3919aa.png 2400w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc17.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;連携に成功すると7桁の&lt;code&gt;PIN&lt;/code&gt;が表示されるので,&lt;br&gt;
これを&lt;code&gt;twurl&lt;/code&gt;のメッセージに従って入力する.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Twitter" class="gallery-image" data-flex-basis="789px" data-flex-grow="328" height="876" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc18.png" srcset="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc18_hu_7cac1559efdc68c0.png 800w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc18_hu_71d55ad895a52e92.png 1600w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc18_hu_bf7b8975fa12aa4.png 2400w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sc18.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 先程のつづき&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ twurl authorize --consumer-key &lt;span class="nv"&gt;$key&lt;/span&gt; --consumer-secret &lt;span class="nv"&gt;$secret&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Go to https://api.twitter.com/oauth/authorize?oauth_consumer_key&lt;span class="o"&gt;=&lt;/span&gt;keykeykeykeykeykeykeykey...&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;oauth_version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.0 and paste in the supplied PIN
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;1234567&lt;/span&gt; &lt;span class="c1"&gt;# PINを入力&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Authorization successful
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 認証に成功したアカウントの確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ twurl accounts
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; keykeykeykeykeykeykeykey &lt;span class="o"&gt;(&lt;/span&gt;default&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで&lt;code&gt;twurl&lt;/code&gt;と自分のアカウントが紐付いた.&lt;/p&gt;
&lt;p&gt;次に&lt;a class="link" href="https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-update" target="_blank" rel="noopener"
 &gt;ツイート投稿API&lt;/a&gt;を叩いてツイートしてみる.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;twurl&lt;/code&gt;を使って&lt;br&gt;
&lt;code&gt;https://api.twitter.com/1.1/hoge/huga.json&lt;/code&gt;&lt;br&gt;
のようなエンドポイントを叩く場合は,&lt;br&gt;
&lt;code&gt;twurl /1.1/hoge/huga.json&lt;/code&gt;のようにすればいいみたい.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# APIからツイートしてみる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# レスポンスがJSONで返ってくるのでjqでパースする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ twurl -X POST -d &lt;span class="s1"&gt;&amp;#39;status=そとちゃんかわいい&amp;#39;&lt;/span&gt; /1.1/statuses/update.json &lt;span class="p"&gt;|&lt;/span&gt; jq
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;created_at&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;Mon May 18 10:09:54 +0000 2020&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: 1262324524051075000,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;id_str&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;1262324524051075074&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;text&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;そとちゃんかわいい&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;truncated&amp;#34;&lt;/span&gt;: false,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;entities&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;hashtags&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;[]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;symbols&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;[]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;user_mentions&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;[]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;urls&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;source&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;&amp;lt;a href=\&amp;#34;https://uzimihsr.github.io/\&amp;#34; rel=\&amp;#34;nofollow\&amp;#34;&amp;gt;uzimihsr-twurl&amp;lt;/a&amp;gt;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;in_reply_to_status_id&amp;#34;&lt;/span&gt;: null,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;in_reply_to_status_id_str&amp;#34;&lt;/span&gt;: null,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;in_reply_to_user_id&amp;#34;&lt;/span&gt;: null,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;in_reply_to_user_id_str&amp;#34;&lt;/span&gt;: null,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;in_reply_to_screen_name&amp;#34;&lt;/span&gt;: null,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;user&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: 1146420174272073700,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;id_str&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;1146420174272073733&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;ずみし&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;screen_name&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;uzimihsr&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;location&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;日本 東京&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;description&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;超絶かわいい元保護猫そとちゃんのしもべです&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;https://t.co/mM0q9F0x2t&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;entities&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;urls&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;https://t.co/mM0q9F0x2t&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;expanded_url&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;https://instagram.com/uzimihsr&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;display_url&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;instagram.com/uzimihsr&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;indices&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 0,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="m"&gt;23&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;description&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;urls&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;protected&amp;#34;&lt;/span&gt;: false,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;followers_count&amp;#34;&lt;/span&gt;: 35,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;friends_count&amp;#34;&lt;/span&gt;: 52,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;listed_count&amp;#34;&lt;/span&gt;: 0,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;created_at&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;Wed Jul 03 14:07:23 +0000 2019&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;favourites_count&amp;#34;&lt;/span&gt;: 32,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;utc_offset&amp;#34;&lt;/span&gt;: null,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;time_zone&amp;#34;&lt;/span&gt;: null,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;geo_enabled&amp;#34;&lt;/span&gt;: true,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;verified&amp;#34;&lt;/span&gt;: false,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;statuses_count&amp;#34;&lt;/span&gt;: 227,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;lang&amp;#34;&lt;/span&gt;: null,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;contributors_enabled&amp;#34;&lt;/span&gt;: false,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;is_translator&amp;#34;&lt;/span&gt;: false,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;is_translation_enabled&amp;#34;&lt;/span&gt;: false,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;profile_background_color&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;F5F8FA&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;profile_background_image_url&amp;#34;&lt;/span&gt;: null,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;profile_background_image_url_https&amp;#34;&lt;/span&gt;: null,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;profile_background_tile&amp;#34;&lt;/span&gt;: false,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;profile_image_url&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;http://pbs.twimg.com/profile_images/1220189466368692224/VkTo35n4_normal.jpg&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;profile_image_url_https&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;https://pbs.twimg.com/profile_images/1220189466368692224/VkTo35n4_normal.jpg&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;profile_banner_url&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;https://pbs.twimg.com/profile_banners/1146420174272073733/1584881012&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;profile_link_color&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;1DA1F2&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;profile_sidebar_border_color&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;C0DEED&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;profile_sidebar_fill_color&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;DDEEF6&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;profile_text_color&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;333333&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;profile_use_background_image&amp;#34;&lt;/span&gt;: true,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;has_extended_profile&amp;#34;&lt;/span&gt;: false,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;default_profile&amp;#34;&lt;/span&gt;: true,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;default_profile_image&amp;#34;&lt;/span&gt;: false,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;following&amp;#34;&lt;/span&gt;: false,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;follow_request_sent&amp;#34;&lt;/span&gt;: false,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;notifications&amp;#34;&lt;/span&gt;: false,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;translator_type&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;none&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;geo&amp;#34;&lt;/span&gt;: null,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;coordinates&amp;#34;&lt;/span&gt;: null,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;place&amp;#34;&lt;/span&gt;: null,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;contributors&amp;#34;&lt;/span&gt;: null,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;is_quote_status&amp;#34;&lt;/span&gt;: false,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;retweet_count&amp;#34;&lt;/span&gt;: 0,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;favorite_count&amp;#34;&lt;/span&gt;: 0,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;favorited&amp;#34;&lt;/span&gt;: false,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;retweeted&amp;#34;&lt;/span&gt;: false,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;lang&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;ja&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;実際に投稿されたツイートがこちら.&lt;br&gt;
連携した&lt;code&gt;app&lt;/code&gt;(&lt;strong&gt;uzimihsr-twurl&lt;/strong&gt;)から投稿されている.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;そとちゃんかわいい&lt;/p&gt;&amp;mdash; ずみし (@uzimihsr) &lt;a href="https://twitter.com/uzimihsr/status/1262324524051075074?ref_src=twsrc%5Etfw"&gt;May 18, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;


&lt;p&gt;&lt;a class="link" href="https://twitter.com/uzimihsr/status/1262324524051075074" target="_blank" rel="noopener"
 &gt;https://twitter.com/uzimihsr/status/1262324524051075074&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;やったぜ.&lt;br&gt;
コマンドラインから&lt;code&gt;Twitter API&lt;/code&gt;を使ってツイートすることができた.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;以上の手順で開発者アカウントの利用申請から&lt;code&gt;Twitter API&lt;/code&gt;を用いたツイートまでをやってみた.&lt;br&gt;
&lt;code&gt;Twitter&lt;/code&gt;大好き芸人なので&lt;code&gt;twurl&lt;/code&gt;のコード読んだりAPIリファレンス読んだりしていろいろ遊んでみたい.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="テンションが高いときのねこ(かわいい)" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sotochan_hu_65b86389571a385.jpg 800w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sotochan_hu_7bffc8c845ae8f24.jpg 1600w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sotochan_hu_7885d833e0bddb4a.jpg 2400w, https://blog.uzimihsr.com/post/2020-05-18-twitter-api-application/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;h2 id="参考"&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e9%96%8b%e7%99%ba%e8%80%85%e3%82%a2%e3%82%ab%e3%82%a6%e3%83%b3%e3%83%88%e3%81%ae%e5%88%a9%e7%94%a8%e7%94%b3%e8%ab%8b" &gt;開発者アカウントの利用申請&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://help.twitter.com/ja/rules-and-policies/twitter-api" target="_blank" rel="noopener"
 &gt;https://help.twitter.com/ja/rules-and-policies/twitter-api&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://developer.twitter.com/ja/apply-for-access" target="_blank" rel="noopener"
 &gt;https://developer.twitter.com/ja/apply-for-access&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#app%e3%81%ae%e4%bd%9c%e6%88%90" &gt;appの作成&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://developer.twitter.com/ja/docs/basics/apps/overview" target="_blank" rel="noopener"
 &gt;https://developer.twitter.com/ja/docs/basics/apps/overview&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#twurl%e3%82%92%e4%bd%bf%e3%81%a3%e3%81%a6%e3%83%84%e3%82%a4%e3%83%bc%e3%83%88" &gt;twurlを使ってツイート&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://developer.twitter.com/en/docs/tutorials/using-twurl" target="_blank" rel="noopener"
 &gt;https://developer.twitter.com/en/docs/tutorials/using-twurl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/twitter/twurl" target="_blank" rel="noopener"
 &gt;https://github.com/twitter/twurl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-update" target="_blank" rel="noopener"
 &gt;https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-update&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Kubernetes完全に理解したい 6章</title><link>https://blog.uzimihsr.com/post/2020-05-10-kubernetes-guide-chap6/</link><pubDate>Sun, 10 May 2020 10:17:07 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-05-10-kubernetes-guide-chap6/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-05-10-kubernetes-guide-chap6/sotochan.jpg" alt="Featured image of post Kubernetes完全に理解したい 6章" /&gt;&lt;h2 id="serviceとかingressとか"&gt;ServiceとかIngressとか
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://book.impress.co.jp/books/1118101055" target="_blank" rel="noopener"
 &gt;Kubernetes完全ガイド&lt;/a&gt;の続き.&lt;br&gt;
次はServiceとかの話.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="読んだもの"&gt;読んだもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://book.impress.co.jp/books/1118101055" target="_blank" rel="noopener"
 &gt;Kubernetes完全ガイド&lt;/a&gt; 6章(Discovery &amp;amp; LBリソース)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;重要そうなところとかよく使いそうなところだけまとめる.&lt;/p&gt;
&lt;h2 id="読んだことのまとめ"&gt;読んだことのまとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#service" &gt;Service&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#clusterip-service" &gt;ClusterIP Service&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#externalip-service" &gt;ExternalIP Service&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#nodeport-service" &gt;NodePort Service&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#loadBalancer-service" &gt;LoadBalancer Service&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#headless-service" &gt;Headless Service&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#externalName-service" &gt;ExternalName Service&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#none-selector-service" &gt;None-Selector Service&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#ingress" &gt;Ingress&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="service"&gt;Service
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Pod&lt;/code&gt;へのトラフィックの負荷分散とサービスディスカバリを行うリソース.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;よく使いそうな設定項目&lt;/th&gt;
 &lt;th&gt;説明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.type&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Service&lt;/code&gt;の種類を指定する&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.ports[]&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;トラフィックを受け付けるポートと&lt;br&gt;転送先コンテナのポートに関する設定&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.selector&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Service&lt;/code&gt;の対象となる&lt;code&gt;Pod&lt;/code&gt;のラベル&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code&gt;Service&lt;/code&gt;は指定したラベルを持つ&lt;code&gt;Pod&lt;/code&gt;へのトラフィックを振り分けたり,&lt;br&gt;
&lt;code&gt;Service&lt;/code&gt;名から対象となる&lt;code&gt;Pod&lt;/code&gt;を探し出したりする.&lt;br&gt;
&lt;code&gt;Pod&lt;/code&gt;は作り直すたびにIPが変わってしまうので,&lt;br&gt;
ラベルで管理する&lt;code&gt;Service&lt;/code&gt;を使うととても便利.&lt;/p&gt;
&lt;h4 id="clusterip-service"&gt;ClusterIP Service
&lt;/h4&gt;&lt;p&gt;一番簡単な&lt;code&gt;Service&lt;/code&gt;. マニフェストの&lt;code&gt;.spec.type&lt;/code&gt;は&lt;code&gt;ClusterIP&lt;/code&gt;.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;よく使いそうな設定項目&lt;/th&gt;
 &lt;th&gt;説明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.ports[].port&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;トラフィックを受け付けるポート&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.ports[].targetPort&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;転送先&lt;code&gt;Pod&lt;/code&gt;のポート(コンテナ)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;クラスタ内のみで有効な仮想IPを作成し, トラフィックをコンテナに振り分ける.&lt;br&gt;
基本的にはクラスタ内でのロードバランサ(負荷分散装置)として使用する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Deploymentが存在し, Podのラベル(app=sample-app)を指定するClusterIP Serviceが作成済の状態&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get deployments
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY UP-TO-DATE AVAILABLE AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment 3/3 &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; 80s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample-app -o custom-columns&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;NAME:{metadata.name},IP:{status.podIP}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME IP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6c5948bf66-c5j2l 10.4.2.40
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6c5948bf66-fwdzj 10.4.1.14
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6c5948bf66-xkn4v 10.4.2.41
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get service sample-clusterip
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-clusterip ClusterIP 10.7.246.109 &amp;lt;none&amp;gt; 8080/TCP 13s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Service(10.7.246.109)の8080番宛のトラフィックを各Podの80番ポートに転送する設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl describe service sample-clusterip
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: sample-clusterip
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: kubectl.kubernetes.io/last-applied-configuration:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Selector: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample-app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Type: ClusterIP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IP: 10.7.246.109
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Port: http-port 8080/TCP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;TargetPort: 80/TCP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Endpoints: 10.4.1.14:80,10.4.2.40:80,10.4.2.41:80
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Session Affinity: None
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ロードバランシングの確認のため, 各Podのnginxで表示するページにPod名を記述&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="k"&gt;for&lt;/span&gt; PODNAME in &lt;span class="k"&gt;$(&lt;/span&gt;kubectl get pods -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample-app -o &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;{.items[*].metadata.name}&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PODNAME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; -- cp /etc/hostname /usr/share/nginx/html/index.html&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 使い捨てのPodからCurlして確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 何回か繰り返すと各Pod名が表示され, 負荷分散されていることがわかる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl run --image&lt;span class="o"&gt;=&lt;/span&gt;centos:6 --restart&lt;span class="o"&gt;=&lt;/span&gt;Never --rm -i testpod -- curl -s http://10.7.246.109:8080
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6c5948bf66-c5j2l
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod &lt;span class="s2"&gt;&amp;#34;testpod&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl run --image&lt;span class="o"&gt;=&lt;/span&gt;centos:6 --restart&lt;span class="o"&gt;=&lt;/span&gt;Never --rm -i testpod -- curl -s http://10.7.246.109:8080
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6c5948bf66-fwdzj
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod &lt;span class="s2"&gt;&amp;#34;testpod&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl run --image&lt;span class="o"&gt;=&lt;/span&gt;centos:6 --restart&lt;span class="o"&gt;=&lt;/span&gt;Never --rm -i testpod -- curl -s http://10.7.246.109:8080
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6c5948bf66-xkn4v
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod &lt;span class="s2"&gt;&amp;#34;testpod&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Serviceが存在する状態でPodを再作成してIPが変わってもラベルが同じなら負荷分散の設定が効く&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl delete deployment sample-deployment
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.extensions &lt;span class="s2"&gt;&amp;#34;sample-deployment&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f sample-deployment.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps/sample-deployment created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample-app -o custom-columns&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;NAME:{metadata.name},IP:{status.podIP}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME IP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6c5948bf66-g4dpz 10.4.2.58
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6c5948bf66-h9qhx 10.4.2.59
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6c5948bf66-vvtl8 10.4.1.15
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl describe service sample-clusterip &lt;span class="p"&gt;|&lt;/span&gt; grep Endpoints
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Endpoints: 10.4.1.15:80,10.4.2.58:80,10.4.2.59:80
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podの環境変数からServiceの情報を取得できる(サービスディスカバリ)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it sample-deployment-6c5948bf66-g4dpz printenv &lt;span class="p"&gt;|&lt;/span&gt; grep SAMPLE_CLUSTERIP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;SAMPLE_CLUSTERIP_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;tcp://10.7.246.109:8080
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;SAMPLE_CLUSTERIP_PORT_8080_TCP_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;SAMPLE_CLUSTERIP_SERVICE_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10.7.246.109
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;SAMPLE_CLUSTERIP_SERVICE_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;SAMPLE_CLUSTERIP_PORT_8080_TCP_ADDR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10.7.246.109
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;SAMPLE_CLUSTERIP_SERVICE_PORT_HTTP_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;SAMPLE_CLUSTERIP_PORT_8080_TCP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;tcp://10.7.246.109:8080
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;SAMPLE_CLUSTERIP_PORT_8080_TCP_PROTO&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Service名からIPを正引きできる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# このときのFQDNは&amp;lt;Service名&amp;gt;.&amp;lt;namespace&amp;gt;.svc.cluster.localを指定する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl run --image&lt;span class="o"&gt;=&lt;/span&gt;centos:6 --restart&lt;span class="o"&gt;=&lt;/span&gt;Never --rm -i testpod -- dig sample-clusterip.default.svc.cluster.local
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;;;&lt;/span&gt; QUESTION SECTION:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;;&lt;/span&gt;sample-clusterip.default.svc.cluster.local. IN A
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;;;&lt;/span&gt; ANSWER SECTION:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-clusterip.default.svc.cluster.local. &lt;span class="m"&gt;30&lt;/span&gt; IN A 10.7.246.109
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod &lt;span class="s2"&gt;&amp;#34;testpod&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 逆引きも可能&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl run --image&lt;span class="o"&gt;=&lt;/span&gt;centos:6 --restart&lt;span class="o"&gt;=&lt;/span&gt;Never --rm -i testpod -- dig -x 10.7.246.109
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;;;&lt;/span&gt; QUESTION SECTION:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;;&lt;/span&gt;109.246.7.10.in-addr.arpa.	IN	PTR
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;;;&lt;/span&gt; ANSWER SECTION:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;109.246.7.10.in-addr.arpa. 30	IN	PTR	sample-clusterip.default.svc.cluster.local.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod &lt;span class="s2"&gt;&amp;#34;testpod&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/master/samples/chapter06/sample-deployment.yaml" target="_blank" rel="noopener"
 &gt;sample-deployment.yaml&lt;/a&gt;&lt;br&gt;
&lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/master/samples/chapter06/sample-clusterip.yaml" target="_blank" rel="noopener"
 &gt;sample-clusterip.yaml&lt;/a&gt;&lt;/p&gt;
&lt;h4 id="externalip-service"&gt;ExternalIP Service
&lt;/h4&gt;&lt;p&gt;&lt;code&gt;ClusterIP Service&lt;/code&gt;の機能に加えてクラスタ外からのトラフィックもコンテナに振り分ける&lt;code&gt;Service&lt;/code&gt;.&lt;br&gt;
マニフェストの&lt;code&gt;.spec.type&lt;/code&gt;は&lt;code&gt;ClusterIP&lt;/code&gt;であることに注意.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;よく使いそうな設定項目&lt;/th&gt;
 &lt;th&gt;説明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.externalIPs[]&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;トラフィックを受け付ける&lt;code&gt;Node&lt;/code&gt;のIP&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code&gt;ExternalIP Service&lt;/code&gt;ではクラスタの&lt;code&gt;Node&lt;/code&gt;のIPとポートを指定し,&lt;br&gt;
そこへ来たトラフィックを&lt;code&gt;Pod&lt;/code&gt;の任意のポート(コンテナ)に振り分ける.&lt;br&gt;
&lt;code&gt;Node&lt;/code&gt;のIPを指定するため,&lt;br&gt;
&lt;code&gt;Node&lt;/code&gt;へ疎通できるネットワークからであればクラスタ外からでもクラスタ内のコンテナに疎通できる.&lt;br&gt;
クラスタ内からのトラフィックについては&lt;code&gt;ClusterIP Service&lt;/code&gt;と同様に仮想IPで受けて&lt;code&gt;Pod&lt;/code&gt;に振り分ける.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podの状態&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -o custom-columns&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;NAME:{.metadata.name},PodIP:{.status.podIP}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME PodIP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6c5948bf66-9j5jh 10.4.2.3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6c5948bf66-9md5t 10.4.2.5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6c5948bf66-ghbrx 10.4.2.4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Nodeの状態&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get nodes -o custom-columns&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;NAME:{metadata.name},IP:{status.addresses[].address}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME IP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-0dgf 10.138.0.9
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-n2mf 10.138.0.10
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-wk64 10.138.0.8
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ExternalIP Service(sample-externalip)が存在する状態&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get services
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes ClusterIP 10.7.240.1 &amp;lt;none&amp;gt; 443/TCP 93d
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-externalip ClusterIP 10.7.241.169 10.138.0.9,10.138.0.10 8080/TCP 50s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Nodeのうち2つ(10.138.0.9,10.138.0.10)の8080番へのトラフィックを各Podの80番に転送する設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# クラスタ内からのトラフィックは仮想IP(10.7.241.169:8080)で受ける&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl describe service sample-externalip
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: sample-externalip
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: kubectl.kubernetes.io/last-applied-configuration:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Selector: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample-app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Type: ClusterIP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IP: 10.7.241.169
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;External IPs: 10.138.0.9,10.138.0.10
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Port: http-port 8080/TCP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;TargetPort: 80/TCP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Endpoints: 10.4.2.3:80,10.4.2.4:80,10.4.2.5:80
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Session Affinity: None
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 今回はクラスタがGKEで提供されているため, 以下のcurlは同じネットワークのインスタンスから実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ExternalIPで指定されているNodeのIPとポートを叩くとコンテナへ転送される&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://10.138.0.9:8080
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6c5948bf66-9md5t
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://10.138.0.9:8080
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6c5948bf66-9j5jh
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://10.138.0.9:8080
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6c5948bf66-ghbrx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://10.138.0.10:8080
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6c5948bf66-9md5t
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://10.138.0.10:8080
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6c5948bf66-9j5jh
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://10.138.0.10:8080
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6c5948bf66-ghbrx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ExternalIPで指定していないNodeを叩いてもコンテナへ疎通できない&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://10.138.0.8:8080
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl: &lt;span class="o"&gt;(&lt;/span&gt;7&lt;span class="o"&gt;)&lt;/span&gt; Failed to connect to 10.138.0.8 port 8080: Connection refused
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/master/samples/chapter06/sample-externalip.yaml" target="_blank" rel="noopener"
 &gt;sample-externalip.yaml&lt;/a&gt;(&lt;code&gt;.spec.externalIPs[]&lt;/code&gt;は&lt;code&gt;Node&lt;/code&gt;に合わせて書き換える)&lt;/p&gt;
&lt;h3 id="nodeport-service"&gt;NodePort Service
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;ExternalIP Service&lt;/code&gt;と同様にクラスタ外からのトラフィックを受ける&lt;code&gt;Service&lt;/code&gt;.&lt;br&gt;
マニフェストの&lt;code&gt;.spec.type&lt;/code&gt;は&lt;code&gt;NodePort&lt;/code&gt;.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;よく使いそうな設定項目&lt;/th&gt;
 &lt;th&gt;説明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.ports[].nodePort&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;クラスタ外からのトラフィックを受けるポートを指定&lt;br&gt;(指定しない場合は自動で決定)&lt;br&gt;すべての&lt;code&gt;Node&lt;/code&gt;で使用可能なポートを指定する必要がある&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code&gt;ExternalIP Service&lt;/code&gt;とは異なり,&lt;br&gt;
クラスタのすべての&lt;code&gt;Node&lt;/code&gt;の指定したポートへのトラフィックをクラスタ内の&lt;code&gt;Pod&lt;/code&gt;に転送する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podの状態&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -o custom-columns&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;NAME:{.metadata.name},PodIP:{.status.podIP}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME PodIP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6cd85bd5f-57nsj 10.0.0.6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6cd85bd5f-5rgtk 10.0.2.3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6cd85bd5f-bwq9t 10.0.1.3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# NodePort Service(sample-nodeport)が存在する状態&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get services
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes ClusterIP 10.4.0.1 &amp;lt;none&amp;gt; 443/TCP 12d
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-nodeport NodePort 10.4.13.251 &amp;lt;none&amp;gt; 8080:30080/TCP 7s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 各Nodeの30080番へのトラフィックを各Podの80番へ転送する設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# クラスタ内からのトラフィックは仮想IP(10.4.13.251)の8080番で受ける&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl describe service sample-nodeport
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: sample-nodeport
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: kubectl.kubernetes.io/last-applied-configuration:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Selector: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample-app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Type: NodePort
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IP: 10.4.13.251
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Port: http-port 8080/TCP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;TargetPort: 80/TCP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NodePort: http-port 30080/TCP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Endpoints: 10.0.0.6:80,10.0.1.3:80,10.0.2.3:80
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Session Affinity: None
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;External Traffic Policy: Cluster
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Nodeの外部IPを確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get nodes -o wide
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gke-k8s-01-pool-1-2c84f666-8jwm Ready &amp;lt;none&amp;gt; 13h v1.14.10-gke.17 10.128.15.192 www.www.www.www Container-Optimized OS from Google 4.14.138+ docker://18.9.7
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gke-k8s-01-pool-2-641104a4-7r06 Ready &amp;lt;none&amp;gt; 14h v1.14.10-gke.17 10.128.0.60 xxx.xxx.xxx.xxx Container-Optimized OS from Google 4.14.138+ docker://18.9.7
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gke-k8s-01-pool-2-641104a4-gbrv Ready &amp;lt;none&amp;gt; 20h v1.14.10-gke.17 10.128.0.56 yyy.yyy.yyy.yyy Container-Optimized OS from Google 4.14.138+ docker://18.9.7
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gke-k8s-01-pool-2-641104a4-zgjm Ready &amp;lt;none&amp;gt; 23h v1.14.10-gke.17 10.128.0.55 zzz.zzz.zzz.zzz Container-Optimized OS from Google 4.14.138+ docker://18.9.7
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# GKEなのでGCPのインスタンス一覧からでも確認できる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ gcloud compute instances list
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME ZONE MACHINE_TYPE PREEMPTIBLE INTERNAL_IP EXTERNAL_IP STATUS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gke-k8s-01-pool-1-2c84f666-8jwm us-central1-a f1-micro 10.128.15.192 www.www.www.www RUNNING
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gke-k8s-01-pool-2-641104a4-7r06 us-central1-a n1-standard-1 &lt;span class="nb"&gt;true&lt;/span&gt; 10.128.0.60 xxx.xxx.xxx.xxx RUNNING
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gke-k8s-01-pool-2-641104a4-gbrv us-central1-a n1-standard-1 &lt;span class="nb"&gt;true&lt;/span&gt; 10.128.0.56 yyy.yyy.yyy.yyy RUNNING
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gke-k8s-01-pool-2-641104a4-zgjm us-central1-a n1-standard-1 &lt;span class="nb"&gt;true&lt;/span&gt; 10.128.0.55 zzz.zzz.zzz.zzz RUNNING
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Nodeの外部IPの指定されたポートを叩くとちゃんと転送される&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://www.www.www.www:30080
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6cd85bd5f-bwq9t
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://xxx.xxx.xxx.xxx:30080
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6cd85bd5f-5rgtk
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://yyy.yyy.yyy.yyy:30080
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6cd85bd5f-57nsj
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://zzz.zzz.zzz.zzz:30080
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6cd85bd5f-57nsj
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/master/samples/chapter06/sample-nodeport.yaml" target="_blank" rel="noopener"
 &gt;sample-nodeport.yaml&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="loadbalancer-service"&gt;LoadBalancer Service
&lt;/h3&gt;&lt;p&gt;クラスタ外部のロードバランサーを利用してクラスタ外からのトラフィックを受ける&lt;code&gt;Service&lt;/code&gt;.&lt;br&gt;
マニフェストの&lt;code&gt;.spec.type&lt;/code&gt;は&lt;code&gt;LoadBalancer&lt;/code&gt;.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;よく使いそうな設定項目&lt;/th&gt;
 &lt;th&gt;説明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.ports[].port&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;外部ロードバランサーでトラフィックを受けるポートと&lt;br&gt;クラスタ内からのトラフィックを受けるポートを指定&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.ports[].nodePort&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;NodePort Service&lt;/code&gt;と同じ&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.loadBalancerIP&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;利用可能な場合のみ&lt;br&gt;外部ロードバランサーの静的IPを指定&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.loadBalancerSourceRanges&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;外部ロードバランサーのファイアウォールで&lt;br&gt;許可する通信元の設定&lt;br&gt;(未指定の場合は0.0.0.0/0になる)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code&gt;LoadBalancer Service&lt;/code&gt;クラスタ外にある&lt;code&gt;LoadBalancer&lt;/code&gt;宛のトラフィックをクラスタの&lt;code&gt;Node&lt;/code&gt;に対して振り分け,&lt;br&gt;
&lt;code&gt;Node&lt;/code&gt;に届いたトラフィックは&lt;code&gt;NodePort Service&lt;/code&gt;の仕組みで&lt;code&gt;Pod&lt;/code&gt;に転送される.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podの状態&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -o custom-columns&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;NAME:{.metadata.name},PodIP:{.status.podIP}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME PodIP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6cd85bd5f-57nsj 10.0.0.6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6cd85bd5f-5rgtk 10.0.2.3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6cd85bd5f-bwq9t 10.0.1.3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# LoadBalancer Service(sample-lb)が存在する状態&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get services
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes ClusterIP 10.4.0.1 &amp;lt;none&amp;gt; 443/TCP 12d
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-lb LoadBalancer 10.4.13.107 34.71.248.88 8080:30082/TCP 5m43s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 外部ロードバランサーの8080番に届いたトラフィックを各Nodeの30082番に振り分ける設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# NodePort Serviceを内包しているのでNodeの30082番に届いたトラフィックは各Podの80番に振り分けられる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# クラスタ内からのトラフィックは仮想IP(10.4.13.107)の8080番で受ける&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl describe service sample-lb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: sample-lb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: kubectl.kubernetes.io/last-applied-configuration:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Selector: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample-app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Type: LoadBalancer
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IP: 10.4.13.107
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;LoadBalancer Ingress: 34.71.248.88
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Port: http-port 8080/TCP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;TargetPort: 80/TCP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NodePort: http-port 30082/TCP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Endpoints: 10.0.0.6:80,10.0.1.3:80,10.0.2.3:80
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Session Affinity: None
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;External Traffic Policy: Cluster
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Reason Age From Message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---- ------ ---- ---- -------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal EnsuringLoadBalancer 6m46s service-controller Ensuring load balancer
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal EnsuredLoadBalancer 5m47s service-controller Ensured load balancer
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# GKEの場合はLoadBalancer Serviceの作成時に自動でロードバランサーが払い出される&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ gcloud compute forwarding-rules list
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME REGION IP_ADDRESS IP_PROTOCOL TARGET
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;a0c33af4a736211ea911a42010a80001 us-central1 34.71.248.88 TCP us-central1/targetPools/a0c33af4a736211ea911a42010a80001
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 外部ロードバランサーの8080番を叩くとPodに転送される&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://www.www.www.www:8080
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6cd85bd5f-bwq9t
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://www.www.www.www:8080
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6cd85bd5f-5rgtk
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://www.www.www.www:8080
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6cd85bd5f-57nsj
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/master/samples/chapter06/sample-lb.yaml" target="_blank" rel="noopener"
 &gt;sample-lb.yaml&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="headless-service"&gt;Headless Service
&lt;/h3&gt;&lt;p&gt;仮想IPではなくDNS Round Robinでエンドポイントを提供する&lt;code&gt;Service&lt;/code&gt;.&lt;br&gt;
マニフェストの&lt;code&gt;.spec.type&lt;/code&gt;は&lt;code&gt;ClusterIP&lt;/code&gt;.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;よく使いそうな設定項目&lt;/th&gt;
 &lt;th&gt;説明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.clusterIP&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;None&lt;/code&gt;のみ指定可能&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code&gt;Headless Service&lt;/code&gt;の名前解決時には&lt;code&gt;&amp;lt;serviceName&amp;gt;.&amp;lt;namespace&amp;gt;.svc.cluster.local&lt;/code&gt;で正引きできる.&lt;br&gt;
&lt;code&gt;Pod&lt;/code&gt;が&lt;code&gt;StatefulSet&lt;/code&gt;の場合のみ, &lt;code&gt;&amp;lt;podName&amp;gt;.&amp;lt;serviceName&amp;gt;.&amp;lt;namespace&amp;gt;.svc.cluster.local&lt;/code&gt;で&lt;code&gt;Pod&lt;/code&gt;単位で正引きできる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podが存在する状態&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -o custom-columns&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;NAME:{.metadata.name},PodIP:{.status.podIP}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME PodIP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-statefulset-headless-0 10.0.1.2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-statefulset-headless-1 10.0.1.3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-statefulset-headless-2 10.0.1.4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 動作確認用にnginxで表示するHTMLにPod名を記述&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="k"&gt;for&lt;/span&gt; PODNAME in &lt;span class="k"&gt;$(&lt;/span&gt;kubectl get pods -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample-app -o &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;{.items[*].metadata.name}&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PODNAME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; -- cp /etc/hostname /usr/share/nginx/html/index.html&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Headless Service(sample-headless)が存在する状態&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get services
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes ClusterIP 10.4.0.1 &amp;lt;none&amp;gt; 443/TCP 12d
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-headless ClusterIP None &amp;lt;none&amp;gt; 80/TCP 19s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# sample-headlessの80番へのトラフィックを各Podの80番に転送する設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl describe service sample-headless
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: sample-headless
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: kubectl.kubernetes.io/last-applied-configuration:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Selector: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample-app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Type: ClusterIP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IP: None
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Port: http-port 80/TCP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;TargetPort: 80/TCP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Endpoints: 10.0.1.2:80,10.0.1.3:80,10.0.1.4:80
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Session Affinity: None
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 使い捨てのPodから名前解決を行うとPodのIPが返ってくる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl run --image&lt;span class="o"&gt;=&lt;/span&gt;centos:6 --restart&lt;span class="o"&gt;=&lt;/span&gt;Never --rm -i testpod -- dig sample-headless.default.svc.cluster.local +short
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;10.0.1.4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;10.0.1.3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;10.0.1.2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod &lt;span class="s2"&gt;&amp;#34;testpod&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 使い捨てのPodからsample-headlessを叩くとRound Robin方式で各Podへ振り分けられる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl run --image&lt;span class="o"&gt;=&lt;/span&gt;centos:6 --restart&lt;span class="o"&gt;=&lt;/span&gt;Never --rm -i testpod -- curl -sSL sample-headless.default.svc.cluster.local
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-statefulset-headless-0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod &lt;span class="s2"&gt;&amp;#34;testpod&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl run --image&lt;span class="o"&gt;=&lt;/span&gt;centos:6 --restart&lt;span class="o"&gt;=&lt;/span&gt;Never --rm -i testpod -- curl -sSL sample-headless.default.svc.cluster.local
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-statefulset-headless-1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod &lt;span class="s2"&gt;&amp;#34;testpod&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl run --image&lt;span class="o"&gt;=&lt;/span&gt;centos:6 --restart&lt;span class="o"&gt;=&lt;/span&gt;Never --rm -i testpod -- curl -sSL sample-headless.default.svc.cluster.local
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-statefulset-headless-2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod &lt;span class="s2"&gt;&amp;#34;testpod&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# PodがStatefulSetで管理されている場合のみPod名でも名前解決できる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl run --image&lt;span class="o"&gt;=&lt;/span&gt;centos:6 --restart&lt;span class="o"&gt;=&lt;/span&gt;Never --rm -i testpod -- dig sample-statefulset-headless-0.sample-headless.default.svc.cluster.local +short
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;10.0.1.2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod &lt;span class="s2"&gt;&amp;#34;testpod&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl run --image&lt;span class="o"&gt;=&lt;/span&gt;centos:6 --restart&lt;span class="o"&gt;=&lt;/span&gt;Never --rm -i testpod -- dig sample-statefulset-headless-1.sample-headless.default.svc.cluster.local +short
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;10.0.1.3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod &lt;span class="s2"&gt;&amp;#34;testpod&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl run --image&lt;span class="o"&gt;=&lt;/span&gt;centos:6 --restart&lt;span class="o"&gt;=&lt;/span&gt;Never --rm -i testpod -- dig sample-statefulset-headless-2.sample-headless.default.svc.cluster.local +short
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;10.0.1.4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod &lt;span class="s2"&gt;&amp;#34;testpod&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/master/samples/chapter06/sample-statefulset-headless.yaml" target="_blank" rel="noopener"
 &gt;sample-statefulset-headless.yaml&lt;/a&gt;&lt;br&gt;
&lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/master/samples/chapter06/sample-headless.yaml" target="_blank" rel="noopener"
 &gt;sample-headless.yaml&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="externalname-service"&gt;ExternalName Service
&lt;/h3&gt;&lt;p&gt;名前解決に対して外部ドメインのCNAMEを返す&lt;code&gt;Service&lt;/code&gt;.&lt;br&gt;
マニフェストの&lt;code&gt;.spec.type&lt;/code&gt;は&lt;code&gt;ExternalName&lt;/code&gt;.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;よく使いそうな設定項目&lt;/th&gt;
 &lt;th&gt;説明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.externalName&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;外部ドメインのCNAMEを指定できる&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;クラスタ内から外部のサービスに対してアクセスする際は&lt;code&gt;ExternalName Service&lt;/code&gt;に対して名前解決を行い得られたCNAMEを利用すればいいので,&lt;br&gt;
&lt;code&gt;Pod&lt;/code&gt;内に外部サービスのアクセス先情報を持たせる必要がなくなり,&lt;br&gt;
アクセス先を変える場合は&lt;code&gt;ExternalName Service&lt;/code&gt;の設定変更のみで行うことができる(疎結合).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ExternalName Service(sample-externalname)が存在する状態&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get services
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes ClusterIP 10.4.0.1 &amp;lt;none&amp;gt; 443/TCP 13d
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-externalname ExternalName &amp;lt;none&amp;gt; example.com &amp;lt;none&amp;gt; 5s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# example.comをCNAMEとして返す設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl describe service sample-externalname
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: sample-externalname
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: kubectl.kubernetes.io/last-applied-configuration:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Selector: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Type: ExternalName
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IP:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;External Name: example.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Session Affinity: None
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 使い捨てのPodから名前解決するとCNAMEが返ってくる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl run --image&lt;span class="o"&gt;=&lt;/span&gt;centos:6 --restart&lt;span class="o"&gt;=&lt;/span&gt;Never --rm -i testpod -- dig sample-externalname.default.svc.cluster.local CNAME +short
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;example.com.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod &lt;span class="s2"&gt;&amp;#34;testpod&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# クラスタ内からそのままServiceを叩いてもエラーになる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl run --image&lt;span class="o"&gt;=&lt;/span&gt;centos:6 --restart&lt;span class="o"&gt;=&lt;/span&gt;Never --rm -i testpod -- curl -I -sSL sample-externalname.default.svc.cluster.local
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;HTTP/1.1 &lt;span class="m"&gt;404&lt;/span&gt; Not Found
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Content-Type: text/html
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Date: Wed, &lt;span class="m"&gt;01&lt;/span&gt; Apr &lt;span class="m"&gt;2020&lt;/span&gt; 14:54:34 GMT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Server: ECS &lt;span class="o"&gt;(&lt;/span&gt;ord/4CF4&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Content-Length: &lt;span class="m"&gt;345&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod &lt;span class="s2"&gt;&amp;#34;testpod&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ホストヘッダを付与してServiceを叩くとexample.comに接続できる(本来の用途ではないはず...)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl run --image&lt;span class="o"&gt;=&lt;/span&gt;centos:6 --restart&lt;span class="o"&gt;=&lt;/span&gt;Never --rm -i testpod -- curl -I -sSL sample-externalname.default.svc.cluster.local -H &lt;span class="s1"&gt;&amp;#39;Host:example.com&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;HTTP/1.1 &lt;span class="m"&gt;200&lt;/span&gt; OK
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Accept-Ranges: bytes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Age: &lt;span class="m"&gt;522515&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Cache-Control: max-age&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;604800&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Content-Type: text/html&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;charset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;UTF-8
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Date: Wed, &lt;span class="m"&gt;01&lt;/span&gt; Apr &lt;span class="m"&gt;2020&lt;/span&gt; 14:54:39 GMT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Etag: &lt;span class="s2"&gt;&amp;#34;3147526947+ident&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Expires: Wed, &lt;span class="m"&gt;08&lt;/span&gt; Apr &lt;span class="m"&gt;2020&lt;/span&gt; 14:54:39 GMT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Last-Modified: Thu, &lt;span class="m"&gt;17&lt;/span&gt; Oct &lt;span class="m"&gt;2019&lt;/span&gt; 07:18:26 GMT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Server: ECS &lt;span class="o"&gt;(&lt;/span&gt;ord/572A&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;X-Cache: HIT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Content-Length: &lt;span class="m"&gt;1256&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod &lt;span class="s2"&gt;&amp;#34;testpod&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/master/samples/chapter06/sample-externalname.yaml" target="_blank" rel="noopener"
 &gt;sample-externalname.yaml&lt;/a&gt;(&lt;code&gt;.spec.externalName&lt;/code&gt;は好きな外部のドメインに書き換える)&lt;/p&gt;
&lt;h3 id="none-selector-service"&gt;None-Selector Service
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;ExternalName Service&lt;/code&gt;と異なり, 名前解決に対してCNAMEを返すのではなく指定したIPに対してロードバランシングする&lt;code&gt;Service&lt;/code&gt;.&lt;br&gt;
マニフェストの&lt;code&gt;.spec.type&lt;/code&gt;は&lt;code&gt;ClusterIP&lt;/code&gt;.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;よく使いそうな設定項目&lt;/th&gt;
 &lt;th&gt;説明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.metadata.name&lt;/code&gt;(&lt;code&gt;Endpoint&lt;/code&gt;)&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Service&lt;/code&gt;と同じ名前を指定&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.subnets[].addresses[].ip&lt;/code&gt;(&lt;code&gt;Endpoint&lt;/code&gt;)&lt;/td&gt;
 &lt;td&gt;ロードバランシングしたいIPを指定&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code&gt;.spec.selector&lt;/code&gt;がなく&lt;code&gt;.spec.type&lt;/code&gt;が&lt;code&gt;ClusterIP&lt;/code&gt;の&lt;code&gt;Service&lt;/code&gt;なので,&lt;br&gt;
仮想IP(ClusterIP)を叩かれたときの転送先の設定を同じ名前の&lt;code&gt;Endpoints&lt;/code&gt;に定義する必要がある.&lt;br&gt;
(実は他の&lt;code&gt;Service&lt;/code&gt;は生成時に自動で対応する&lt;code&gt;Endpoints&lt;/code&gt;を作っている.)&lt;br&gt;
ちょっとむずかしいけど, 要はクラスタ内からの通信に対して任意のロードバランサーが作れる仕組み.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# None-Selector Service(sample-none-selector)が存在する状態&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get services sample-none-selector
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-none-selector ClusterIP 10.4.2.165 &amp;lt;none&amp;gt; 8080/TCP 12s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# クラスタ内から仮想IP(10.4.2.165)に対して名前解決した場合17.178.96.59(apple.com)か172.217.175.110(google.com)に分ける設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# あくまでわかりやすくするための例. 本当はちゃんと同じ外部サービスのIPを複数指定するべき. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl describe service sample-none-selector
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: sample-none-selector
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: kubectl.kubernetes.io/last-applied-configuration:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Selector: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Type: ClusterIP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IP: 10.4.2.165
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Port: &amp;lt;unset&amp;gt; 8080/TCP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;TargetPort: 80/TCP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Endpoints: 17.178.96.59:80,172.217.175.110:80
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Session Affinity: None
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 手動で作成したEndpoints&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get endpoints sample-none-selector
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME ENDPOINTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-none-selector 17.178.96.59:80,172.217.175.110:80 78s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# None-Selector Serviceは同じ名前のEndpointsに設定されたIPを参照している&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl describe endpoints sample-none-selector
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: sample-none-selector
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: kubectl.kubernetes.io/last-applied-configuration:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Subsets:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Addresses: 17.178.96.59,172.217.175.110
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; NotReadyAddresses: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ports:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Name Port Protocol
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---- ---- --------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;unset&amp;gt; &lt;span class="m"&gt;80&lt;/span&gt; TCP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 使い捨てのPodから仮想IPを叩くと指定した外部IPに転送される&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl run --image&lt;span class="o"&gt;=&lt;/span&gt;centos:6 --restart&lt;span class="o"&gt;=&lt;/span&gt;Never --rm -i testpod -- curl -I -s 10.4.2.165:8080
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;HTTP/1.1 &lt;span class="m"&gt;301&lt;/span&gt; Moved Permanently
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Location: http://www.google.com:8080/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Content-Type: text/html&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;charset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;UTF-8
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Date: Thu, &lt;span class="m"&gt;02&lt;/span&gt; Apr &lt;span class="m"&gt;2020&lt;/span&gt; 14:38:32 GMT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Expires: Sat, &lt;span class="m"&gt;02&lt;/span&gt; May &lt;span class="m"&gt;2020&lt;/span&gt; 14:38:32 GMT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Cache-Control: public, max-age&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2592000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Server: gws
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Content-Length: &lt;span class="m"&gt;224&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;X-XSS-Protection: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;X-Frame-Options: SAMEORIGIN
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod &lt;span class="s2"&gt;&amp;#34;testpod&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl run --image&lt;span class="o"&gt;=&lt;/span&gt;centos:6 --restart&lt;span class="o"&gt;=&lt;/span&gt;Never --rm -i testpod -- curl -I -s 10.4.2.165:8080
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;HTTP/1.1 &lt;span class="m"&gt;301&lt;/span&gt; MOVED PERMANENTLY
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Server: Apache
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Date: Thu, &lt;span class="m"&gt;02&lt;/span&gt; Apr &lt;span class="m"&gt;2020&lt;/span&gt; 14:38:37 GMT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Location: https://www.apple.com/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Content-type: text/html
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Connection: close
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod &lt;span class="s2"&gt;&amp;#34;testpod&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/master/samples/chapter06/sample-none-selector.yaml" target="_blank" rel="noopener"
 &gt;sample-none-selector.yaml&lt;/a&gt;(&lt;code&gt;Endpoints&lt;/code&gt;の&lt;code&gt;.subnets[].addresses[].ip&lt;/code&gt;は有効な外部のドメインに書き換える)&lt;/p&gt;
&lt;h3 id="ingress"&gt;Ingress
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Service&lt;/code&gt;とは異なり, L7レベルのロードバランシングを行うリソース.&lt;br&gt;
&lt;code&gt;Ingress&lt;/code&gt;自体の実装方法にもいろいろ種類はあるけど,&lt;br&gt;
基本的には自身へのトラフィックをパスに応じた&lt;code&gt;Service&lt;/code&gt;に転送する.&lt;br&gt;
nginxのリバースプロキシみたいな感じ.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;よく使いそうな設定項目&lt;/th&gt;
 &lt;th&gt;説明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.rules[].host&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;仮想ホスト名&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.rules[].http.paths[].path&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;トラフィックを振り分けるためのパスを設定&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.rules[].http.paths[].backend.serviceName&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;~.path&lt;/code&gt;へのトラフィックを&lt;br&gt;転送する先の&lt;code&gt;Service&lt;/code&gt;名を指定&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.rules[].http.paths[].backend.servicePort&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;~.serviceName&lt;/code&gt;の&lt;code&gt;Service&lt;/code&gt;のポート番号を指定&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.backend.serviceName&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;パスを指定されなかった場合にトラフィックを転送する&lt;code&gt;Service&lt;/code&gt;名を指定&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.backend.servicePort&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;パスを指定されなかった場合にトラフィックを転送する&lt;code&gt;Service&lt;/code&gt;のポート番号を指定&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;GKEの場合はクラスタ外のロードバランサーを利用し,&lt;br&gt;
そのロードバランサー宛のトラフィックを&lt;code&gt;Service&lt;/code&gt;に転送する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podとそれに紐づくServiceが存在する状態&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 各Serviceは自身の8888番へのアクセスを同じsuffixがついたPodに転送する設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get all
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/sample-ingress-apps-1 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 62s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/sample-ingress-apps-2 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 61s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/sample-ingress-default 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 60s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/sample-ingress-default NodePort 10.4.2.125 &amp;lt;none&amp;gt; 8888:32343/TCP 62s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/sample-ingress-svc-1 NodePort 10.4.4.202 &amp;lt;none&amp;gt; 8888:30755/TCP 63s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/sample-ingress-svc-2 NodePort 10.4.0.222 &amp;lt;none&amp;gt; 8888:31640/TCP 62s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 各Podへのリクエストに対してPod名を返す設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it sample-ingress-apps-1 -- mkdir /usr/share/nginx/html/path1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it sample-ingress-apps-1 -- /bin/sh -c &lt;span class="s1"&gt;&amp;#39;hostname &amp;gt; /usr/share/nginx/html/path1/index.html&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it sample-ingress-apps-2 -- mkdir /usr/share/nginx/html/path2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it sample-ingress-apps-2 -- /bin/sh -c &lt;span class="s1"&gt;&amp;#39;hostname &amp;gt; /usr/share/nginx/html/path2/index.html&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it sample-ingress-default -- /bin/sh -c &lt;span class="s1"&gt;&amp;#39;hostname &amp;gt; /usr/share/nginx/html/index.html&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Ingress(sample-ingress)はパスに応じて違うBackend(Service)にトラフィックを分ける設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get ingresses
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME HOSTS ADDRESS PORTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-ingress sample.example.com 35.190.31.149 80, &lt;span class="m"&gt;443&lt;/span&gt; 2d1h
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl describe ingress sample-ingress
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: sample-ingress
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Address: 35.190.31.149
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Default backend: sample-ingress-default:8888 &lt;span class="o"&gt;(&lt;/span&gt;&amp;lt;none&amp;gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;TLS:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; tls-sample terminates sample.example.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Rules:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Host Path Backends
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---- ---- --------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; sample.example.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; /path1/* sample-ingress-svc-1:8888 &lt;span class="o"&gt;(&lt;/span&gt;&amp;lt;none&amp;gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; /path2/* sample-ingress-svc-2:8888 &lt;span class="o"&gt;(&lt;/span&gt;&amp;lt;none&amp;gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Ingress宛にリクエストするとパスに応じて異なるServiceからそれぞれのPodにルーティングされる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://35.190.31.149/index.html -H &lt;span class="s2"&gt;&amp;#34;Host: sample.example.com&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-ingress-default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://35.190.31.149/path1/index.html -H &lt;span class="s2"&gt;&amp;#34;Host: sample.example.com&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-ingress-apps-1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://35.190.31.149/path2/index.html -H &lt;span class="s2"&gt;&amp;#34;Host: sample.example.com&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-ingress-apps-2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/master/samples/chapter06/sample-ingress-apps.yaml" target="_blank" rel="noopener"
 &gt;sample-ingress-apps.yaml&lt;/a&gt;&lt;br&gt;
&lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/master/samples/chapter06/sample-ingress.yaml" target="_blank" rel="noopener"
 &gt;sample-ingress.yaml&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;キメ顔ねこ&lt;br&gt;
&lt;img alt="そとちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-10-kubernetes-guide-chap6/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-05-10-kubernetes-guide-chap6/sotochan_hu_f402117b0e926564.jpg 800w, https://blog.uzimihsr.com/post/2020-05-10-kubernetes-guide-chap6/sotochan_hu_9c85c8d695c252ac.jpg 1600w, https://blog.uzimihsr.com/post/2020-05-10-kubernetes-guide-chap6/sotochan_hu_490beda017c35fff.jpg 2400w, https://blog.uzimihsr.com/post/2020-05-10-kubernetes-guide-chap6/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>Grafanaをログイン(パスワード)なしで見られるようにする</title><link>https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/</link><pubDate>Fri, 08 May 2020 20:06:38 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sotochan.jpg" alt="Featured image of post Grafanaをログイン(パスワード)なしで見られるようにする" /&gt;&lt;h2 id="ログインが面倒"&gt;ログインが面倒
&lt;/h2&gt;&lt;p&gt;Grafanaのダッシュボードを他の人に見せるときにいちいちパスワードを入力してログインしてもらうのが面倒だと思った.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Snapshot&lt;/code&gt;を使ってダッシュボードを共有した&lt;/li&gt;
&lt;li&gt;ダッシュボードをログインなしで閲覧できるよう設定した&lt;/li&gt;
&lt;li&gt;ログインなしで見られるダッシュボードを&lt;code&gt;Organization&lt;/code&gt;で分けた&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Raspberry Pi 3 Model B+
&lt;ul&gt;
&lt;li&gt;OSはRaspbian(10.0)&lt;/li&gt;
&lt;li&gt;監視サーバとして使用&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Grafana
&lt;ul&gt;
&lt;li&gt;v6.5.2&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2020-01-15-prometheus-grafana-raspberry-pi/" target="_blank" rel="noopener"
 &gt;インストール済み&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#snapshot%e3%82%92%e4%bd%bf%e3%81%86" &gt;Snapshotを使う&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#anonymous-access%e3%82%92%e6%9c%89%e5%8a%b9%e3%81%ab%e3%81%99%e3%82%8b" &gt;anonymous accessを有効にする&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#organization%e3%82%92%e5%88%86%e3%81%91%e3%82%8b" &gt;Organizationを分ける&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="snapshotを使う"&gt;Snapshotを使う
&lt;/h3&gt;&lt;p&gt;初期設定の&lt;code&gt;Grafana&lt;/code&gt;を開くとIDとパスワードでのログインを求められる.&lt;/p&gt;
&lt;p&gt;&lt;img alt="ログイン画面" class="gallery-image" data-flex-basis="422px" data-flex-grow="176" height="1636" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc01.png" srcset="https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc01_hu_6b936e0c62abd401.png 800w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc01_hu_ed2d17638ff9db14.png 1600w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc01_hu_5994baff9cd753c4.png 2400w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc01.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;自分が管理者であれば普通にログインするだけなんだけど,&lt;br&gt;
他の人にダッシュボードを共有するときにいちいち新規ユーザーを作ってパスワードを発行するのはめんどくさい.&lt;/p&gt;
&lt;p&gt;こんなときに&lt;code&gt;Snapshot&lt;/code&gt;を使うとダッシュボードの状態を保存して共有できる.&lt;/p&gt;
&lt;p&gt;共有したいダッシュボード右上の&lt;code&gt;Share&lt;/code&gt;ボタンから&lt;code&gt;Snapshot&lt;/code&gt;を選択する.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Snapshot name&lt;/code&gt;(共有する&lt;code&gt;Snapshot&lt;/code&gt;の名前)と&lt;code&gt;Expire&lt;/code&gt;(&lt;code&gt;Snapshot&lt;/code&gt;の有効期限),&lt;br&gt;
&lt;code&gt;Timeout&lt;/code&gt;(メトリクス取得のタイムアウト秒数)が設定できるけど,&lt;br&gt;
特に何も変えずに&lt;code&gt;Local Snapshot&lt;/code&gt;を選択する.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Snapshot" class="gallery-image" data-flex-basis="421px" data-flex-grow="175" height="1639" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc02.png" srcset="https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc02_hu_1542e708251f7ad6.png 800w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc02_hu_9741cf476a74c0c6.png 1600w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc02_hu_998691d2e9dcea6d.png 2400w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc02.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Snapshot&lt;/code&gt;のURLが生成される.&lt;br&gt;
ただしこの状態ではホストが &lt;strong&gt;localhost&lt;/strong&gt; になっているので注意.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Snapshot" class="gallery-image" data-flex-basis="422px" data-flex-grow="176" height="1636" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc03.png" srcset="https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc03_hu_6a0dad283d91cc56.png 800w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc03_hu_d84b960ffec42ed.png 1600w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc03_hu_507e0d3ddb4ef8f3.png 2400w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc03.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Snapshot&lt;/code&gt;の一覧は画面左のメニューから&lt;code&gt;Dashboards&lt;/code&gt;-&amp;gt;&lt;code&gt;Snapshots&lt;/code&gt;で確認できる.&lt;br&gt;
ここで表示されるURLを使うのがかんたん.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Snapshot" class="gallery-image" data-flex-basis="422px" data-flex-grow="175" height="1637" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc04.png" srcset="https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc04_hu_59b06c15d2cb77a0.png 800w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc04_hu_6c0d7c685c989d5f.png 1600w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc04_hu_ba4fec8c5d4baeac.png 2400w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc04.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;ログインしてたときのキャッシュを使わないようにシークレットブラウザで&lt;code&gt;Snapshot&lt;/code&gt;のURLを開いてみると,&lt;br&gt;
今度はログインなしでダッシュボードが開ける.&lt;/p&gt;
&lt;p&gt;&lt;img alt="ダッシュボードのSnapshot" class="gallery-image" data-flex-basis="420px" data-flex-grow="175" height="1642" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc05.png" srcset="https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc05_hu_5b4a878a699904b6.png 800w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc05_hu_3927e4b82080d7ab.png 1600w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc05_hu_f5ee4f5d7e282d5e.png 2400w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc05.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;ただし&lt;code&gt;Snapshot&lt;/code&gt;は作成時に時間の範囲が固定されてしまうので,&lt;br&gt;
画像のように範囲を変えるとメトリクスを見ることができない&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img alt="ダッシュボードのSnapshot" class="gallery-image" data-flex-basis="421px" data-flex-grow="175" height="1640" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc06.png" srcset="https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc06_hu_6447ce409cc21b75.png 800w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc06_hu_ef09cfa53317f6e3.png 1600w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc06_hu_10802025249f7b36.png 2400w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc06.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;h3 id="anonymous-accessを有効にする"&gt;anonymous accessを有効にする
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Snapshot&lt;/code&gt;は簡単に共有できるので便利だけど,&lt;br&gt;
やっぱり普通のダッシュボードが見たいのでそもそものログイン設定をいじってみる.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Grafana&lt;/code&gt;の設定ファイル(&lt;code&gt;grafana.ini&lt;/code&gt;)を編集する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Grafana設定ファイルを編集して再起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo vim /etc/grafana/grafana.ini
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl restart grafana-server
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;設定はこんな感じ.&lt;br&gt;
だいたい &lt;strong&gt;290&lt;/strong&gt; 行目あたりに&lt;code&gt;Anonymous Auth&lt;/code&gt;の設定があるので変更する.&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;grafana.ini(抜粋)&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#################################### Anonymous Auth ######################&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[auth.anonymous]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# enable anonymous access&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ゲストユーザー(ログインなし)のアクセスを許可する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;enabled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# specify organization name that should be used for unauthenticated users&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Organization名を指定する(Main Org.はデフォルトで作成されている)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;org_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;Main Org.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# specify role for unauthenticated users&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ゲストユーザーのRole(役割)をViewer(閲覧のみ)にする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Editor(編集者), Admin(管理者)も設定可能&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;org_role&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;Viewer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;再起動した後, &lt;a class="link" href="#snapshot%e3%82%92%e4%bd%bf%e3%81%86" &gt;Snapshotを使う&lt;/a&gt;と同様にシークレットブラウザで&lt;code&gt;Grafana&lt;/code&gt;のURLを開くと
今度はログインなしでダッシュボードが開かれる.&lt;/p&gt;
&lt;p&gt;こちらは元のダッシュボードそのものなので時間の範囲を変更してもメトリクスは問題なく表示できるが,&lt;br&gt;
&lt;code&gt;Role&lt;/code&gt;が&lt;code&gt;Viewer&lt;/code&gt;なので編集ができなくなっていて, &lt;code&gt;Data Source&lt;/code&gt;や&lt;code&gt;Query&lt;/code&gt;も見えなくなっている.&lt;/p&gt;
&lt;p&gt;&lt;img alt="ダッシュボード" class="gallery-image" data-flex-basis="422px" data-flex-grow="175" height="1637" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc07.png" srcset="https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc07_hu_8b4eeddc126411a4.png 800w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc07_hu_29839ce4a270d6a1.png 1600w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc07_hu_b729a4f6d43b546a.png 2400w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc07.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;編集のためにログインしたい場合は左下の&lt;code&gt;Sign in&lt;/code&gt;からログイン画面が開くので,&lt;br&gt;
そこからログインすれば今まで通り編集ができるようになる.&lt;/p&gt;
&lt;p&gt;&lt;img alt="ダッシュボード" class="gallery-image" data-flex-basis="422px" data-flex-grow="175" height="1637" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc08.png" srcset="https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc08_hu_e5118793c211cf7c.png 800w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc08_hu_80598b5ff4c6d82b.png 1600w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc08_hu_513233e246713814.png 2400w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc08.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="編集できる" class="gallery-image" data-flex-basis="421px" data-flex-grow="175" height="1638" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc09.png" srcset="https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc09_hu_16ee1acb74e2b111.png 800w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc09_hu_30c757352d65f966.png 1600w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc09_hu_50e8e9ae4073887e.png 2400w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc09.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;これで閲覧のみの場合はログインなしで&lt;code&gt;Grafana&lt;/code&gt;に入れるようになった.&lt;br&gt;
やったぜ.&lt;/p&gt;
&lt;h3 id="organizationを分ける"&gt;Organizationを分ける
&lt;/h3&gt;&lt;p&gt;以上の手順で&lt;code&gt;anonymous access&lt;/code&gt;を許可すると,&lt;br&gt;
指定した&lt;code&gt;Organization&lt;/code&gt;のダッシュボードがすべてログインなしで閲覧可能になってしまう.&lt;/p&gt;
&lt;p&gt;そのため, 作成途中のダッシュボードやあまり他の人に知られたくないメトリクスの場合は&lt;code&gt;Organization&lt;/code&gt;を分けて管理することにする.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Organization&lt;/code&gt;の作成はUIから簡単にできる.&lt;br&gt;
&lt;code&gt;Admin&lt;/code&gt;権限でログインした状態で画面左のメニューから&lt;code&gt;Server Admin&lt;/code&gt;-&amp;gt;&lt;code&gt;Orgs&lt;/code&gt;-&amp;gt;&lt;code&gt;New Org&lt;/code&gt;と進み,&lt;br&gt;
&lt;code&gt;Org. name&lt;/code&gt;に任意の&lt;code&gt;Organization&lt;/code&gt;名を入力して&lt;code&gt;Create&lt;/code&gt;するだけ.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Oragnizationの作成" class="gallery-image" data-flex-basis="420px" data-flex-grow="175" height="1645" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc10.png" srcset="https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc10_hu_4c74438beb1e738a.png 800w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc10_hu_3c3f2e5c7e9e1686.png 1600w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc10_hu_b6ea95842a708f1.png 2400w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc10.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;または, &lt;code&gt;Grafana&lt;/code&gt;のAPIを使って作成することもできる.&lt;br&gt;
初期設定の場合はbasic認証がかけられているので&lt;code&gt;Admin&lt;/code&gt;権限ユーザーのIDとパスワードで突破する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -X POST http://&amp;lt;GrafanaのURL&amp;gt;/api/orgs &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -u &amp;lt;Admin権限のuser&amp;gt;:&amp;lt;password&amp;gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -H &lt;span class="s2"&gt;&amp;#34;Accept: application/json&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -H &lt;span class="s2"&gt;&amp;#34;Content-Type: application/json&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -d &lt;span class="s1"&gt;&amp;#39;{&amp;#34;name&amp;#34;:&amp;#34;Org2&amp;#34;}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;message&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;Organization created&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;orgId&amp;#34;&lt;/span&gt;:3&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img alt="Organization" class="gallery-image" data-flex-basis="422px" data-flex-grow="175" height="1637" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc11.png" srcset="https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc11_hu_fd533e044e84c077.png 800w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc11_hu_43977e100e54ee89.png 1600w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc11_hu_8265211b49a1f872.png 2400w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc11.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;新しく作った&lt;code&gt;Organization&lt;/code&gt;(&lt;strong&gt;Org1&lt;/strong&gt;)でダッシュボードを作成して保存する.&lt;/p&gt;
&lt;p&gt;&lt;img alt="ダッシュボード" class="gallery-image" data-flex-basis="421px" data-flex-grow="175" height="1639" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc12.png" srcset="https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc12_hu_8e336a05f3c77a3d.png 800w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc12_hu_b39fc1f96ff6a3ec.png 1600w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc12_hu_f2cc056d98f1971f.png 2400w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc12.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;再度&lt;code&gt;Grafana&lt;/code&gt;の設定を変更する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Grafana設定ファイルを編集して再起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo vim /etc/grafana/grafana.ini
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl restart grafana-server
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;details&gt;&lt;summary&gt;grafana.ini(抜粋)&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#################################### Anonymous Auth ######################&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[auth.anonymous]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# enable anonymous access&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;enabled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# specify organization name that should be used for unauthenticated users&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 新しく作ったOrganizationを指定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;org_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;Org1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# specify role for unauthenticated users&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;org_role&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;Viewer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;これまでと同様にシークレットブラウザで&lt;code&gt;Grafana&lt;/code&gt;を開くと同様にログインなしで入れるが,&lt;br&gt;
今度は &lt;strong&gt;Org1&lt;/strong&gt; のダッシュボードしか見られないようになっている.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Org1のダッシュボード" class="gallery-image" data-flex-basis="421px" data-flex-grow="175" height="1641" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc13.png" srcset="https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc13_hu_fc30ec86cc0592b6.png 800w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc13_hu_e5d8c0f484394a64.png 1600w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc13_hu_8da0ed99b6d3a45e.png 2400w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc13.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;元々の&lt;code&gt;Organization&lt;/code&gt;(&lt;strong&gt;Main Org.&lt;/strong&gt;)を開きたい場合はログインした状態で&lt;br&gt;
左下のユーザーアイコンから&lt;code&gt;Switch Organization&lt;/code&gt;-&amp;gt;&lt;code&gt;Switch to&lt;/code&gt;で切り替えられる.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Organizationの変更" class="gallery-image" data-flex-basis="420px" data-flex-grow="175" height="1642" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc14.png" srcset="https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc14_hu_30fa544a50c11ba1.png 800w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc14_hu_49fddb688acf0c1.png 1600w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc14_hu_497123898d430cc6.png 2400w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sc14.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;これでログインなしで見られるダッシュボードを管理することができた.&lt;br&gt;
やったぜ.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;これで&lt;code&gt;Grafana&lt;/code&gt;のダッシュボードをログインなしで見られるようになった.&lt;br&gt;
設定自体は3行だけでできてめっちゃ簡単だったし,&lt;br&gt;
ダッシュボードが完成した後はあまりいじることもないので基本はこの設定にしておくのが便利だと思った.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;アンモニャイト&lt;br&gt;
&lt;img alt="そとちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sotochan_hu_1a8a08b59cc97f0c.jpg 800w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sotochan_hu_be9c953f66c9f806.jpg 1600w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sotochan_hu_33867d4076a853ca.jpg 2400w, https://blog.uzimihsr.com/post/2020-05-08-grafana-anonymous-authentication/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;h2 id="参考"&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#snapshot%e3%82%92%e4%bd%bf%e3%81%86" &gt;Snapshotを使う&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://grafana.com/docs/grafana/latest/reference/share_dashboard/" target="_blank" rel="noopener"
 &gt;https://grafana.com/docs/grafana/latest/reference/share_dashboard/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#anonymous-access%e3%82%92%e6%9c%89%e5%8a%b9%e3%81%ab%e3%81%99%e3%82%8b" &gt;anonymous accessを有効にする&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://grafana.com/docs/grafana/latest/auth/overview/#anonymous-authentication" target="_blank" rel="noopener"
 &gt;https://grafana.com/docs/grafana/latest/auth/overview/#anonymous-authentication&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#organization%e3%82%92%e5%88%86%e3%81%91%e3%82%8b" &gt;Organizationを分ける&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://grafana.com/docs/grafana/latest/http_api/org/#create-organization" target="_blank" rel="noopener"
 &gt;https://grafana.com/docs/grafana/latest/http_api/org/#create-organization&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>AngularアプリをnginxとGitHub Pagesでデプロイする</title><link>https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/</link><pubDate>Mon, 04 May 2020 15:43:39 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sotochan.jpg" alt="Featured image of post AngularアプリをnginxとGitHub Pagesでデプロイする" /&gt;&lt;h2 id="成果物をデプロイする"&gt;成果物をデプロイする
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2020-05-03-angular-setup/" target="_blank" rel="noopener"
 &gt;前回&lt;/a&gt;の続き.&lt;br&gt;
Angularの入門をやってみたので, その成果物をデプロイした.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;作成済みの&lt;code&gt;Angular&lt;/code&gt;アプリを持ってきてローカルでビルドした&lt;/li&gt;
&lt;li&gt;ビルドしたアプリを&lt;code&gt;nginx&lt;/code&gt;で公開した&lt;/li&gt;
&lt;li&gt;アプリを&lt;code&gt;GitHub Pages&lt;/code&gt;で公開した&lt;/li&gt;
&lt;li&gt;&lt;code&gt;angular-cli-ghpages&lt;/code&gt;を利用したデプロイを試した&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Mojave 10.14
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2020-05-03-angular-setup/" target="_blank" rel="noopener"
 &gt;環境構築済み&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Angular CLI
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://cli.angular.io/" target="_blank" rel="noopener"
 &gt;https://cli.angular.io/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;バージョン: 9.1.4&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2020-05-03-angular-setup/" target="_blank" rel="noopener"
 &gt;インストール済み&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;nginx
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.nginx.com/" target="_blank" rel="noopener"
 &gt;https://www.nginx.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;nginx/1.17.8&lt;/li&gt;
&lt;li&gt;brewでインストール済み&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;angular-cli-ghpages
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.npmjs.com/package/angular-cli-ghpages" target="_blank" rel="noopener"
 &gt;https://www.npmjs.com/package/angular-cli-ghpages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;version&amp;rdquo;: &amp;ldquo;0.6.2&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;今回入れる&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;GitHubのリポジトリ
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/uzimihsr/angular-first-app" target="_blank" rel="noopener"
 &gt;https://github.com/uzimihsr/angular-first-app&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;今回作成する&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#angular%e3%82%a2%e3%83%97%e3%83%aa%e3%81%ae%e3%83%93%e3%83%ab%e3%83%89" &gt;Angularアプリのビルド&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#nginx%e3%81%a7%e3%83%87%e3%83%97%e3%83%ad%e3%82%a4" &gt;nginxでデプロイ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#github-pages%e3%81%a7%e3%83%87%e3%83%97%e3%83%ad%e3%82%a4" &gt;GitHub Pagesでデプロイ&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e6%89%8b%e5%8b%95%e3%81%a7%e3%82%84%e3%82%8b%e5%a0%b4%e5%90%88" &gt;手動でやる場合&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%91%e3%83%83%e3%82%b1%e3%83%bc%e3%82%b8%e3%82%92%e5%88%a9%e7%94%a8%e3%81%99%e3%82%8b%e5%a0%b4%e5%90%88" &gt;パッケージを利用する場合&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="angularアプリのビルド"&gt;Angularアプリのビルド
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Angular&lt;/code&gt;公式の&lt;a class="link" href="https://angular.jp/start" target="_blank" rel="noopener"
 &gt;入門&lt;/a&gt;で&lt;a class="link" href="https://stackblitz.com/angular/odpeknvxnlq" target="_blank" rel="noopener"
 &gt;StackBlitz&lt;/a&gt;上で作ったアプリがダウンロードできるようになっているので,&lt;br&gt;
これを試しにビルドしてみる.&lt;/p&gt;
&lt;p&gt;サンプルアプリを作ったときと同じように, 新たにワークスペースを作成する.&lt;br&gt;
今回はサンプルアプリは作らず空のワークスペースを作ってみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 空のワークスペースを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; workspace
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ng new --create-application&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt; angular-first-app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls angular-first-app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;README.md angular.json node_modules package-lock.json package.json tsconfig.json tslint.json
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;自分の作った&lt;a class="link" href="https://stackblitz.com/angular/odpeknvxnlq" target="_blank" rel="noopener"
 &gt;StackBlitzプロジェクト&lt;/a&gt;から&lt;code&gt;Download Project&lt;/code&gt;してきた &lt;strong&gt;&amp;lt;プロジェクトID&amp;gt;.angular&lt;/strong&gt; をコピーして,&lt;br&gt;
実際にアプリを立ち上げてみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 入門で作ったプロジェクトをコピー&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; angular-first-app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cp -rf ~/Downloads/&amp;lt;プロジェクトID&amp;gt;.angular/* ./
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# そのまま起動すると依存関係が足りなくて失敗する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ng serve
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;An unhandled exception occurred: Cannot find module &lt;span class="s1"&gt;&amp;#39;@angular-devkit/build-angular/package.json&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Require stack:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;See &lt;span class="s2"&gt;&amp;#34;/private/var/folders/t7/qck11mhn5fj4q6r1mbdf2nxw0000gn/T/ng-D1yxxF/angular-errors.log&amp;#34;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; further details.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# package.jsonに記述された依存パッケージをインストールしてから再度起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ npm install
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ng serve
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;** Angular Live Development Server is listening on localhost:4200, open your browser on http://localhost:4200/ **
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;: Compiled successfully.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 動作確認ができたらCtrl+Cで終了する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ブラウザで &lt;strong&gt;http://localhost:4200/&lt;/strong&gt; を開くと&lt;a class="link" href="https://angular.jp/start" target="_blank" rel="noopener"
 &gt;入門&lt;/a&gt;でつくったものと同じアプリが起動していることが確認できる.&lt;/p&gt;
&lt;p&gt;&lt;img alt="サンプルアプリ" class="gallery-image" data-flex-basis="570px" data-flex-grow="237" height="1211" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc01.png" srcset="https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc01_hu_7eee1c27182545d1.png 800w, https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc01_hu_864c2e7ab3d50404.png 1600w, https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc01_hu_5b406cc746eb5079.png 2400w, https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc01.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;これでアプリの動作確認はできたので, 実際にビルドしてみる.&lt;br&gt;
ビルドが成功すると成果物として &lt;strong&gt;dist&lt;/strong&gt; ディレクトリが作成されていることがわかる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ビルド前の状態&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; angular-first-app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;README.md karma.conf.js package-lock.json src tsconfig.json tslint.json
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;angular.json node_modules package.json tsconfig.app.json tsconfig.spec.json
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# アプリをビルド&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ng build --prod
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Generating ES5 bundles &lt;span class="k"&gt;for&lt;/span&gt; differential loading...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ES5 bundle generation complete.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Date: 2020-05-04T01:48:14.298Z - Hash: 19cf3332dd4d450b70af - Time: 39294ms
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ビルド後&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;README.md dist node_modules package.json tsconfig.app.json tsconfig.spec.json
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;angular.json karma.conf.js package-lock.json src tsconfig.json tslint.json
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls dist
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3rdpartylicenses.txt main-es2015.6d0587fd878af4417329.js polyfills-es5.30e587ebdc07016ad8d1.js styles.c7ea3b8058a0e880ad91.css
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;assets main-es5.6d0587fd878af4417329.js runtime-es2015.1eba213af0b233498d9d.js
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;index.html polyfills-es2015.f8d7ae8b8a28c567fae7.js runtime-es5.1eba213af0b233498d9d.js
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Angular&lt;/code&gt;アプリをデプロイするときはこの &lt;strong&gt;dist/index.html&lt;/strong&gt; をwebサーバーで公開すれば良いらしい.&lt;/p&gt;
&lt;h3 id="nginxでデプロイ"&gt;nginxでデプロイ
&lt;/h3&gt;&lt;p&gt;まずはビルドした成果物を&lt;code&gt;nginx&lt;/code&gt;で公開してみる.&lt;br&gt;
必要な作業は作成された &lt;strong&gt;dist&lt;/strong&gt; ディレクトリをドキュメントルートに設定するだけ. かんたん.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 絶対パスを確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; dist
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;pwd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/path/to/angular-first-app/dist
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# nginx設定ファイルを編集して起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim /usr/local/etc/nginx/nginx.conf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 動作確認が終わったら止める&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ nginx -s stop
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;details&gt;&lt;summary&gt;nginx.conf&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-nginx" data-lang="nginx"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;worker_processes&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;events&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;worker_connections&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;http&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;include&lt;/span&gt; &lt;span class="s"&gt;mime.types&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;default_type&lt;/span&gt; &lt;span class="s"&gt;application/octet-stream&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;sendfile&lt;/span&gt; &lt;span class="no"&gt;on&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;keepalive_timeout&lt;/span&gt; &lt;span class="mi"&gt;65&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;localhost&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Angularアプリのdistディレクトリを指定
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="s"&gt;/path/to/angular-first-app/dist&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;index&lt;/span&gt; &lt;span class="s"&gt;index.html&lt;/span&gt; &lt;span class="s"&gt;index.htm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;error_page&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt; &lt;span class="mi"&gt;502&lt;/span&gt; &lt;span class="mi"&gt;503&lt;/span&gt; &lt;span class="mi"&gt;504&lt;/span&gt; &lt;span class="s"&gt;/50x.html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/50x.html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="s"&gt;html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;include&lt;/span&gt; &lt;span class="s"&gt;servers/*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;&lt;code&gt;nginx&lt;/code&gt;が問題なく動いたらブラウザで &lt;strong&gt;http://localhost:8080/&lt;/strong&gt; を開く.&lt;br&gt;
&lt;code&gt;ng serve&lt;/code&gt;したときと同じアプリが動いていることが確認できる.&lt;/p&gt;
&lt;p&gt;&lt;img alt="サンプルアプリ" class="gallery-image" data-flex-basis="568px" data-flex-grow="236" height="1216" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc02.png" srcset="https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc02_hu_e5a98ca8797d8624.png 800w, https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc02_hu_4165139d45d8149e.png 1600w, https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc02_hu_e493007ea940ddb0.png 2400w, https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc02.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;今回はMacの&lt;code&gt;nginx&lt;/code&gt;だったので手動で止めたけど,&lt;br&gt;
本番環境で&lt;code&gt;nginx&lt;/code&gt;がdaemon化されている場合も同様に&lt;code&gt;nginx.conf&lt;/code&gt;をいじればアプリがデプロイできる. はず.&lt;/p&gt;
&lt;h3 id="github-pagesでデプロイ"&gt;GitHub Pagesでデプロイ
&lt;/h3&gt;&lt;p&gt;自分でwebサーバーを管理するのが面倒な場合は&lt;code&gt;GitHub Pages&lt;/code&gt;を使うこともできる.&lt;br&gt;
デプロイ方法は2通り.&lt;/p&gt;
&lt;h4 id="手動でやる場合"&gt;手動でやる場合
&lt;/h4&gt;&lt;p&gt;まずは&lt;code&gt;GitHub Pages&lt;/code&gt;の公開に必要なリポジトリ(&lt;strong&gt;angular-first-app&lt;/strong&gt;)を&lt;a class="link" href="https://github.com/new" target="_blank" rel="noopener"
 &gt;ここ&lt;/a&gt;から作成する.&lt;br&gt;
&lt;code&gt;Initialize this repository with a README&lt;/code&gt;のチェックは外しておく.&lt;/p&gt;
&lt;p&gt;今回作ったリポジトリ : &lt;a class="link" href="https://github.com/uzimihsr/angular-first-app" target="_blank" rel="noopener"
 &gt;https://github.com/uzimihsr/angular-first-app&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;このリポジトリにpushしたファイルが&lt;code&gt;GitHub Pages&lt;/code&gt;として公開されるので,&lt;br&gt;
&lt;a class="link" href="#angular%e3%82%a2%e3%83%97%e3%83%aa%e3%81%ae%e3%83%93%e3%83%ab%e3%83%89" &gt;Angularアプリのビルド&lt;/a&gt;で作成したディレクトリ(&lt;strong&gt;angular-first-app&lt;/strong&gt;)をこのリポジトリに紐付ける.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ng new した時点で.gitが作成されているのでinitはたぶん不要&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; angular-first-app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls -a
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;. .editorconfig .gitignore angular.json karma.conf.js package-lock.json src tsconfig.json tslint.json
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.. .git README.md dist node_modules package.json tsconfig.app.json tsconfig.spec.json
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# リポジトリを紐付けて確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git remote add origin https://github.com/uzimihsr/angular-first-app.git
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git remote -v
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;origin	https://github.com/uzimihsr/angular-first-app.git &lt;span class="o"&gt;(&lt;/span&gt;fetch&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;origin	https://github.com/uzimihsr/angular-first-app.git &lt;span class="o"&gt;(&lt;/span&gt;push&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 一旦commitしておく&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git add .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git commit -m &lt;span class="s2"&gt;&amp;#34;initial commit&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この状態で&lt;code&gt;Angular&lt;/code&gt;アプリを&lt;code&gt;GitHub Pages&lt;/code&gt;用にビルドする.&lt;br&gt;
今回は&lt;code&gt;--output-path&lt;/code&gt;オプションを指定しているのでビルドした成果物が &lt;strong&gt;dist&lt;/strong&gt; ではなく別のディレクトリ &lt;strong&gt;docs&lt;/strong&gt; に作成される.&lt;br&gt;
また, &lt;strong&gt;https://[GitHubアカウント].github.io/[リポジトリ名]/&lt;/strong&gt; でアプリにアクセスできるように&lt;code&gt;--base-href&lt;/code&gt;オプションもつけている.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ビルド前の状態&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;README.md dist node_modules package.json tsconfig.app.json tsconfig.spec.json
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;angular.json karma.conf.js package-lock.json src tsconfig.json tslint.json
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 成果物の出力先とアクセスされるときのパスを指定してビルド&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ng build --prod --output-path docs --base-href /angular-first-app/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Generating ES5 bundles &lt;span class="k"&gt;for&lt;/span&gt; differential loading...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ES5 bundle generation complete.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Date: 2020-05-04T05:50:14.401Z - Hash: 19cf3332dd4d450b70af - Time: 19395ms
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ビルド後の状態&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;README.md dist karma.conf.js package-lock.json src tsconfig.json tslint.json
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;angular.json docs node_modules package.json tsconfig.app.json tsconfig.spec.json
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# GitHub Pages用に404ページを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cp docs/index.html docs/404.html
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここまでできたら, すべての変更を&lt;code&gt;GitHub&lt;/code&gt;のリポジトリに反映する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# すべての変更をcommitしてpush&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git add .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git commit -m &lt;span class="s2"&gt;&amp;#34;build&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git push origin master
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;問題なくpushできたので次に&lt;code&gt;GitHub Pages&lt;/code&gt;の設定を行う.&lt;/p&gt;
&lt;p&gt;ブラウザで&lt;a class="link" href="https://github.com/uzimihsr/angular-first-app/settings" target="_blank" rel="noopener"
 &gt;リポジトリのsettings&lt;/a&gt;を開く.&lt;br&gt;
&lt;code&gt;GitHub Pages&lt;/code&gt;の設定で&lt;code&gt;Source&lt;/code&gt;を&lt;code&gt;master branch /docs folder&lt;/code&gt;に変更する.&lt;br&gt;
これにより &lt;strong&gt;docs&lt;/strong&gt; の内容が&lt;code&gt;GitHub Pages&lt;/code&gt;として公開される.&lt;/p&gt;
&lt;p&gt;&lt;img alt="GitHub Pagesの設定" class="gallery-image" data-flex-basis="388px" data-flex-grow="161" height="926" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc03.png" srcset="https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc03_hu_57f4350b6bd12281.png 800w, https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc03.png 1498w" width="1498"&gt;&lt;/p&gt;
&lt;p&gt;設定反映後以下のようになっていればOK.&lt;/p&gt;
&lt;p&gt;&lt;img alt="GitHub Pagesの設定" class="gallery-image" data-flex-basis="275px" data-flex-grow="114" height="1307" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc04.png" srcset="https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc04_hu_a3c2ee3cf152bca2.png 800w, https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc04.png 1500w" width="1500"&gt;&lt;/p&gt;
&lt;p&gt;ブラウザで &lt;strong&gt;&lt;a class="link" href="https://uzimihsr.github.io/angular-first-app/" target="_blank" rel="noopener"
 &gt;https://uzimihsr.github.io/angular-first-app/&lt;/a&gt;&lt;/strong&gt; を開くと,&lt;br&gt;
&lt;code&gt;ng serve&lt;/code&gt;したときや&lt;code&gt;nginx&lt;/code&gt;でデプロイしたときと同じアプリが&lt;code&gt;GitHub Pages&lt;/code&gt;で公開されているのが確認できる.&lt;/p&gt;
&lt;p&gt;&lt;img alt="GitHub Pages" class="gallery-image" data-flex-basis="592px" data-flex-grow="246" height="1166" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc05.png" srcset="https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc05_hu_73dc759883e41d77.png 800w, https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc05_hu_8ca6e6315140f4d3.png 1600w, https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc05_hu_45d99aef0e764d97.png 2400w, https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc05.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;h4 id="パッケージを利用する場合"&gt;パッケージを利用する場合
&lt;/h4&gt;&lt;p&gt;&lt;a class="link" href="https://www.npmjs.com/package/angular-cli-ghpages" target="_blank" rel="noopener"
 &gt;angular-cli-ghpages&lt;/a&gt;を使うことで,&lt;br&gt;
&lt;a class="link" href="#%e6%89%8b%e5%8b%95%e3%81%a7%e3%82%84%e3%82%8b%e5%a0%b4%e5%90%88" &gt;手動でやる場合&lt;/a&gt;よりも簡単にデプロイできる.&lt;/p&gt;
&lt;p&gt;最初に1回手動でデプロイしたあとはこっちの方法でデプロイするのがよさそうなので,&lt;br&gt;
&lt;a class="link" href="#%e6%89%8b%e5%8b%95%e3%81%a7%e3%82%84%e3%82%8b%e5%a0%b4%e5%90%88" &gt;手動でやる場合&lt;/a&gt;で作成したリポジトリをそのまま利用する.&lt;/p&gt;
&lt;p&gt;やることとしては&lt;code&gt;GitHub Pages&lt;/code&gt;にデプロイする用のパッケージ&lt;code&gt;angular-cli-ghpages&lt;/code&gt;を追加して,&lt;br&gt;
&lt;code&gt;ng deploy&lt;/code&gt;するだけ. かんたん.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# リモートリポジトリの確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; angular-first-app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git remote -v
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;origin	https://github.com/uzimihsr/angular-first-app.git &lt;span class="o"&gt;(&lt;/span&gt;fetch&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;origin	https://github.com/uzimihsr/angular-first-app.git &lt;span class="o"&gt;(&lt;/span&gt;push&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# パッケージを追加&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ng add angular-cli-ghpages
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Installing packages &lt;span class="k"&gt;for&lt;/span&gt; tooling via npm.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Installed packages &lt;span class="k"&gt;for&lt;/span&gt; tooling via npm.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;UPDATE angular.json &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3753&lt;/span&gt; bytes&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# デプロイ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ng deploy --base-href&lt;span class="o"&gt;=&lt;/span&gt;/angular-first-app/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;📦 Building &lt;span class="s2"&gt;&amp;#34;angular.io-example&amp;#34;&lt;/span&gt;. Configuration: &lt;span class="s2"&gt;&amp;#34;production&amp;#34;&lt;/span&gt;. Your base-href: &lt;span class="s2"&gt;&amp;#34;/angular-first-app/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Generating ES5 bundles &lt;span class="k"&gt;for&lt;/span&gt; differential loading...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ES5 bundle generation complete.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Date: 2020-05-04T06:45:54.460Z - Hash: 19cf3332dd4d450b70af - Time: 20338ms
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;👨‍🚀 Uploading via git, please wait...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🚀 Successfully published via angular-cli-ghpages! Have a nice day!
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# リモートリポジトリにmasterブランチの他にgh-pagesブランチが作成されている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git branch -a
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* master
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; remotes/origin/gh-pages
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; remotes/origin/master
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;ng deploy&lt;/code&gt;が成功するとリポジトリに新しく &lt;strong&gt;gh-pages&lt;/strong&gt; ブランチが作成されている.&lt;br&gt;
&lt;a class="link" href="https://github.com/uzimihsr/angular-first-app/tree/gh-pages" target="_blank" rel="noopener"
 &gt;https://github.com/uzimihsr/angular-first-app/tree/gh-pages&lt;/a&gt;&lt;br&gt;
中身を見ればなんとなくわかるが, &lt;a class="link" href="#%e6%89%8b%e5%8b%95%e3%81%a7%e3%82%84%e3%82%8b%e5%a0%b4%e5%90%88" &gt;手動でやる場合&lt;/a&gt;でビルドした &lt;strong&gt;docs&lt;/strong&gt; の中身と同じものがブランチの直下に作成されている.&lt;br&gt;
commitとpushも自動でやってくれてるっぽい.&lt;/p&gt;
&lt;p&gt;&lt;img alt="gh-pagesブランチ" class="gallery-image" data-flex-basis="423px" data-flex-grow="176" height="1631" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc06.png" srcset="https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc06_hu_35b616402cdbe66c.png 800w, https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc06_hu_6cb43a21d9df7c1e.png 1600w, https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc06_hu_c511a5b5e2cd1ef1.png 2400w, https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc06.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;この &lt;strong&gt;gh-pages&lt;/strong&gt; ブランチを&lt;code&gt;GitHub Pages&lt;/code&gt;として公開するために再度設定を行う.&lt;/p&gt;
&lt;p&gt;ブラウザで&lt;a class="link" href="https://github.com/uzimihsr/angular-first-app/settings" target="_blank" rel="noopener"
 &gt;リポジトリのsettings&lt;/a&gt;を開く.&lt;br&gt;
&lt;code&gt;GitHub Pages&lt;/code&gt;の設定で&lt;code&gt;Source&lt;/code&gt;を&lt;code&gt;gh-pages branch&lt;/code&gt;に変更する.&lt;/p&gt;
&lt;p&gt;&lt;img alt="GitHub Pagesの設定" class="gallery-image" data-flex-basis="272px" data-flex-grow="113" height="1309" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc07.png" srcset="https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc07_hu_c7d6842275bd2729.png 800w, https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc07.png 1487w" width="1487"&gt;&lt;/p&gt;
&lt;p&gt;設定反映後以下のようになっていればOK.&lt;/p&gt;
&lt;p&gt;&lt;img alt="GitHub Pagesの設定" class="gallery-image" data-flex-basis="272px" data-flex-grow="113" height="1311" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc08.png" srcset="https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc08_hu_7a9da4cd13bb3e4b.png 800w, https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc08.png 1486w" width="1486"&gt;&lt;/p&gt;
&lt;p&gt;再度ブラウザで &lt;strong&gt;&lt;a class="link" href="https://uzimihsr.github.io/angular-first-app/" target="_blank" rel="noopener"
 &gt;https://uzimihsr.github.io/angular-first-app/&lt;/a&gt;&lt;/strong&gt; を開くと,&lt;br&gt;
これまでと同じアプリが&lt;code&gt;GitHub Pages&lt;/code&gt;で公開されているのが確認できる.&lt;/p&gt;
&lt;p&gt;&lt;img alt="GitHub Pages" class="gallery-image" data-flex-basis="592px" data-flex-grow="246" height="1166" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc05.png" srcset="https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc05_hu_73dc759883e41d77.png 800w, https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc05_hu_8ca6e6315140f4d3.png 1600w, https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc05_hu_45d99aef0e764d97.png 2400w, https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sc05.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;これで&lt;code&gt;GitHub Pages&lt;/code&gt;へのデプロイが簡単になった.&lt;br&gt;
やったぜ.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;以上の手順で&lt;code&gt;Angular&lt;/code&gt;のアプリを&lt;code&gt;nginx&lt;/code&gt;や&lt;code&gt;GitHub Pages&lt;/code&gt;に公開することができた.&lt;/p&gt;
&lt;p&gt;基本的にはローカルでつくったものを&lt;code&gt;ng serve&lt;/code&gt;で動作確認して,&lt;br&gt;
問題なければ&lt;code&gt;ng deploy&lt;/code&gt;で&lt;code&gt;GitHub Pages&lt;/code&gt;にデプロイ,&lt;br&gt;
もしくは&lt;code&gt;ng build&lt;/code&gt;でビルドしたものを本番環境(&lt;code&gt;nginx&lt;/code&gt;)にデプロイするという流れで開発ができそう.&lt;/p&gt;
&lt;p&gt;これで一通り開発のやり方もわかったのでフロントエンド開発をがんばっていきたい.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="寝てる間におもちゃを積まれてうざそうなねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sotochan_hu_ce60a56fd4c5a28f.jpg 800w, https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sotochan_hu_4a1412d8e61c1258.jpg 1600w, https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sotochan_hu_7de40d3d75ae8070.jpg 2400w, https://blog.uzimihsr.com/post/2020-05-04-angular-deploy-fix/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;h2 id="参考"&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Angularアプリのビルド
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://angular.jp/start/start-deployment" target="_blank" rel="noopener"
 &gt;https://angular.jp/start/start-deployment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://angular.jp/guide/build" target="_blank" rel="noopener"
 &gt;https://angular.jp/guide/build&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;nginxでデプロイ
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://nginx.org/en/docs/beginners_guide.html#static" target="_blank" rel="noopener"
 &gt;http://nginx.org/en/docs/beginners_guide.html#static&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;GitHub Pagesにデプロイ
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://angular.jp/guide/deployment#deploy-to-github-pages" target="_blank" rel="noopener"
 &gt;https://angular.jp/guide/deployment#deploy-to-github-pages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://help.github.com/en/github/working-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site" target="_blank" rel="noopener"
 &gt;https://help.github.com/en/github/working-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.npmjs.com/package/angular-cli-ghpages#-quick-start-local-development" target="_blank" rel="noopener"
 &gt;https://www.npmjs.com/package/angular-cli-ghpages#-quick-start-local-development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.npmjs.com/package/angular-cli-ghpages#--base-href" target="_blank" rel="noopener"
 &gt;https://www.npmjs.com/package/angular-cli-ghpages#--base-href&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>MacでAngularの開発環境構築</title><link>https://blog.uzimihsr.com/post/2020-05-03-angular-setup/</link><pubDate>Sun, 03 May 2020 18:43:39 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-05-03-angular-setup/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-05-03-angular-setup/sotochan.jpg" alt="Featured image of post MacでAngularの開発環境構築" /&gt;&lt;h2 id="フロントエンド開発したい"&gt;フロントエンド開発したい
&lt;/h2&gt;&lt;p&gt;GWだけど特に遊ぶ予定もないので普段あまりやらないフロントエンドの開発をやってみようと思った.&lt;br&gt;
まずは環境構築からやってみた.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;anyenv&lt;/code&gt;と&lt;code&gt;nodenv&lt;/code&gt;で&lt;code&gt;Node.js&lt;/code&gt;の環境構築をした&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Angular CLI&lt;/code&gt;をインストールした&lt;/li&gt;
&lt;li&gt;&lt;code&gt;VSCode&lt;/code&gt;をインストールして&lt;code&gt;Extension&lt;/code&gt;を入れた&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;macOS Mojave 10.14&lt;/li&gt;
&lt;li&gt;anyenv
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/anyenv/anyenv" target="_blank" rel="noopener"
 &gt;https://github.com/anyenv/anyenv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;anyenv 1.1.1&lt;/li&gt;
&lt;li&gt;インストール済み&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;nodenv
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/nodenv/nodenv" target="_blank" rel="noopener"
 &gt;https://github.com/nodenv/nodenv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;nodenv 1.3.2+2.2578d8d&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;今回入れる&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Angular CLI
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://cli.angular.io/" target="_blank" rel="noopener"
 &gt;https://cli.angular.io/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;バージョン: 9.1.4&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;今回入れる&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Visual Studio Code
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://code.visualstudio.com/" target="_blank" rel="noopener"
 &gt;https://code.visualstudio.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Version: 1.44.2&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;今回入れる&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#nodejs%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" &gt;Node.jsのインストール&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#angular-cli%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" &gt;Angular CLIのインストール&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#vscode%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" &gt;VSCodeのインストール&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="nodejsのインストール"&gt;Node.jsのインストール
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;nodenv&lt;/code&gt;は&lt;code&gt;Node.js&lt;/code&gt;のバージョン管理をやってくれるやつ.&lt;br&gt;
これがなくても困らないけど, 入れておくとバージョン更新でトラブったときとかに多分便利.&lt;/p&gt;
&lt;p&gt;まずは&lt;code&gt;anyenv&lt;/code&gt;で&lt;code&gt;nodenv&lt;/code&gt;をインストールしてみる.&lt;br&gt;
めちゃくちゃかんたん. &lt;code&gt;anyenv&lt;/code&gt;神.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# anyenvでインストールできる**envの確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ anyenv install -l &lt;span class="p"&gt;|&lt;/span&gt; grep nodenv
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; nodenv
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# nodenvのインストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ anyenv install nodenv
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Install nodenv succeeded!
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Please reload your profile &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nv"&gt;$SHELL&lt;/span&gt; -l&lt;span class="o"&gt;)&lt;/span&gt; or open a new session.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nv"&gt;$SHELL&lt;/span&gt; -l
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 動作確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ nodenv
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nodenv 1.3.2+2.2578d8d
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Usage: nodenv &amp;lt;command&amp;gt; &lt;span class="o"&gt;[&lt;/span&gt;&amp;lt;args&amp;gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Some useful nodenv commands are:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; commands List all available nodenv commands
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; Set or show the &lt;span class="nb"&gt;local&lt;/span&gt; application-specific Node version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; global Set or show the global Node version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; shell Set or show the shell-specific Node version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; install Install a Node version using node-build
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; uninstall Uninstall a specific Node version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; rehash Rehash nodenv shims &lt;span class="o"&gt;(&lt;/span&gt;run this after installing executables&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; version Show the current Node version and its origin
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; versions List installed Node versions
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; which Display the full path to an executable
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; whence List all Node versions that contain the given executable
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;See &lt;span class="s1"&gt;&amp;#39;nodenv help &amp;lt;command&amp;gt;&amp;#39;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; information on a specific command.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;For full documentation, see: https://github.com/nodenv/nodenv#readme
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;nodenv&lt;/code&gt;がインストールできたので, 今度はこれを使って&lt;code&gt;Node.js&lt;/code&gt;をインストールする.&lt;br&gt;
&lt;code&gt;Node.js&lt;/code&gt;はとんでもない数のバージョンがあるんだけど,&lt;br&gt;
初心者でよくわかんないので&lt;a class="link" href="https://nodejs.org/ja/" target="_blank" rel="noopener"
 &gt;公式&lt;/a&gt;で現在(2020年5月4日)推奨版とされている &lt;strong&gt;12.16.3&lt;/strong&gt; を入れる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# nodenvでインストール可能できるバージョンの一覧を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ nodenv install -l &lt;span class="p"&gt;|&lt;/span&gt; grep -e &lt;span class="s2"&gt;&amp;#34;^12.*&lt;/span&gt;$&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;12.0.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;12.x-dev
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;12.x-next
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;12.1.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;12.2.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;12.3.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;12.3.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;12.4.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;12.5.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;12.6.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;12.7.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;12.8.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;12.8.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;12.9.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;12.9.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;12.10.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;12.11.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;12.11.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;12.12.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;12.13.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;12.13.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;12.14.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;12.14.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;12.15.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;12.16.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;12.16.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;12.16.2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;12.16.3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Node.js 12.16.3をインストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ nodenv install 12.16.3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nodenv: default-packages file not found
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# なんか怒られたので対処する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# nodenv installしたときに自動で入れるパッケージを指定するファイルが必要らしいので空ファイルを作る&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ touch &lt;span class="k"&gt;$(&lt;/span&gt;nodenv root&lt;span class="k"&gt;)&lt;/span&gt;/default-packages
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 再度インストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ nodenv install 12.16.3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Installed node-v12.16.3-darwin-x64 to /Users/uzimihsr/.anyenv/envs/nodenv/versions/12.16.3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Installed default packages &lt;span class="k"&gt;for&lt;/span&gt; 12.16.3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# インストール済みのバージョンを確認し使用するバージョンを指定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ nodenv versions
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 12.16.3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ nodenv global 12.16.3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ nodenv versions
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 12.16.3 &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; by /Users/uzimihsr/.anyenv/envs/nodenv/version&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 動作確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nv"&gt;$SHELL&lt;/span&gt; -l
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ node -v
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;v12.16.3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ npm -v
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;6.14.4
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以上で&lt;code&gt;Node.js&lt;/code&gt;のインストールは完了.&lt;br&gt;
めっちゃ簡単だった. &lt;code&gt;nodenv&lt;/code&gt;も神.&lt;/p&gt;
&lt;p&gt;ついでに入ってる&lt;code&gt;npm&lt;/code&gt;は&lt;code&gt;Node.js&lt;/code&gt;のパッケージ管理ツールで,&lt;br&gt;
&lt;code&gt;python&lt;/code&gt;でいう&lt;code&gt;pip&lt;/code&gt;みたいなやつ.&lt;br&gt;
(そういえば最近全然&lt;code&gt;python&lt;/code&gt;触ってないな&amp;hellip;)&lt;/p&gt;
&lt;h3 id="angular-cliのインストール"&gt;Angular CLIのインストール
&lt;/h3&gt;&lt;p&gt;続いて&lt;code&gt;Angular&lt;/code&gt;の開発をするために&lt;code&gt;npm&lt;/code&gt;を使ってCLIをインストールする.&lt;br&gt;
無くても開発はできるみたいだけど, 入れない理由はない.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Angular CLIのインストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ npm install -g @angular/cli
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/Users/uzimihsr/.anyenv/envs/nodenv/versions/12.16.3/bin/ng -&amp;gt; /Users/uzimihsr/.anyenv/envs/nodenv/versions/12.16.3/lib/node_modules/@angular/cli/bin/ng
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; @angular/cli@9.1.4 postinstall /Users/uzimihsr/.anyenv/envs/nodenv/versions/12.16.3/lib/node_modules/@angular/cli
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; node ./bin/postinstall/script.js
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;+ @angular/cli@9.1.4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;added &lt;span class="m"&gt;271&lt;/span&gt; packages from &lt;span class="m"&gt;206&lt;/span&gt; contributors in 24.329s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 動作確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nv"&gt;$SHELL&lt;/span&gt; -l
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ng version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Angular CLI: 9.1.4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node: 12.16.3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;OS: darwin x64
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Angular:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Ivy Workspace:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Package Version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;@angular-devkit/architect 0.901.4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;@angular-devkit/core 9.1.4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;@angular-devkit/schematics 9.1.4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;@schematics/angular 9.1.4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;@schematics/update 0.901.4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rxjs 6.5.4
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;CLIがインストールできたので, 実際に&lt;code&gt;Angular&lt;/code&gt;アプリを動かしてみる.&lt;br&gt;
CLIは&lt;code&gt;ng&lt;/code&gt;で呼び出せる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 適当なディレクトリで作業&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; workspace
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 新規ワークスペースとサンプルアプリを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# パッケージをいくつか入れるので時間がかかる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ng new my-app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;? Would you like to add Angular routing? Yes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;? Which stylesheet format would you like to use? CSS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;CREATE my-app/README.md &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1022&lt;/span&gt; bytes&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;✔ Packages installed successfully.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Successfully initialized git.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 作成されたディレクトリでアプリを起動する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; my-app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ng serve
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;** Angular Live Development Server is listening on localhost:4200, open your browser on http://localhost:4200/ **
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;: Compiled successfully.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 動作確認が終わったらCtrl+Cで終了&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ブラウザで &lt;strong&gt;http://localhost:4200/&lt;/strong&gt; を開く.&lt;br&gt;
サンプルアプリが起動していることが確認できる.&lt;/p&gt;
&lt;p&gt;&lt;img alt="サンプルアプリ" class="gallery-image" data-flex-basis="384px" data-flex-grow="160" height="1800" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-03-angular-setup/sc01.png" srcset="https://blog.uzimihsr.com/post/2020-05-03-angular-setup/sc01_hu_92f9e28f337bbed8.png 800w, https://blog.uzimihsr.com/post/2020-05-03-angular-setup/sc01_hu_89b227ef9d852d10.png 1600w, https://blog.uzimihsr.com/post/2020-05-03-angular-setup/sc01_hu_a2cc4cf6320dc914.png 2400w, https://blog.uzimihsr.com/post/2020-05-03-angular-setup/sc01.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;これで&lt;code&gt;Angular&lt;/code&gt;のアプリを動かせるようになった.&lt;br&gt;
やったぜ.&lt;/p&gt;
&lt;h3 id="vscodeのインストール"&gt;VSCodeのインストール
&lt;/h3&gt;&lt;p&gt;普段開発用のエディタは&lt;a class="link" href="https://atom.io/" target="_blank" rel="noopener"
 &gt;Atom&lt;/a&gt;を使ってるんだけど,&lt;br&gt;
&lt;code&gt;Angular&lt;/code&gt;向けの良いパッケージが見つからなかったので&lt;a class="link" href="https://code.visualstudio.com/" target="_blank" rel="noopener"
 &gt;Visual Studio Code&lt;/a&gt;(&lt;code&gt;VSCode&lt;/code&gt;)を使ってみる.&lt;/p&gt;
&lt;p&gt;ホントは&lt;code&gt;Atom&lt;/code&gt;で頑張りたかったんだけど&lt;br&gt;
&lt;a class="link" href="https://angular.io/resources?category=development" target="_blank" rel="noopener"
 &gt;公式のIDEリスト&lt;/a&gt;でも推奨されてるし,&lt;br&gt;
チュートリアルとかで使ってる&lt;a class="link" href="https://stackblitz.com/" target="_blank" rel="noopener"
 &gt;StackBlitz&lt;/a&gt;も&lt;code&gt;VSCode&lt;/code&gt;っぽいIDEなので逆らえなかった.&lt;/p&gt;
&lt;p&gt;普通に&lt;a class="link" href="https://code.visualstudio.com/Download" target="_blank" rel="noopener"
 &gt;公式のダウンロードページ&lt;/a&gt;から落としてくる.&lt;br&gt;
勝手に展開されるので, &lt;strong&gt;Visual Studio Code.app&lt;/strong&gt; を &lt;strong&gt;/Applications&lt;/strong&gt; に移動する.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Applications" class="gallery-image" data-flex-basis="260px" data-flex-grow="108" height="1232" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-03-angular-setup/sc02.png" srcset="https://blog.uzimihsr.com/post/2020-05-03-angular-setup/sc02_hu_894493628b6a3dfc.png 800w, https://blog.uzimihsr.com/post/2020-05-03-angular-setup/sc02.png 1338w" width="1338"&gt;&lt;/p&gt;
&lt;p&gt;とは言っても毎回アプリを探して起動するのは不便なので&lt;code&gt;PATH&lt;/code&gt;を通してコマンドラインから起動できるようにする.&lt;br&gt;
実際に起動し, &lt;code&gt;F1&lt;/code&gt;でコマンドパレットを開き&lt;code&gt;Install 'code' command in PATH&lt;/code&gt;を選択する.&lt;/p&gt;
&lt;p&gt;&lt;img alt="コマンドパレット" class="gallery-image" data-flex-basis="309px" data-flex-grow="129" height="1760" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-03-angular-setup/sc03.png" srcset="https://blog.uzimihsr.com/post/2020-05-03-angular-setup/sc03_hu_23459690bbfc6390.png 800w, https://blog.uzimihsr.com/post/2020-05-03-angular-setup/sc03_hu_1de96f73ea3be98.png 1600w, https://blog.uzimihsr.com/post/2020-05-03-angular-setup/sc03.png 2272w" width="2272"&gt;&lt;/p&gt;
&lt;p&gt;画面右下に&lt;code&gt;Shell command 'code' successfully installed in PATH.&lt;/code&gt;と表示されれば設定は完了.&lt;/p&gt;
&lt;p&gt;試しに先程作成したワークスペースをコマンドラインから開いてみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; my-app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# VSCodeでカレントディレクトリを開く&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ code .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img alt="VSCode" class="gallery-image" data-flex-basis="309px" data-flex-grow="129" height="1760" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-03-angular-setup/sc04.png" srcset="https://blog.uzimihsr.com/post/2020-05-03-angular-setup/sc04_hu_395c711c7720c5a9.png 800w, https://blog.uzimihsr.com/post/2020-05-03-angular-setup/sc04_hu_c8eef806a52fe0e3.png 1600w, https://blog.uzimihsr.com/post/2020-05-03-angular-setup/sc04.png 2272w" width="2272"&gt;&lt;/p&gt;
&lt;p&gt;さらに&lt;code&gt;Angular&lt;/code&gt;を扱いやすくするために&lt;a class="link" href="https://marketplace.visualstudio.com/items?itemName=Angular.ng-template" target="_blank" rel="noopener"
 &gt;公式のExtension&lt;/a&gt;を入れておく.&lt;br&gt;
&lt;code&gt;Atom&lt;/code&gt;でいうパッケージみたいな拡張機能を&lt;code&gt;VSCode&lt;/code&gt;では&lt;code&gt;Extension&lt;/code&gt;と呼ぶらしい.&lt;br&gt;
メニューから検索すればすぐ見つかるので&lt;code&gt;Install&lt;/code&gt;を押せば入る.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Extension" class="gallery-image" data-flex-basis="309px" data-flex-grow="129" height="1760" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-03-angular-setup/sc05.png" srcset="https://blog.uzimihsr.com/post/2020-05-03-angular-setup/sc05_hu_47462438e555b229.png 800w, https://blog.uzimihsr.com/post/2020-05-03-angular-setup/sc05_hu_92449f6578b0d311.png 1600w, https://blog.uzimihsr.com/post/2020-05-03-angular-setup/sc05.png 2272w" width="2272"&gt;&lt;/p&gt;
&lt;p&gt;これでエディタのセットアップも完了.&lt;br&gt;
やったぜ.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;以上の手順でMacに&lt;code&gt;Angular&lt;/code&gt;アプリの開発環境をつくることができた.&lt;br&gt;
フロントエンド初心者だけどちょっとずつ頑張っていきたい.&lt;br&gt;
実際の成果物をデプロイする手順は長くなりそうなので&lt;a class="link" href="https://uzimihsr.github.io/post/2020-05-04-angular-deploy-fix/" target="_blank" rel="noopener"
 &gt;別の記事&lt;/a&gt;に書く.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="紙袋だいすきねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-05-03-angular-setup/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-05-03-angular-setup/sotochan_hu_a5ed06e734e1229f.jpg 800w, https://blog.uzimihsr.com/post/2020-05-03-angular-setup/sotochan_hu_5e3e487a24f2f29a.jpg 1600w, https://blog.uzimihsr.com/post/2020-05-03-angular-setup/sotochan_hu_269367eb4c67ba5e.jpg 2400w, https://blog.uzimihsr.com/post/2020-05-03-angular-setup/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;h2 id="参考"&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Node.jsのインストール
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/nodenv/nodenv/blob/master/README.md#installing-node-versions" target="_blank" rel="noopener"
 &gt;https://github.com/nodenv/nodenv/blob/master/README.md#installing-node-versions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Angular CLIのインストール
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://angular.jp/cli" target="_blank" rel="noopener"
 &gt;https://angular.jp/cli&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://angular.jp/start/start-deployment" target="_blank" rel="noopener"
 &gt;https://angular.jp/start/start-deployment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://angular.jp/guide/setup-local" target="_blank" rel="noopener"
 &gt;https://angular.jp/guide/setup-local&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;VSCodeのインストール
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://code.visualstudio.com/docs/setup/mac#_launching-from-the-command-line" target="_blank" rel="noopener"
 &gt;https://code.visualstudio.com/docs/setup/mac#_launching-from-the-command-line&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>PushgatewayでCronJobの監視を行う</title><link>https://blog.uzimihsr.com/post/2020-04-30-pushgateway/</link><pubDate>Thu, 30 Apr 2020 21:40:42 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-04-30-pushgateway/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sotochan.jpg" alt="Featured image of post PushgatewayでCronJobの監視を行う" /&gt;&lt;h2 id="ジョブの監視"&gt;ジョブの監視
&lt;/h2&gt;&lt;p&gt;Pushgatewayを使った監視をやってみた.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;ラズパイに&lt;code&gt;Pushgateway&lt;/code&gt;をインストールした&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Kubernetes&lt;/code&gt;の&lt;code&gt;CronJob&lt;/code&gt;からメトリクスをPushしてみた&lt;/li&gt;
&lt;li&gt;簡単な監視ルールを設定した&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Raspberry Pi 3 Model B+
&lt;ul&gt;
&lt;li&gt;OSはRaspbian(10.0)&lt;/li&gt;
&lt;li&gt;監視サーバとして使用&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Prometheus
&lt;ul&gt;
&lt;li&gt;version=&amp;ldquo;2.15.2&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2020-01-15-prometheus-grafana-raspberry-pi/" target="_blank" rel="noopener"
 &gt;インストール済み&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Pushgateway
&lt;ul&gt;
&lt;li&gt;version=&amp;ldquo;1.2.0&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;今回入れる&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;macOS Mojave 10.14
&lt;ul&gt;
&lt;li&gt;Go, Docker, Kubernetesはこちらで実行&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Go(golang)
&lt;ul&gt;
&lt;li&gt;go version go1.13&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Docker
&lt;ul&gt;
&lt;li&gt;Version: 19.03.2&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Kubernetesクラスタ(Minikube)
&lt;ul&gt;
&lt;li&gt;GitVersion:&amp;ldquo;v1.16.2&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2019-10-28-hello-minikube/" target="_blank" rel="noopener"
 &gt;MacBook上で構築&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="構成"&gt;構成
&lt;/h2&gt;&lt;p&gt;&lt;img alt="component" class="gallery-image" data-flex-basis="803px" data-flex-grow="334" height="649" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-component.png" srcset="https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-component_hu_c21a3b6e005a6bd.png 800w, https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-component_hu_d327ad2f61f942e9.png 1600w, https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-component.png 2173w" width="2173"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/prometheus/pushgateway" target="_blank" rel="noopener"
 &gt;Pushgateway&lt;/a&gt;とは&amp;hellip;&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&amp;ldquo;The Pushgateway is an intermediary service which allows you to push metrics from jobs which cannot be scraped.&amp;rdquo;&lt;br&gt;
&amp;ldquo;Pushgatewayとは, スクレイプが不可能なジョブのメトリクスをプッシュするための仲介サービスです.&amp;rdquo;&lt;br&gt;
(&lt;a class="link" href="https://prometheus.io/docs/practices/pushing/" target="_blank" rel="noopener"
 &gt;https://prometheus.io/docs/practices/pushing/&lt;/a&gt; より超意訳)&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;&lt;code&gt;Node exporter&lt;/code&gt;みたいなExporterは監視対象が動いてる間メトリクスを吐き出しつづけるから&lt;code&gt;Prometheus&lt;/code&gt;で定期的にスクレイプ(pull)できるけど,&lt;/p&gt;
&lt;p&gt;バッチジョブみたいに動いている間しか情報を持たないものは&lt;code&gt;Prometheus&lt;/code&gt;からスクレイプできず, 通常の方法では監視ができない.&lt;/p&gt;
&lt;p&gt;これを解決するため, &lt;code&gt;Pushgateway&lt;/code&gt;を使ってジョブからのメトリクスのpushを受け付けて永続化し, &lt;code&gt;Prometheus&lt;/code&gt;でこのメトリクスをpullすることでジョブの監視を行う.&lt;/p&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#pushgateway%e3%81%ae%e3%82%bb%e3%83%83%e3%83%88%e3%82%a2%e3%83%83%e3%83%97" &gt;Pushgatewayのセットアップ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%a1%e3%83%88%e3%83%aa%e3%82%af%e3%82%b9%e3%81%aepush%e3%81%a8prometheus%e3%81%ab%e3%82%88%e3%82%8b%e3%82%b9%e3%82%af%e3%83%ac%e3%82%a4%e3%83%97" &gt;メトリクスのpushとPrometheusによるスクレイプ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#cronjob%e3%81%ae%e7%9b%a3%e8%a6%96" &gt;CronJobの監視&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="pushgatewayのセットアップ"&gt;Pushgatewayのセットアップ
&lt;/h3&gt;&lt;p&gt;まずはラズパイに&lt;code&gt;Pushgateway&lt;/code&gt;をインストールしていく.&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://prometheus.io/download/#pushgateway" target="_blank" rel="noopener"
 &gt;ダウンロードページ&lt;/a&gt;で&lt;code&gt;Architecture&lt;/code&gt;を&lt;code&gt;armv7&lt;/code&gt;にした状態で&lt;br&gt;
&lt;strong&gt;pushgateway-1.2.0.linux-armv7.tar.gz&lt;/strong&gt; のダウンロードリンクを確認する.&lt;/p&gt;
&lt;p&gt;ラズパイにSSHしてダウンロード, インストール, 起動までやってみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 以下はRaspberry Piで実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 任意のディレクトリで作業&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; workspace
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 確認したURLからダウンロードして展開, 移動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ wget https://github.com/prometheus/pushgateway/releases/download/v1.2.0/pushgateway-1.2.0.linux-armv7.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ tar -xzf pushgateway-1.2.0.linux-armv7.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo cp pushgateway-1.2.0.linux-armv7/pushgateway /usr/local/bin/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 起動してみる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ /usr/local/bin/pushgateway
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;info &lt;span class="nv"&gt;ts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2020-04-28T13:24:39.058Z &lt;span class="nv"&gt;caller&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;main.go:83 &lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;starting pushgateway&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;(version=1.2.0, branch=HEAD, revision=b7e0167e9574f4f88404dde9653ee1d3c940f2eb)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;info &lt;span class="nv"&gt;ts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2020-04-28T13:24:39.058Z &lt;span class="nv"&gt;caller&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;main.go:84 &lt;span class="nv"&gt;build_context&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;(go=go1.13.8, user=root@0e823ccfff84, date=20200311-18:57:04)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;info &lt;span class="nv"&gt;ts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2020-04-28T13:24:39.062Z &lt;span class="nv"&gt;caller&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;main.go:137 &lt;span class="nv"&gt;listen_address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;:9091
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 確認次第Ctrl+Cで終了する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;[ラズパイのIP]:9091&lt;/strong&gt; を開いてみると&lt;code&gt;Pushgateway&lt;/code&gt;のUI画面が開く.&lt;br&gt;
今のところは何もメトリクスがないのでヘッダ以外は真っ白な画面.&lt;br&gt;
&lt;img alt="Pushgateway" class="gallery-image" data-flex-basis="932px" data-flex-grow="388" height="244" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc01.png" srcset="https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc01_hu_65aaba4f522ddc32.png 800w, https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc01.png 948w" width="948"&gt;&lt;/p&gt;
&lt;p&gt;動作確認ができたので,&lt;br&gt;
サービス化してついでに&lt;code&gt;nginx&lt;/code&gt;での&lt;a class="link" href="https://uzimihsr.github.io/post/2020-01-29-nginx/" target="_blank" rel="noopener"
 &gt;リバースプロキシ&lt;/a&gt;にも対応させておく.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 以下はRaspberry Piで実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# service起動に必要なuser(pushgateway)を追加する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo useradd -U -s /sbin/nologin -M -d / pushgateway
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# serviceファイルの作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo vim /etc/systemd/system/pushgateway.service
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# serviceの自動起動設定と起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl daemon-reload
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; pushgateway.service
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Created symlink /etc/systemd/system/multi-user.target.wants/pushgateway.service → /etc/systemd/system/pushgateway.service.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl start pushgateway.service
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;● pushgateway.service - Pushgateway
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Loaded: loaded &lt;span class="o"&gt;(&lt;/span&gt;/etc/systemd/system/pushgateway.service&lt;span class="p"&gt;;&lt;/span&gt; enabled&lt;span class="p"&gt;;&lt;/span&gt; vendor preset: enabled&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Active: active &lt;span class="o"&gt;(&lt;/span&gt;running&lt;span class="o"&gt;)&lt;/span&gt; since Tue 2020-04-28 22:41:04 JST&lt;span class="p"&gt;;&lt;/span&gt; 28s ago
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Main PID: &lt;span class="m"&gt;30393&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;pushgateway&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Tasks: &lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;limit: 2200&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Memory: 3.2M
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; CGroup: /system.slice/pushgateway.service
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └─30393 /usr/local/bin/pushgateway --web.external-url&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:8080/pushgateway/ --web.route-prefix&lt;span class="o"&gt;=&lt;/span&gt;/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Apr &lt;span class="m"&gt;28&lt;/span&gt; 22:41:04 raspberrypi pushgateway&lt;span class="o"&gt;[&lt;/span&gt;30393&lt;span class="o"&gt;]&lt;/span&gt;: &lt;span class="nv"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;info &lt;span class="nv"&gt;ts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2020-04-28T13:41:04.858Z &lt;span class="nv"&gt;caller&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;main.go:137 &lt;span class="nv"&gt;listen_address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;:9091
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# nginx設定ファイルの変更, 再起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo vim /etc/nginx/conf.d/default.conf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl restart nginx
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;details&gt;&lt;summary&gt;pushgateway.service&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-service" data-lang="service"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Unit]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Pushgateway&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Service]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;User&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;pushgateway&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;ExecStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/local/bin/pushgateway &lt;/span&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; --web.external-url=http://localhost:8080/pushgateway/ &lt;/span&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; --web.route-prefix=/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Install]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;WantedBy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;multi-user.target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;default.conf&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-nginx" data-lang="nginx"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="kn"&gt;listen&lt;/span&gt;	&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/prometheus/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="kn"&gt;proxy_pass&lt;/span&gt;	&lt;span class="s"&gt;http://localhost:9090/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/alertmanager/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="kn"&gt;proxy_pass&lt;/span&gt;	&lt;span class="s"&gt;http://localhost:9093/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/pushgateway/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="kn"&gt;proxy_pass&lt;/span&gt;	&lt;span class="s"&gt;http://localhost:9091/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/grafana/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="kn"&gt;proxy_pass&lt;/span&gt;	&lt;span class="s"&gt;http://localhost:3000/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;ここまで終わらせれば &lt;strong&gt;[ラズパイのIP]:[nginxのポート]/pushgateway&lt;/strong&gt; で&lt;code&gt;Pushgateway&lt;/code&gt;のUIが開けるようになっているはず.&lt;/p&gt;
&lt;p&gt;以上で&lt;code&gt;Pushgateway&lt;/code&gt;のセットアップは完了.&lt;/p&gt;
&lt;h3 id="メトリクスのpushとprometheusによるスクレイプ"&gt;メトリクスのpushとPrometheusによるスクレイプ
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Pushgateway&lt;/code&gt;の準備ができたので, 実際にメトリクスをpushしてみる.&lt;/p&gt;
&lt;p&gt;各言語のクライアントを使った叩き方は&lt;a class="link" href="https://prometheus.io/docs/instrumenting/pushing/" target="_blank" rel="noopener"
 &gt;ここ&lt;/a&gt;にあるけど,&lt;br&gt;
今回は敢えて&lt;a class="link" href="https://github.com/prometheus/pushgateway/blob/master/README.md#api" target="_blank" rel="noopener"
 &gt;API&lt;/a&gt;を使ってコマンドラインからpushしてみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 以下はMacで実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# job=&amp;#34;some_job&amp;#34;のグループにsome_metricという名前のGaugeをpushする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;some_metric 3.14&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; curl --data-binary @- http://&amp;lt;ラズパイのIP&amp;gt;:&amp;lt;nginxのポート&amp;gt;/pushgateway/metrics/job/some_job
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Pushが成功していれば&lt;code&gt;Pushgateway&lt;/code&gt;のUIにメトリクスの情報が表示される.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;some_metric&lt;/code&gt;以外の2つのメトリクス(&lt;code&gt;push_time_seconds&lt;/code&gt;, &lt;code&gt;push_failure_time_seconds&lt;/code&gt;)はそれぞれ&lt;br&gt;
メトリクスの更新に(成功|失敗)したUNIX時間を値として持つメトリクス.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Pushgateway" class="gallery-image" data-flex-basis="488px" data-flex-grow="203" height="1134" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc02.png" srcset="https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc02_hu_190468933562f6ba.png 800w, https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc02_hu_b7dce9da8f394dfe.png 1600w, https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc02.png 2306w" width="2306"&gt;&lt;/p&gt;
&lt;p&gt;こんな感じでジョブ実行時にpushすることで, &lt;code&gt;Pushgateway&lt;/code&gt;にジョブのメトリクスが貯まっていく.&lt;/p&gt;
&lt;p&gt;これらのメトリクスを時系列データとして扱うため,&lt;br&gt;
&lt;code&gt;Prometheus&lt;/code&gt;で&lt;code&gt;Pushgateway&lt;/code&gt;の持つメトリクスを定期的に収集(スクレイプ)する設定を追加してみる.&lt;br&gt;
ラベルの衝突を避けるため, &lt;code&gt;Pushgateway&lt;/code&gt;のスクレイプ設定には&lt;code&gt;honor_labels&lt;/code&gt;を追加しておく.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 以下はRaspberry Piで実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Prometheus設定ファイルを編集, 再起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo vim /usr/local/prometheus/prometheus.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl restart prometheus.service
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;details&gt;&lt;summary&gt;prometheus.yml&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;global&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;scrape_interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;15s&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;evaluation_interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;15s&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;rule_files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;rules.yml&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;alerting&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;alertmanagers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;localhost:9093&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;scrape_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;prometheus&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;localhost:9090&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;node&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;localhost:9100&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# ここから下を追加&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;pushgateway&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;honor_labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;localhost:9091&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Pushgatewayが起動しているポートを指定&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;設定が問題なく反映されていれば,&lt;br&gt;
&lt;code&gt;Prometheus&lt;/code&gt;から&lt;code&gt;Pushgateway&lt;/code&gt;がスクレイプできているのを確認できる.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Prometheus" class="gallery-image" data-flex-basis="393px" data-flex-grow="164" height="1406" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc03.png" srcset="https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc03_hu_891a585cf9fa2a21.png 800w, https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc03_hu_1c5c2976c22e1c8a.png 1600w, https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc03.png 2308w" width="2308"&gt;&lt;/p&gt;
&lt;p&gt;試しに何回かメトリクスをpushして, それから&lt;code&gt;Prometheus&lt;/code&gt;で時系列データを確認してみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 以下はMacで実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 先程とは違う値をpush&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;some_metric 1.41&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; curl --data-binary @- http://&amp;lt;ラズパイのIP&amp;gt;:&amp;lt;nginxのポート&amp;gt;/pushgateway/metrics/job/some_job
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 少し待ってから再度push&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;some_metric 2.71&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; curl --data-binary @- http://&amp;lt;ラズパイのIP&amp;gt;:&amp;lt;nginxのポート&amp;gt;/pushgateway/metrics/job/some_job
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;some_metric&lt;/code&gt;の値を見てみると, 次のようになる.&lt;br&gt;
注意すべき点としては, 新たにメトリクスがpushされるまで以前の値が変わらず保持され続けること.&lt;br&gt;
&lt;code&gt;Pushgateway&lt;/code&gt;はあくまでジョブのメトリクスを受け付けるためのものなので,&lt;br&gt;
ジョブが実行されていない間は最後にpushされた値を保持し続けて&lt;code&gt;Prometheus&lt;/code&gt;がスクレイプできるようにしている.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Prometheus" class="gallery-image" data-flex-basis="356px" data-flex-grow="148" height="1552" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc04.png" srcset="https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc04_hu_e4452bfe9a3dbaf.png 800w, https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc04_hu_4c6e47ae5a0ac7ee.png 1600w, https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc04.png 2306w" width="2306"&gt;&lt;/p&gt;
&lt;p&gt;これでジョブのメトリクスを&lt;code&gt;Pushgateway&lt;/code&gt;経由で&lt;code&gt;Prometheus&lt;/code&gt;がスクレイプできるようになった.&lt;/p&gt;
&lt;h3 id="cronjobの監視"&gt;CronJobの監視
&lt;/h3&gt;&lt;p&gt;ジョブのメトリクスが収集できるようになったので, いよいよ簡単な監視をしてみる.&lt;/p&gt;
&lt;p&gt;まずは監視対象として&lt;code&gt;Go&lt;/code&gt;で乱数のメトリクスをpushするだけのサンプルジョブを作成し,&lt;br&gt;
&lt;a class="link" href="https://uzimihsr.github.io/post/2020-03-15-golang-build-image/" target="_blank" rel="noopener"
 &gt;この手順&lt;/a&gt;で&lt;code&gt;Docker image&lt;/code&gt;化してみる.&lt;br&gt;
&lt;code&gt;Prometheus&lt;/code&gt;クライアントの使い方は&lt;a class="link" href="https://godoc.org/github.com/prometheus/client_golang/prometheus/push#Pusher.Push" target="_blank" rel="noopener"
 &gt;pushパッケージのGoDoc&lt;/a&gt;を参考にした.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 以下はMacで実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ジョブプログラムの作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim main.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 動作確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go run main.go --endpoint&lt;span class="o"&gt;=&lt;/span&gt;192.168.3.200:9091
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;192.168.3.200:9091
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample_job
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Metrics pushed successfully.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# docker化&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim Dockerfile
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image build -t golang-sample-job:latest .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Successfully built ff903de0d164
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Successfully tagged golang-sample-job:latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image ls golang-sample-job
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;REPOSITORY TAG IMAGE ID CREATED SIZE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;golang-sample-job latest ff903de0d164 About a minute ago 12.6MB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 動作確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run --rm golang-sample-job:latest --endpoint&lt;span class="o"&gt;=&lt;/span&gt;192.168.3.200:9091
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;192.168.3.200:9091
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample_job
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Metrics pushed successfully.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# タグをつけ直してDockerHubにアップロード&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image tag golang-sample-job:latest uzimihsr/golang-sample-job:latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image push uzimihsr/golang-sample-job:latest
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;details&gt;&lt;summary&gt;main.go&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-golang" data-lang="golang"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;flag&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;math/rand&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;os&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/prometheus/client_golang/prometheus&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/prometheus/client_golang/prometheus/push&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="c1"&gt;// Pushgatewayのエンドポイントとジョブ名は実行時引数で渡す&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pushgatewayEndpoint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;endpoint&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;http://pushgateway:9091&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Pushgateway endpoint. default: http://pushgateway:9091&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;jobName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;job&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;sample_job&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Job name. default: sample_job&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NFlag&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;		&lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;flags : --endpoint, --job&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;		&lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;pushgatewayEndpoint&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;jobName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="c1"&gt;// Gaugeの作成&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;randomValue&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;prometheus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewGauge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prometheus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GaugeOpts&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;		&lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;random_value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;		&lt;/span&gt;&lt;span class="nx"&gt;Help&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Float64 random value generated by golang.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="c1"&gt;// 乱数をGaugeにセット&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Seed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;UnixNano&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;randomValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Float64&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="c1"&gt;// メトリクスをpush&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;pushgatewayEndpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;jobName&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;		&lt;/span&gt;&lt;span class="nf"&gt;Collector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;randomValue&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;		&lt;/span&gt;&lt;span class="nf"&gt;Grouping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;sample_label&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;sample_label_value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;		&lt;/span&gt;&lt;span class="nf"&gt;Push&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;		&lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Could not push metrics to Pushgateway:&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;		&lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Metrics pushed successfully.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;Dockerfile&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-docker" data-lang="docker"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# build&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;golang:1.13&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; . ./goapp&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;./goapp&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; go mod download &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;CGO_ENABLED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="nv"&gt;GOOS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;linux go build -a -installsuffix cgo -o /app .&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# run&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;scratch&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;LABEL&lt;/span&gt; &lt;span class="nv"&gt;maintainer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;usimihsr&amp;#34;&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;goapp&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; --from&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; /app ./&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; --from&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;./app&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;実際にビルドした&lt;code&gt;image&lt;/code&gt; : &lt;a class="link" href="https://hub.docker.com/r/uzimihsr/golang-sample-job" target="_blank" rel="noopener"
 &gt;uzimihsr/golang-sample-job&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;これでサンプルジョブの&lt;code&gt;Docker image&lt;/code&gt;が作成できたので,&lt;br&gt;
次にこれを&lt;code&gt;CronJob&lt;/code&gt;化する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 以下はMacで実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# マニフェストの作成とCronJobの作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim cronjob.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f cronjob.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get cronjob sample-cronjob
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-cronjob */1 * * * * False &lt;span class="m"&gt;0&lt;/span&gt; 6m37s 3h12m
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この&lt;code&gt;CronJob&lt;/code&gt;では&lt;code&gt;Pod&lt;/code&gt;定義の&lt;code&gt;.spec.initContainers&lt;/code&gt;で&lt;br&gt;
メインコンテナの前にメトリクスをpushするコンテナを必ず実行するように定義している.&lt;br&gt;
こうすることでメインコンテナの成否に関わらずジョブの監視が可能になる.&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;cronjob.yaml&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;batch/v1beta1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;CronJob&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;sample-cronjob&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;schedule&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;*/1 * * * *&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;concurrencyPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Allow&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;startingDeadlineSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;successfulJobsHistoryLimit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;failedJobsHistoryLimit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;jobTemplate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;parallelism&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;backoffLimit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;initContainers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;push-metrics&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;uzimihsr/golang-sample-job:latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;imagePullPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;IfNotPresent&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;--endpoint=&amp;lt;ラズパイのIP&amp;gt;:9091&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;main-batch&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;busybox&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;/bin/sh&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- -&lt;span class="l"&gt;c&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;date; echo Hello from the Kubernetes cluster&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;restartPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Never&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;&lt;code&gt;CronJob&lt;/code&gt;が問題なく動作していれば1分ごとのジョブ実行時に乱数のメトリクス&lt;code&gt;random_value&lt;/code&gt;がpushされるので,&lt;br&gt;
&lt;code&gt;Prometheus&lt;/code&gt;で確認してみる.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Prometheus" class="gallery-image" data-flex-basis="444px" data-flex-grow="185" height="1554" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc05.png" srcset="https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc05_hu_3c1414a54618b63b.png 800w, https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc05_hu_708f6e7bd4e2e35b.png 1600w, https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc05_hu_77656761ecc012c1.png 2400w, https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc05.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;これらのメトリクスを使って簡単な監視ができるので, 以下のアラートルールを作成してみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 以下はMacで実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# アラートルールを編集して反映&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim /usr/local/prometheus/rules.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl restart prometheus.service
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;details&gt;&lt;summary&gt;rules.yml&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;instance&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;InstanceDown&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;up == 0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;1m&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 以下のルールを追加&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;pushgateway&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;CronJobNotScheduled&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;time() - push_time_seconds{job=&amp;#34;sample_job&amp;#34;} &amp;gt; 60 * 2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;CronJobFailed&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;random_value{job=&amp;#34;sample_job&amp;#34;} &amp;gt; 0.5&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;2m&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;&lt;code&gt;CronJobNotScheduled&lt;/code&gt;は最後に&lt;code&gt;CronJob&lt;/code&gt;が実行されてからの時間が2分以上になった場合に発火するアラート.&lt;br&gt;
pushの際に自動で更新されるメトリクス&lt;code&gt;push_time_seconds&lt;/code&gt;の値と現在の時間を比較して条件判定している.&lt;br&gt;
クラスタに障害があったりして2分以上&lt;code&gt;CronJob&lt;/code&gt;が実行されなかった場合はメトリクスがpushされないので,&lt;br&gt;
このルールで検知できる.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Prometheus" class="gallery-image" data-flex-basis="445px" data-flex-grow="185" height="1550" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc06.png" srcset="https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc06_hu_abb098945946ef04.png 800w, https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc06_hu_5a7b08f111f09f46.png 1600w, https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc06_hu_7749dc680399d959.png 2400w, https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc06.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;CronJobFailed&lt;/code&gt;は&lt;code&gt;CronJob&lt;/code&gt;が2分以上失敗し続けた場合に発火する(ことを想定した)アラート.&lt;br&gt;
今回は例としてジョブ開始時にpushされる乱数のメトリクス&lt;code&gt;random_value&lt;/code&gt;を条件判定に使っているが,&lt;br&gt;
ジョブのプロセスの終了ステータスをメトリクス化してジョブの最後にpushさせればジョブが連続して失敗した場合に検知できる.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Prometheus" class="gallery-image" data-flex-basis="444px" data-flex-grow="185" height="1554" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc07.png" srcset="https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc07_hu_be0986ce042de048.png 800w, https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc07_hu_ca62b0eb5350017d.png 1600w, https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc07_hu_2da7a4fd56c3df44.png 2400w, https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc07.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;試しにこのアラートルールが有効になっている状態で&lt;code&gt;CronJob&lt;/code&gt;を停止してみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 以下はMacで実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# CronJobを停止する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl patch cronjob sample-cronjob -p &lt;span class="s1"&gt;&amp;#39;{&amp;#34;spec&amp;#34;:{&amp;#34;suspend&amp;#34;:true}}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get cronjob sample-cronjob
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-cronjob */1 * * * * True &lt;span class="m"&gt;0&lt;/span&gt; 49s 3h49m
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;CronJob&lt;/code&gt;を停止すると新たなメトリクスがpushされなくなるので,&lt;br&gt;
2分以上経過した時点で&lt;code&gt;CronJobNotScheduled&lt;/code&gt;が発火し,&lt;br&gt;
停止した時点で最後にpushされた&lt;code&gt;random_value&lt;/code&gt;がしきい値(&lt;strong&gt;0.5&lt;/strong&gt;)より大きい値であったので&lt;code&gt;CronJobFailed&lt;/code&gt;も発火した.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Prometheus" class="gallery-image" data-flex-basis="427px" data-flex-grow="178" height="1616" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc08.png" srcset="https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc08_hu_7bf3e35334a3eacc.png 800w, https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc08_hu_e42b131ff4254e9d.png 1600w, https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc08_hu_b455b99bfa04911d.png 2400w, https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sc08.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;これで&lt;code&gt;Pushgateway&lt;/code&gt;を利用した&lt;code&gt;CronJob&lt;/code&gt;の監視ができるようになった.&lt;br&gt;
やったぜ.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Pushgateway&lt;/code&gt;のインストールから&lt;code&gt;CronJob&lt;/code&gt;の監視までの流れを一通りやってみた.&lt;br&gt;
&lt;code&gt;CronJob&lt;/code&gt;がちゃんと実行されているかを&lt;code&gt;Kubernetes API&lt;/code&gt;や&lt;code&gt;kubectl&lt;/code&gt;でいちいち確認するのは大変なので,&lt;br&gt;
こんな感じで監視できると便利だと思う.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="クッキーを焼くそとちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sotochan_hu_c90c1b301ecfeb1c.jpg 800w, https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sotochan_hu_5cb02381c80656ee.jpg 1600w, https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sotochan_hu_1cc490e13234ba66.jpg 2400w, https://blog.uzimihsr.com/post/2020-04-30-pushgateway/2020-04-30-sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>kubectlで時間範囲を指定してPod情報を取得する</title><link>https://blog.uzimihsr.com/post/2020-04-15-kubectl/</link><pubDate>Wed, 15 Apr 2020 11:11:48 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-04-15-kubectl/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-04-15-kubectl/2020-04-16-sotochan.jpg" alt="Featured image of post kubectlで時間範囲を指定してPod情報を取得する" /&gt;&lt;h2 id="podがいっぱいあると調査するのが大変"&gt;Podがいっぱいあると調査するのが大変
&lt;/h2&gt;&lt;p&gt;KubernetesクラスタのPod情報を取りたいときに,&lt;br&gt;
Podの起動日時を指定して取る方法がわかんなかったのでメモ.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Pod&lt;/code&gt;が起動した時刻を範囲指定して情報を取得する例&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2020-04-15の14:01:00~14:09:00(UTC)の間に作成されたPodだけ取り出してみる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -o custom-columns&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;NAME:{.metadata.name},CREATED-AT:{.metadata.creationTimestamp}&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; awk &lt;span class="s1"&gt;&amp;#39;{if (NR==1) print; else if (&amp;#34;2020-04-15T14:01:00Z&amp;#34; &amp;lt; $2 &amp;amp;&amp;amp; $2 &amp;lt; &amp;#34;2020-04-15T14:09:00Z&amp;#34;) print}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME CREATED-AT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sleep-1586959500-7pf6c 2020-04-15T14:05:06Z
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="やりかた"&gt;やりかた
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e4%ba%8b%e5%89%8d%e6%ba%96%e5%82%99" &gt;事前準備&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#pod%e6%83%85%e5%a0%b1%e3%82%92%e5%8f%96%e5%be%97%e3%81%99%e3%82%8b" &gt;Pod情報を取得する&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%97%e3%83%a9%e3%82%b0%e3%82%a4%e3%83%b3%e5%8c%96%e3%81%97%e3%81%a6%e3%81%bf%e3%82%8b" &gt;プラグイン化してみる&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="事前準備"&gt;事前準備
&lt;/h3&gt;&lt;p&gt;何個か&lt;code&gt;Pod&lt;/code&gt;を作っておきたいので&lt;code&gt;CronJob&lt;/code&gt;を作成する.&lt;br&gt;
せっかくなのでyaml無しで&lt;code&gt;kubectl create&lt;/code&gt;でつくってみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 5分毎に起動して30秒sleepするCronJob&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create cronjob test-job --image&lt;span class="o"&gt;=&lt;/span&gt;busybox --schedule&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;*/5 * * * *&amp;#34;&lt;/span&gt; --restart&lt;span class="o"&gt;=&lt;/span&gt;Never -- /bin/sh -c &lt;span class="s1"&gt;&amp;#39;date; sleep 30; date&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob.batch/sleep created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get cronjob sleep -o yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apiVersion: batch/v1beta1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kind: CronJob
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; creationTimestamp: &lt;span class="s2"&gt;&amp;#34;2020-04-15T13:59:57Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: sleep
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; resourceVersion: &lt;span class="s2"&gt;&amp;#34;8570399&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; selfLink: /apis/batch/v1beta1/namespaces/default/cronjobs/sleep
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; uid: a199da04-7fdc-11ea-b34b-42010a800054
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; concurrencyPolicy: Allow
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; failedJobsHistoryLimit: &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; jobTemplate:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; metadata:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; creationTimestamp: null
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: sleep
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; spec:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; template:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; metadata:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; creationTimestamp: null
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; spec:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; containers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - command:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - /bin/sh
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - -c
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - date&lt;span class="p"&gt;;&lt;/span&gt; sleep 30&lt;span class="p"&gt;;&lt;/span&gt; date
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; image: busybox
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; imagePullPolicy: Always
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: sleep
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; resources: &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; terminationMessagePath: /dev/termination-log
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; terminationMessagePolicy: File
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; dnsPolicy: ClusterFirst
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; restartPolicy: Never
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; schedulerName: default-scheduler
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; securityContext: &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; terminationGracePeriodSeconds: &lt;span class="m"&gt;30&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; schedule: &lt;span class="s1"&gt;&amp;#39;*/5 * * * *&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; successfulJobsHistoryLimit: &lt;span class="m"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; suspend: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;status:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; active:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - apiVersion: batch/v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kind: Job
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: sleep-1587039720
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; resourceVersion: &lt;span class="s2"&gt;&amp;#34;8570397&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; uid: df56a4d7-7fdc-11ea-b34b-42010a800054
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; lastScheduleTime: &lt;span class="s2"&gt;&amp;#34;2020-04-15T14:00:00Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 15分以上放っておくとPodが3つできている(successfulJobsHistoryLimit: 3)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods &lt;span class="p"&gt;|&lt;/span&gt; awk &lt;span class="s1"&gt;&amp;#39;{if (NR==1) print; else if ($1 ~ /sleep/) print}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sleep-1586959200-m8q7b 0/1 Completed &lt;span class="m"&gt;0&lt;/span&gt; 11m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sleep-1586959500-7pf6c 0/1 Completed &lt;span class="m"&gt;0&lt;/span&gt; 6m14s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sleep-1586959800-wgmpd 0/1 Completed &lt;span class="m"&gt;0&lt;/span&gt; 74s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# CronJobを止めておく&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl patch cronjob sleep -p &lt;span class="s1"&gt;&amp;#39;{&amp;#34;spec&amp;#34;:{&amp;#34;suspend&amp;#34;:true}}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cronjob.batch/sleep patched
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="pod情報を取得する"&gt;Pod情報を取得する
&lt;/h3&gt;&lt;p&gt;普通にgetしてみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sleep-1586959200-m8q7b 0/1 Completed &lt;span class="m"&gt;0&lt;/span&gt; 14m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sleep-1586959500-7pf6c 0/1 Completed &lt;span class="m"&gt;0&lt;/span&gt; 9m21s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sleep-1586959800-wgmpd 0/1 Completed &lt;span class="m"&gt;0&lt;/span&gt; 4m21s
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これだとAGEしかわかんないので,&lt;br&gt;
例えばhh時mm分~hh時nn分に作成された&lt;code&gt;Pod&lt;/code&gt;だけほしいってときに困る.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Pod&lt;/code&gt;の&lt;code&gt;.metadata.creationTimestamp&lt;/code&gt;には起動した時間が記述されているので,&lt;br&gt;
これを表示するようにしてみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# columnにPod名と起動時間を指定してみる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -o custom-columns&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;NAME:{.metadata.name},CREATED-AT:{.metadata.creationTimestamp}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME CREATED-AT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sleep-1586959200-m8q7b 2020-04-15T14:00:05Z
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sleep-1586959500-7pf6c 2020-04-15T14:05:06Z
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sleep-1586959800-wgmpd 2020-04-15T14:10:06Z
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;いい感じ.&lt;br&gt;
これで各&lt;code&gt;Pod&lt;/code&gt;がいつ起動したかがわかる.&lt;/p&gt;
&lt;p&gt;ちょっと調べた(&lt;code&gt;kubectl get pods --help&lt;/code&gt;見ただけ)けど&lt;br&gt;
時間の範囲を指定して表示するオプションとかがなかったので,&lt;br&gt;
ここからは&lt;code&gt;awk&lt;/code&gt;でしこしこやっていく.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.status.startTime&lt;/code&gt;のフォーマットが&lt;code&gt;YYYY-MM-DDThh:mm:ssZ&lt;/code&gt;なので,&lt;br&gt;
これに従って範囲を指定してみる.&lt;br&gt;
参考 : &lt;a class="link" href="https://ja.wikipedia.org/wiki/ISO_8601" target="_blank" rel="noopener"
 &gt;https://ja.wikipedia.org/wiki/ISO_8601&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2020-04-15の14:01:00~14:09:00(UTC)の間に作成されたPodだけ取り出してみる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -o custom-columns&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;NAME:{.metadata.name},CREATED-AT:{.metadata.creationTimestamp}&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; awk &lt;span class="s1"&gt;&amp;#39;{if (NR==1) print; else if (&amp;#34;2020-04-15T14:01:00Z&amp;#34; &amp;lt; $2 &amp;amp;&amp;amp; $2 &amp;lt; &amp;#34;2020-04-15T14:09:00Z&amp;#34;) print}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME CREATED-AT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sleep-1586959500-7pf6c 2020-04-15T14:05:06Z
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;時刻の範囲を指定して&lt;code&gt;Pod&lt;/code&gt;名が取得できた.&lt;br&gt;
やったぜ.&lt;/p&gt;
&lt;h3 id="プラグイン化してみる"&gt;プラグイン化してみる
&lt;/h3&gt;&lt;p&gt;毎度毎度コマンドを組み立てるのも大変なので, かんたんなプラグインをつくってみる.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;kubectl-timerange&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/sh
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;func&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$#&lt;/span&gt; -lt &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nv"&gt;$#&lt;/span&gt; -gt &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;args: resource time_from time_to&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;resource&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;time_from&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; time_to
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$#&lt;/span&gt; -lt &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;time_to&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;date -u +%Y-%m-%dT%k:%M:%SZ&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;time_to&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$3&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubectl get &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;resource&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; -o custom-columns&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;NAME:{.metadata.name},START_TIME:{.metadata.creationTimestamp}&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; awk &lt;span class="s1"&gt;&amp;#39;{if (NR==1) print; else if (&amp;#39;&lt;/span&gt;&lt;span class="se"&gt;\&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;time_from&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\&amp;#34;&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39; &amp;lt; $2 &amp;amp;&amp;amp; $2 &amp;lt; &amp;#39;&lt;/span&gt;&lt;span class="se"&gt;\&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;time_to&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\&amp;#34;&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;) print}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;func &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;作ったプラグインを読めるようにする.&lt;br&gt;
ファイル名が&lt;code&gt;kubectl-hoge&lt;/code&gt;のスクリプトがPATHの通った場所にあると,&lt;br&gt;
&lt;code&gt;kubectl hoge&lt;/code&gt;で呼び出すことができる.&lt;br&gt;
&lt;a class="link" href="https://kubernetes.io/docs/tasks/extend-kubectl/kubectl-plugins/" target="_blank" rel="noopener"
 &gt;Extend kubectl with plugins&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# スクリプトを記述&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim /usr/local/bin/kubectl-timerange
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 実行できるようにする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ chmod +x /usr/local/bin/kubectl-timerange
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 有効なプラグインを確認する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl plugin list
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;The following compatible plugins are available:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/usr/local/bin/kubectl-timerange
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 実際に使ってみる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl timerange pod &lt;span class="s1"&gt;&amp;#39;2020-04-15T14:01:00Z&amp;#39;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;2020-04-15T14:09:00Z&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME CREATED-AT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sleep-1586959500-7pf6c 2020-04-15T14:05:06Z
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;できた.&lt;br&gt;
毎回&lt;code&gt;awk&lt;/code&gt;のスクリプトを書くのも大変なのでこっちのほうが使いやすい.&lt;br&gt;
はず&amp;hellip;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;CronJob&lt;/code&gt;を扱う機会が多いので, &lt;code&gt;Job&lt;/code&gt;が連続して失敗したときなんかに調査用に使っていきたい.&lt;br&gt;
というか&lt;code&gt;awk&lt;/code&gt;が便利なのでもうちょっと使いこなせるようになりたい.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="ぐにゃぐにゃねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-04-15-kubectl/2020-04-16-sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-04-15-kubectl/2020-04-16-sotochan_hu_cb89f9a516263d81.jpg 800w, https://blog.uzimihsr.com/post/2020-04-15-kubectl/2020-04-16-sotochan_hu_6838d83ba8b0dbc2.jpg 1600w, https://blog.uzimihsr.com/post/2020-04-15-kubectl/2020-04-16-sotochan_hu_112ef63d63003197.jpg 2400w, https://blog.uzimihsr.com/post/2020-04-15-kubectl/2020-04-16-sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>GoアプリをDockerのscratchイメージで動かす</title><link>https://blog.uzimihsr.com/post/2020-03-15-golang-build-image/</link><pubDate>Sun, 15 Mar 2020 13:36:21 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-03-15-golang-build-image/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-03-15-golang-build-image/2020-03-15-sotochan.jpg" alt="Featured image of post GoアプリをDockerのscratchイメージで動かす" /&gt;&lt;h2 id="軽いイメージをつくる"&gt;軽いイメージをつくる
&lt;/h2&gt;&lt;p&gt;Go(golang)のDocker buildの練習をしてみた.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Go(golang)で作ったアプリをDockerイメージにした&lt;/li&gt;
&lt;li&gt;マルチステージビルドを使って軽いイメージを作った&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;scratchを使う場合は次のような&lt;code&gt;Dockerfile&lt;/code&gt;を書けばいい.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-dockerfile" data-lang="dockerfile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# ビルド用イメージ&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;golang:1.13&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# mainパッケージがあるディレクトリ(.)をまるごとコピー&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; . ./goapp&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;./goapp&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# goapp内のgo.mod, go.sumで依存関係を管理している場合に使用&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; go mod download&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# クロスコンパイル&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; &lt;span class="nv"&gt;CGO_ENABLED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="nv"&gt;GOOS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;linux go build -a -installsuffix cgo -o /app .&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# バイナリを載せるイメージ&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;scratch&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;goapp&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# ビルド済みのバイナリをコピー&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; --from&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; /app ./&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# httpsで通信を行う場合に使用&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; --from&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;./app&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;MacBook Pro (Retina, 15-inch, Mid 2015)
&lt;ul&gt;
&lt;li&gt;macOS Mojave 10.14&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Go(golang)
&lt;ul&gt;
&lt;li&gt;go version go1.13 darwin/amd64&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Docker
&lt;ul&gt;
&lt;li&gt;Docker version 19.03.2, build 6a30dfc&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;なんかのGoアプリ
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2020-03-09-golang-api-client/" target="_blank" rel="noopener"
 &gt;前回作ったやつ&lt;/a&gt;を使用&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e6%99%ae%e9%80%9a%e3%81%abdocker%e3%82%a4%e3%83%a1%e3%83%bc%e3%82%b8%e3%82%92%e3%83%93%e3%83%ab%e3%83%89" &gt;普通にDockerイメージをビルド&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%9e%e3%83%ab%e3%83%81%e3%82%b9%e3%83%86%e3%83%bc%e3%82%b8%e3%83%93%e3%83%ab%e3%83%89%e3%82%92%e8%a9%a6%e3%81%99" &gt;マルチステージビルドを試す&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#scratch%e3%82%92%e4%bd%bf%e3%81%86" &gt;scratchを使う&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="普通にdockerイメージをビルド"&gt;普通にDockerイメージをビルド
&lt;/h3&gt;&lt;p&gt;Goのアプリはなんでもいいはずなので,&lt;br&gt;
前回作ったwikipedia検索するおもちゃをそのまま使ってみる.&lt;br&gt;
&lt;a class="link" href="https://github.com/uzimihsr/wikipedia-search" target="_blank" rel="noopener"
 &gt;https://github.com/uzimihsr/wikipedia-search&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Dockerfile&lt;/code&gt;を書くとこんな感じ.&lt;br&gt;
ベースイメージは&lt;a class="link" href="https://hub.docker.com/layers/golang/library/golang/1.13/images/sha256-be37fd7a30b94a720a45ba5dcc0cf386d043acc5f4f61db7c6736fd10ee621bd?context=explore" target="_blank" rel="noopener"
 &gt;golang:1.13&lt;/a&gt;でビルドしてみる.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Dockerfile-golang&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-dockerfile" data-lang="dockerfile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# ベースイメージが大きいパターン&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;golang:1.13&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;LABEL&lt;/span&gt; &lt;span class="nv"&gt;maintainer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;usimihsr&amp;#34;&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# ファイルを全部コピー&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; . ./goapp&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;./goapp&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# go.modとgo.sumを使って管理している依存関係をダウンロードしてビルド&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; go mod download &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; go build -o ./app .&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# バイナリをエントリーポイントに指定&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;./app&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ビルドして動かしてみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git clone https://github.com/uzimihsr/wikipedia-search.git
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; wikiepdia-search
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Dockerイメージをビルドする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image build -t wikipedia-search:golang -f Dockerfile-golang .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Sending build context to Docker daemon 87.55kB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 1/6 : FROM golang:1.13
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; 3a7408f53f79
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 2/6 : LABEL &lt;span class="nv"&gt;maintainer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;usimihsr&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; Using cache
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; b5ba8c17244f
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 3/6 : COPY . ./goapp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; d2bffdafe570
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 4/6 : WORKDIR ./goapp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; Running in def85395de98
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Removing intermediate container def85395de98
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; d215e88c95ba
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 5/6 : RUN go mod download &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; go build -o ./app .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; Running in 307004980e61
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Removing intermediate container 307004980e61
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; 9873d8f458a6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 6/6 : ENTRYPOINT &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;./app&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; Running in 4f189dba7fa1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Removing intermediate container 4f189dba7fa1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; f75198355e97
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Successfully built f75198355e97
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Successfully tagged wikipedia-search:golang
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ENTRYPOINTを無視してbashを起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 指定したディレクトリにコピーしたファイルとビルドしたバイナリが確認できる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run --rm -it --entrypoint&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt; wikipedia-search:golang /bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;root@6f62f4307560:/go/goapp$ &lt;span class="nb"&gt;pwd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/go/goapp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;root@6f62f4307560:/go/goapp$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Dockerfile-golang README.md app go.mod main.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;root@6f62f4307560:/go/goapp$ &lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# コンテナを動かしてみる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# &amp;lt;-srlimit=5 &amp;#39;イチロー&amp;#39;&amp;gt;はENTRYPOINTのバイナリ(./app)実行時に渡すパラメータ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run wikipedia-search:golang -srlimit&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;イチロー&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;イチロー
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://ja.wikipedia.org/?curid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1432262&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;首位打者 &lt;span class="o"&gt;(&lt;/span&gt;日本プロ野球&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://ja.wikipedia.org/?curid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;38085&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;国道262号
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://ja.wikipedia.org/?curid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;126147&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;河上イチロー
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://ja.wikipedia.org/?curid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;3682529&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;新井宏昌
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://ja.wikipedia.org/?curid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;688515&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;問題なく動いた.&lt;/p&gt;
&lt;h3 id="マルチステージビルドを試す"&gt;マルチステージビルドを試す
&lt;/h3&gt;&lt;p&gt;上記の手順でGoアプリのイメージが問題なくビルドできた. が,&lt;br&gt;
ベースイメージに使わないファイルが大量にあるため,&lt;br&gt;
かなり重いイメージ(810MB)が出来上がってしまった.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image ls wikipedia-search
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;REPOSITORY TAG IMAGE ID CREATED SIZE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;wikipedia-search golang f75198355e97 &lt;span class="m"&gt;6&lt;/span&gt; minutes ago 810MB
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;実際に使いたいのはバイナリ(app)だけなので,&lt;br&gt;
&lt;a class="link" href="https://docs.docker.com/develop/develop-images/multistage-build/" target="_blank" rel="noopener"
 &gt;マルチステージビルド&lt;/a&gt;を使ってビルド済みのバイナリだけを軽いイメージに載せてみる.&lt;br&gt;
試しに軽量Linuxイメージの&lt;a class="link" href="https://hub.docker.com/layers/alpine/library/alpine/latest/images/sha256-ddba4d27a7ffc3f86dd6c2f92041af252a1f23a8e742c90e6e1297bfa1bc0c45?context=explore" target="_blank" rel="noopener"
 &gt;alpine:latest&lt;/a&gt;を使ってみる.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Dockerfile-alpine&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-dockerfile" data-lang="dockerfile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# golangをビルド用イメージとして使うパターン&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;golang:1.13&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; . ./goapp&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;./goapp&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# ビルド時にクロスコンパイルのオプションを指定&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; go mod download &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;CGO_ENABLED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="nv"&gt;GOOS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;linux go build -a -installsuffix cgo -o /app .&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# ベースイメージはalpineを指定&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;alpine:latest&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;LABEL&lt;/span&gt; &lt;span class="nv"&gt;maintainer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;usimihsr&amp;#34;&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;goapp&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# ビルド用イメージからバイナリをコピー&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; --from&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; /app ./&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# httpsで通信するのに必要なCA証明書を用意する&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; apk --no-cache add ca-certificates&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;./app&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ビルド&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image build -t wikipedia-search:alpine -f Dockerfile-alpine .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Sending build context to Docker daemon 98.3kB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 1/10 : FROM golang:1.13
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; 3a7408f53f79
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 2/10 : COPY . ./goapp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; 2ce3dd5f2452
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 3/10 : WORKDIR ./goapp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; Running in 66c34bbf39c1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Removing intermediate container 66c34bbf39c1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; 6876fbc22a61
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 4/10 : RUN go mod download &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;CGO_ENABLED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="nv"&gt;GOOS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;linux go build -a -installsuffix cgo -o /app .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; Running in 98346481243b
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Removing intermediate container 98346481243b
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; 3bc411f60c04
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 5/10 : FROM alpine:latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; &lt;span class="m"&gt;961769676411&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 6/10 : LABEL &lt;span class="nv"&gt;maintainer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;usimihsr&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; Running in dbddd972c873
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Removing intermediate container dbddd972c873
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; cb8ff63adce6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 7/10 : WORKDIR goapp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; Running in cad6ec5d31df
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Removing intermediate container cad6ec5d31df
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; d88c328fe670
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 8/10 : COPY --from&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; /app ./
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; 5a8738b30e43
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 9/10 : RUN apk --no-cache add ca-certificates
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; Running in c271e71b475e
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;fetch http://dl-cdn.alpinelinux.org/alpine/v3.10/main/x86_64/APKINDEX.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;fetch http://dl-cdn.alpinelinux.org/alpine/v3.10/community/x86_64/APKINDEX.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;(&lt;/span&gt;1/1&lt;span class="o"&gt;)&lt;/span&gt; Installing ca-certificates &lt;span class="o"&gt;(&lt;/span&gt;20190108-r0&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Executing busybox-1.30.1-r2.trigger
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Executing ca-certificates-20190108-r0.trigger
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;OK: &lt;span class="m"&gt;6&lt;/span&gt; MiB in &lt;span class="m"&gt;15&lt;/span&gt; packages
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Removing intermediate container c271e71b475e
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; 7a22400f095e
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 10/10 : ENTRYPOINT &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;./app&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; Running in a3f75ef34223
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Removing intermediate container a3f75ef34223
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; b9635a037fe6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Successfully built b9635a037fe6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Successfully tagged wikipedia-search:alpine
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# マルチステージビルドで置かれたバイナリを確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run --rm -it --entrypoint&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt; wikipedia-search:alpine /bin/ash
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/goapp $ &lt;span class="nb"&gt;pwd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/goapp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/goapp $ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/goapp $ &lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# アプリを実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run wikipedia-search:alpine -srlimit&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;イチロー&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;イチロー
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://ja.wikipedia.org/?curid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1432262&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;首位打者 &lt;span class="o"&gt;(&lt;/span&gt;日本プロ野球&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://ja.wikipedia.org/?curid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;38085&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;国道262号
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://ja.wikipedia.org/?curid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;126147&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;河上イチロー
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://ja.wikipedia.org/?curid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;3682529&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;新井宏昌
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://ja.wikipedia.org/?curid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;688515&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;問題なく動いた.&lt;/p&gt;
&lt;p&gt;イメージもだいぶ軽くなった(810MB -&amp;gt; 13.5MB).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image ls wikipedia-search
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;REPOSITORY TAG IMAGE ID CREATED SIZE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;wikipedia-search alpine 9fc6e1d19baf &lt;span class="m"&gt;18&lt;/span&gt; seconds ago 13.5MB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;wikipedia-search golang f75198355e97 &lt;span class="m"&gt;52&lt;/span&gt; minutes ago 810MB
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;やったぜ.&lt;/p&gt;
&lt;h3 id="scratchを使う"&gt;scratchを使う
&lt;/h3&gt;&lt;p&gt;なんと! 世の中にはalpineよりもっと軽いイメージがあるらしい.&lt;br&gt;
&lt;a class="link" href="https://hub.docker.com/_/scratch?tab=description" target="_blank" rel="noopener"
 &gt;scratch&lt;/a&gt;はDockerの最小イメージで, 中にはなんにも入っていない.&lt;br&gt;
こいつを使えばめちゃめちゃ軽いイメージが作れるのでは?&lt;/p&gt;
&lt;p&gt;やってみる.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Dockerfile-scratch&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-Dockerfile" data-lang="Dockerfile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# golangをビルド用イメージとして使うパターン&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;golang:1.13&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; . ./goapp&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;./goapp&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; go mod download &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;CGO_ENABLED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="nv"&gt;GOOS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;linux go build -a -installsuffix cgo -o /app .&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# ベースイメージはscratchを指定&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;scratch&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;LABEL&lt;/span&gt; &lt;span class="nv"&gt;maintainer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;usimihsr&amp;#34;&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;goapp&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; --from&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; /app ./&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# httpsで通信するのに必要なCA証明書を用意する&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; --from&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;./app&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ビルド&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image build -t wikipedia-search:scratch -f Dockerfile-scratch .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Sending build context to Docker daemon 98.3kB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 1/10 : FROM golang:1.13
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; 3a7408f53f79
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 2/10 : COPY . ./goapp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; Using cache
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; 2ce3dd5f2452
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 3/10 : WORKDIR ./goapp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; Using cache
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; 6876fbc22a61
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 4/10 : RUN go mod download &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;CGO_ENABLED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="nv"&gt;GOOS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;linux go build -a -installsuffix cgo -o /app .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; Using cache
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; 3bc411f60c04
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 5/10 : FROM scratch
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 6/10 : LABEL &lt;span class="nv"&gt;maintainer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;usimihsr&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; Running in ca17656408ee
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Removing intermediate container ca17656408ee
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; a27e151d506a
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 7/10 : WORKDIR goapp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; Running in 6f5f0ef76f49
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Removing intermediate container 6f5f0ef76f49
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; 19dcf5fdbbb4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 8/10 : COPY --from&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; /app ./
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; 76bbcf3bc727
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 9/10 : COPY --from&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; 0f5a0c01f2c0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 10/10 : ENTRYPOINT &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;./app&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; Running in fdaa63f93c93
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Removing intermediate container fdaa63f93c93
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; eafc764f5a6e
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Successfully built eafc764f5a6e
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Successfully tagged wikipedia-search:scratch
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run wikipedia-search:scratch -srlimit&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;イチロー&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;イチロー
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://ja.wikipedia.org/?curid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1432262&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;首位打者 &lt;span class="o"&gt;(&lt;/span&gt;日本プロ野球&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://ja.wikipedia.org/?curid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;38085&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;国道262号
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://ja.wikipedia.org/?curid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;126147&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;河上イチロー
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://ja.wikipedia.org/?curid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;3682529&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;新井宏昌
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://ja.wikipedia.org/?curid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;688515&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これまでと同じように動かせた.&lt;/p&gt;
&lt;p&gt;さらにイメージも軽くなった(13.5MB -&amp;gt; 7.52MB).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image ls wikipedia-search
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;REPOSITORY TAG IMAGE ID CREATED SIZE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;wikipedia-search scratch eafc764f5a6e &lt;span class="m"&gt;9&lt;/span&gt; seconds ago 7.52MB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;wikipedia-search alpine b9635a037fe6 &lt;span class="m"&gt;35&lt;/span&gt; seconds ago 13.5MB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;wikipedia-search golang f75198355e97 About an hour ago 810MB
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;やったぜ.&lt;br&gt;
Goのアプリを軽いDocker imageにすることができた.&lt;/p&gt;
&lt;p&gt;作ったイメージはここ.&lt;br&gt;
&lt;a class="link" href="https://hub.docker.com/r/uzimihsr/wikipedia-search/tags" target="_blank" rel="noopener"
 &gt;https://hub.docker.com/r/uzimihsr/wikipedia-search/tags&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="ひざの上で寝るねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-03-15-golang-build-image/2020-03-15-sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-03-15-golang-build-image/2020-03-15-sotochan_hu_d2c3eae18a87dc1.jpg 800w, https://blog.uzimihsr.com/post/2020-03-15-golang-build-image/2020-03-15-sotochan_hu_60b62f7cc0ad0374.jpg 1600w, https://blog.uzimihsr.com/post/2020-03-15-golang-build-image/2020-03-15-sotochan_hu_bc1c8d2e7d9f2744.jpg 2400w, https://blog.uzimihsr.com/post/2020-03-15-golang-build-image/2020-03-15-sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>GoでWikipediaのAPIを叩いて記事検索した</title><link>https://blog.uzimihsr.com/post/2020-03-09-golang-api-client/</link><pubDate>Mon, 09 Mar 2020 21:29:36 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-03-09-golang-api-client/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-03-09-golang-api-client/2020-03-09-sotochan.jpg" alt="Featured image of post GoでWikipediaのAPIを叩いて記事検索した" /&gt;&lt;h2 id="久しぶりのgo"&gt;久しぶりのGo
&lt;/h2&gt;&lt;p&gt;最近k8sの勉強ばっかで開発っぽいことをやってなかったので, Go(golang)で遊んでみた.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;WikipediaのAPI(Wikimedia API)を叩いてみた&lt;/li&gt;
&lt;li&gt;Go(golang)でAPIクライアントもどきを作った&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;作ったクライアントはこんなかんじ.&lt;br&gt;
Wikipediaの記事を検索した結果とそのURLが表示できる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ wikipedia -srlimit&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt; -lang&lt;span class="o"&gt;=&lt;/span&gt;en &lt;span class="s1"&gt;&amp;#39;cat&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Cat
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://en.wikipedia.org/?curid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;6678&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Cat &lt;span class="o"&gt;(&lt;/span&gt;disambiguation&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://en.wikipedia.org/?curid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;434590&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.cat
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://en.wikipedia.org/?curid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1978706&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Bengal cat
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://en.wikipedia.org/?curid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;63064&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Cat Stevens
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://en.wikipedia.org/?curid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;78747&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;MacBook Pro (Retina, 15-inch, Mid 2015)
&lt;ul&gt;
&lt;li&gt;macOS Mojave 10.14&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Go(golang)
&lt;ul&gt;
&lt;li&gt;go version go1.13 darwin/amd64&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.mediawiki.org/wiki/API:Main_page/ja" target="_blank" rel="noopener"
 &gt;Wikipedia API&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#wikipediaapi%e3%82%92%e3%81%9f%e3%81%9f%e3%81%8f" &gt;WikipediaAPIをたたく&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#go%e3%81%a7api%e3%82%92%e3%81%9f%e3%81%9f%e3%81%8f" &gt;GoでAPIをたたく&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="wikipediaapiをたたく"&gt;WikipediaAPIをたたく
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://www.mediawiki.org/wiki/API:Main_page/ja" target="_blank" rel="noopener"
 &gt;APIのページ&lt;/a&gt;によると,&lt;br&gt;
Wikipedia(日本語版)APIのURLは&lt;br&gt;
&lt;a class="link" href="https://ja.wikipedia.org/w/api.php" target="_blank" rel="noopener"
 &gt;https://ja.wikipedia.org/w/api.php&lt;/a&gt;&lt;br&gt;
となっている.&lt;/p&gt;
&lt;p&gt;今回は&lt;a class="link" href="https://www.mediawiki.org/wiki/API:Search" target="_blank" rel="noopener"
 &gt;記事検索API&lt;/a&gt;を使ってみる.&lt;br&gt;
記事検索をする場合はクエリパラメータに&lt;br&gt;
&lt;code&gt;action=query&lt;/code&gt;, &lt;code&gt;list=search&lt;/code&gt;, &lt;code&gt;srsearch=&amp;lt;検索したい文字列&amp;gt;&lt;/code&gt;を指定して&lt;br&gt;
&lt;code&gt;GET&lt;/code&gt;すればいいみたい.&lt;br&gt;
レスポンスボディの形式は&lt;code&gt;format=json&lt;/code&gt;(JSONの場合)でできるっぽい.&lt;/p&gt;
&lt;p&gt;例: &amp;ldquo;猫&amp;quot;で検索する場合&lt;br&gt;
GET &lt;a class="link" href="http://ja.wikipedia.org/w/api.php?format=json&amp;amp;action=query&amp;amp;list=search&amp;amp;srsearch=" target="_blank" rel="noopener"
 &gt;http://ja.wikipedia.org/w/api.php?format=json&amp;action=query&amp;list=search&amp;srsearch=&lt;/a&gt;猫&lt;/p&gt;
&lt;p&gt;試しに&lt;code&gt;curl&lt;/code&gt;で叩いてみる.&lt;br&gt;
デフォルトでは検索結果の上位10件が返ってくる.&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;APIでの検索結果&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# なんかリダイレクトされるみたいなのでLオプションは必須&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# JSONはjqでいい感じに整形する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -sSL &lt;span class="s1"&gt;&amp;#39;http://ja.wikipedia.org/w/api.php?action=query&amp;amp;format=json&amp;amp;list=search&amp;amp;srsearch=猫&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; jq
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;batchcomplete&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;continue&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;sroffset&amp;#34;&lt;/span&gt;: 10,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;continue&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;-||&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;query&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;searchinfo&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;totalhits&amp;#34;&lt;/span&gt;: &lt;span class="m"&gt;26227&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;search&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;ns&amp;#34;&lt;/span&gt;: 0,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;ネコ&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;pageid&amp;#34;&lt;/span&gt;: 1215264,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;size&amp;#34;&lt;/span&gt;: 123050,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;wordcount&amp;#34;&lt;/span&gt;: 16730,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;snippet&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;黒&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt; - 全身の毛が黒色の&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt;。 白猫 - 全身の毛が白色の&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt;。 トラネコ（タビー） - トラのような縞模様がある&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt;。茶トラ&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt;、キジ&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt;、サバ&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt;など。 三毛&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt; - 3色（一般的に白・茶色・黒）の&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt;。 錆び&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt; - 黒と茶色の2色の&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt;。 はちわれ - 顔面が鼻筋を境にした八の字形の2色になっている&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt;。&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;timestamp&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;2020-03-03T14:46:03Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;ns&amp;#34;&lt;/span&gt;: 0,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;三毛猫ホームズシリーズ&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;pageid&amp;#34;&lt;/span&gt;: 227387,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;size&amp;#34;&lt;/span&gt;: 55409,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;wordcount&amp;#34;&lt;/span&gt;: 7737,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;snippet&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;収録作品　三毛猫ホームズの運動会・三毛&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt;ホームズのスクープ・三毛&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt;ホームズのバカンス・三毛&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt;ホームズの温泉旅行・三毛&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt;ホームズの殺人展覧会・三毛&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt;ホームズのバースデー・パーティ （9）三毛&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt;ホームズのびっくり箱 収録作品　三毛&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt;ホームズのびっくり箱・三毛&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt;ホームズの名演奏・三毛&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt;ホームズのパニック・三毛&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt;ホームズの幽霊退治・三毛&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;timestamp&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;2020-02-20T12:43:57Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;ns&amp;#34;&lt;/span&gt;: 0,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;1905年&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;pageid&amp;#34;&lt;/span&gt;: 2506,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;size&amp;#34;&lt;/span&gt;: 26827,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;wordcount&amp;#34;&lt;/span&gt;: 3310,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;snippet&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;が、1962年からは公式な場では使用されていない。 1月1日 - 日露戦争：旅順開城 1月1日 - 夏目漱石が『ホトトギス』1月号で、処女作『吾輩は&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt;である』を連載開始 1月22日 - サンクトペテルブルクで血の日曜日事件発生 1月23日 - 奈良県鷲家口（現・吉野郡東吉野村）でニホンオオカミの捕&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;timestamp&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;2020-01-23T07:22:49Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;ns&amp;#34;&lt;/span&gt;: 0,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;吾輩は猫である&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;pageid&amp;#34;&lt;/span&gt;: 13241,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;size&amp;#34;&lt;/span&gt;: 32502,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;wordcount&amp;#34;&lt;/span&gt;: 4469,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;snippet&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;『吾輩は&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt;である』（わがはいはねこである）は、夏目漱石の長編小説であり、処女小説である。1905年（明治38年）1月、『ホトトギス』に発表され、好評を博したため、翌1906年（明治39年）8月まで継続した。 「吾輩は&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt;である。名前はまだ無い。どこで生れたかとんと見当がつかぬ。」という書き出しで始ま&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;timestamp&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;2020-02-03T23:11:05Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;ns&amp;#34;&lt;/span&gt;: 0,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;猫騙し&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;pageid&amp;#34;&lt;/span&gt;: 229647,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;size&amp;#34;&lt;/span&gt;: 3049,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;wordcount&amp;#34;&lt;/span&gt;: 432,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;snippet&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt;騙し（ねこだまし）とは相撲の戦法の一種である。 立合いと同時に相手力士の目の前に両手を突き出して掌を合わせて叩くもので、相手の目をつぶらせることを目的とする奇襲戦法の一つ。相手に隙を作り、有利な体勢を作るために使われる。普通の立合いではかなわないような、はるかに強い相手に対する一発勝負に使われる&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;timestamp&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;2019-07-18T01:55:22Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;ns&amp;#34;&lt;/span&gt;: 0,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;クイズRPG 魔法使いと黒猫のウィズ&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;pageid&amp;#34;&lt;/span&gt;: 2969296,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;size&amp;#34;&lt;/span&gt;: 32428,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;wordcount&amp;#34;&lt;/span&gt;: 4747,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;snippet&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;『クイズRPG 魔法使いと黒&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt;のウィズ』（クイズRPG まほうつかいとくろねこのウィズ）は、2013年にコロプラで配信を開始したソーシャルゲーム。 2013年3月にAndroid版が、4月22日にiOS版が配信開始された。 2013年8月20日に英語版を日本・韓国・中国以外の全世界で、韓国語版を韓国で、それぞれGoogle&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;timestamp&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;2020-03-03T09:36:04Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;ns&amp;#34;&lt;/span&gt;: 0,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;長靴猫シリーズ&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;pageid&amp;#34;&lt;/span&gt;: 2623926,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;size&amp;#34;&lt;/span&gt;: 26739,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;wordcount&amp;#34;&lt;/span&gt;: 3221,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;snippet&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;『長靴&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt;シリーズ』（ながぐつねこシリーズ）は、ペローの童話『長靴をはいた&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt;』を原作とする、東映動画（現：東映アニメーション）製作による劇場版長編アニメーション映画シリーズの通称。『長靴をはいた&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt;』（1969年）、『ながぐつ三銃士』（1972年）、『長靴をはいた&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;timestamp&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;2020-02-20T12:09:42Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;ns&amp;#34;&lt;/span&gt;: 0,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;三味線&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;pageid&amp;#34;&lt;/span&gt;: 19199,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;size&amp;#34;&lt;/span&gt;: 17244,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;wordcount&amp;#34;&lt;/span&gt;: 2591,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;snippet&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;三味線（しゃみせん）は、日本の有棹弦楽器。もっぱら弾(はじ)いて演奏される撥弦楽器である。四角状の扁平な木製の胴の両面に&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt;や犬の皮を張り、胴を貫通して伸びる棹に張られた弦を、通常、銀杏形の撥（ばち）で弾き演奏する。 成立は15世紀から16世紀にかけてとされ、戦国時代に琉球（現在の沖縄県）から伝来し&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;timestamp&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;2020-02-26T01:02:18Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;ns&amp;#34;&lt;/span&gt;: 0,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;グーグーだって猫である&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;pageid&amp;#34;&lt;/span&gt;: 1181328,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;size&amp;#34;&lt;/span&gt;: 17396,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;wordcount&amp;#34;&lt;/span&gt;: 1792,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;snippet&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;『グーグーだって&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt;である』（グーグーだってねこである）は大島弓子の漫画作品、およびそれを原作とした映画作品およびテレビドラマ作品。 タイトル・ロールとなっているアメリカンショートヘアの&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt;、「グーグー」を始めとする&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt;たちと作者との生活を綴ったエッセイ漫画。『ヤングロゼ』1996年11月号から1997&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;timestamp&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;2020-02-26T13:44:59Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;ns&amp;#34;&lt;/span&gt;: 0,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;迷い猫オーバーラン!&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;pageid&amp;#34;&lt;/span&gt;: 1727982,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;size&amp;#34;&lt;/span&gt;: 70796,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;wordcount&amp;#34;&lt;/span&gt;: 9877,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;snippet&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;PJ ライトノベル ポータル 文学 『迷い&amp;lt;span class=\&amp;#34;searchmatch\&amp;#34;&amp;gt;猫&amp;lt;/span&amp;gt;オーバーラン！』（まよいねこオーバーラン！）は、松智洋による日本のライトノベル。 集英社スーパーダッシュ文庫より、2008年10月から全12巻が刊行されている。イラストは9巻までぺこが担当していたが、10巻はヤス、11巻は氷川へきる、最終12巻はみつみ美&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;timestamp&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;2020-01-25T04:22:18Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;&lt;a class="link" href="https://ja.wikipedia.org/w/index.php?sort=relevance&amp;amp;search=%E7%8C%AB&amp;amp;title=%E7%89%B9%E5%88%A5:%E6%A4%9C%E7%B4%A2&amp;amp;profile=advanced&amp;amp;fulltext=1&amp;amp;advancedSearch-current=%7B%7D&amp;amp;ns0=1" target="_blank" rel="noopener"
 &gt;WikipediaのUIで検索した場合&lt;/a&gt;と同じような結果が得られることがわかる.&lt;br&gt;
いい感じ.&lt;br&gt;
これでAPIの動作確認は完了.&lt;/p&gt;
&lt;h3 id="goでapiをたたく"&gt;GoでAPIをたたく
&lt;/h3&gt;&lt;p&gt;このままシェルスクリプト化しても便利だと思うんだけど,&lt;br&gt;
今回は&lt;code&gt;Go&lt;/code&gt;の練習としてAPIクライアントっぽく作ってみる.&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;main.go&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;encoding/json&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;flag&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;io/ioutil&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;net/http&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;net/url&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;os&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// JSONをパースするための構造体を定義&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;WikipediaResponse&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;Query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;`json:&amp;#34;query&amp;#34;`&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;SearchInfo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;SearchInfo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;`json:&amp;#34;searchinfo&amp;#34;`&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;Search&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="nx"&gt;Search&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;`json:&amp;#34;search&amp;#34;`&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;SearchInfo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;Totalhits&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;`json:&amp;#34;totalhits&amp;#34;`&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Search&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;Title&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;`json:&amp;#34;title&amp;#34;`&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;PageId&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;`json:&amp;#34;pageid&amp;#34;`&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="c1"&gt;// Snippet string `json:&amp;#34;snippet&amp;#34;`&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="c1"&gt;// 引数チェック&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;language&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;lang&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;ja&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;検索するwikiの言語. default: ja&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;srlimit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;srlimit&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;検索件数. default: 10&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NArg&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;		&lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;検索ワードを指定してください&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;		&lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NFlag&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;		&lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;言語以外のフラグは無効です&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;		&lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;arg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Arg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="c1"&gt;// APIを叩くためのURL作成&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;baseUrl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Scheme&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;http&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;%s.wikipedia.org&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;language&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;w/api.php&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;action&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;query&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;list&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;search&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;srsearch&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;srlimit&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;%d&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;srlimit&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;format&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;json&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RawQuery&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Encode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="c1"&gt;// 記事検索APIを叩く&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;		&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="c1"&gt;// レスポンスをパースする&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ioutil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;wikipediaResponse&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;WikipediaResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Unmarshal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;wikipediaResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="c1"&gt;// ヒットした記事が0件の場合は終了&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;wikipediaResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SearchInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Totalhits&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;		&lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;記事が見つかりませんでした。&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;		&lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="c1"&gt;// 記事タイトルとURLを表示&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;range&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;wikipediaResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Search&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;		&lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;---------------------------------------------------&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;		&lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;		&lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://%s.wikipedia.org/?curid=%d\n&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;language&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PageId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;---------------------------------------------------&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;やったこととしては&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;引数でのクエリパラメータとオプションの受け付け&lt;/li&gt;
&lt;li&gt;リクエストURLの組み立てとAPIへのHTTPリクエストの実行&lt;/li&gt;
&lt;li&gt;レスポンス(JSON)のパース&lt;/li&gt;
&lt;li&gt;必要な情報の表示&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;だけ.&lt;br&gt;
特に難しかったのはAPIを叩く部分とレスポンスのパース部分.&lt;/p&gt;
&lt;p&gt;APIを叩く部分については&lt;a class="link" href="https://golang.org/pkg/net/url/" target="_blank" rel="noopener"
 &gt;&lt;code&gt;net/url&lt;/code&gt;&lt;/a&gt;を使ってURLを組み立てて,&lt;br&gt;
&lt;a class="link" href="https://golang.org/pkg/net/http/" target="_blank" rel="noopener"
 &gt;&lt;code&gt;net/http&lt;/code&gt;&lt;/a&gt;を使ってリクエストを投げるようにした.&lt;br&gt;
基本的にはcurlで叩いたときと同じリクエストを送るようにした.&lt;/p&gt;
&lt;p&gt;公式パッケージ&lt;a class="link" href="https://golang.org/pkg/encoding/json/" target="_blank" rel="noopener"
 &gt;&lt;code&gt;encoding/json&lt;/code&gt;&lt;/a&gt;を使ったJSONのパースは結構面倒で,&lt;br&gt;
事前にJSONの構造を構造体として定義してやる必要がある.&lt;br&gt;
APIのレスポンスはJSONが結構入れ子になっているので書くのが大変だった.&lt;/p&gt;
&lt;p&gt;また, 今回はレスポンスのJSONから記事タイトルとidだけ抜き出して,&lt;br&gt;
&lt;a class="link" href="https://ja.wikipedia.org/?curid=1215264" target="_blank" rel="noopener"
 &gt;https://ja.wikipedia.org/?curid=1215264&lt;/a&gt; の形式にすることでページへのリンクを作成するようにした.&lt;/p&gt;
&lt;p&gt;実際に使ってみるとこんな感じ.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ビルドする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;go.mod main.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go build -o &lt;span class="nv"&gt;$GOPATH&lt;/span&gt;/bin/wikipedia .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# GOPATHがPATHに入っていればwikipediaコマンドを呼び出せる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ wikipedia &lt;span class="s1"&gt;&amp;#39;猫&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ネコ
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://ja.wikipedia.org/?curid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1215264&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;三毛猫ホームズシリーズ
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://ja.wikipedia.org/?curid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;227387&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1905年
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://ja.wikipedia.org/?curid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2506&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;吾輩は猫である
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://ja.wikipedia.org/?curid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;13241&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;猫騙し
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://ja.wikipedia.org/?curid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;229647&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;クイズRPG 魔法使いと黒猫のウィズ
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://ja.wikipedia.org/?curid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2969296&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;長靴猫シリーズ
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://ja.wikipedia.org/?curid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2623926&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;三味線
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://ja.wikipedia.org/?curid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;19199&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;グーグーだって猫である
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://ja.wikipedia.org/?curid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1181328&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;迷い猫オーバーラン!
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://ja.wikipedia.org/?curid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1727982&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 実行時引数でオプションを変えられる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ wikipedia -lang&lt;span class="o"&gt;=&lt;/span&gt;en -srlimit&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;イチロー&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Ichirō
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://en.wikipedia.org/?curid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1067866&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Orix Buffaloes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://en.wikipedia.org/?curid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1145207&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Ichiro Suzuki
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://en.wikipedia.org/?curid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;66417&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;なんかそれっぽいのが作れた.&lt;br&gt;
やったぜ.&lt;/p&gt;
&lt;p&gt;つくったやつはここ.&lt;br&gt;
&lt;a class="link" href="https://github.com/uzimihsr/wikipedia-search" target="_blank" rel="noopener"
 &gt;https://github.com/uzimihsr/wikipedia-search&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;APIクライアントはこんな感じで一度作ってしまえば他にもいろいろできそう.&lt;br&gt;
時間があれば他のAPIにも対応させてwikipedia用のコマンドラインツールみたいなのを作っても面白いかもしれない(需要はなさそう).&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="のび〜をするねこ" class="gallery-image" data-flex-basis="327px" data-flex-grow="136" height="2655" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-03-09-golang-api-client/2020-03-09-sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-03-09-golang-api-client/2020-03-09-sotochan_hu_41f77d427878a1f0.jpg 800w, https://blog.uzimihsr.com/post/2020-03-09-golang-api-client/2020-03-09-sotochan_hu_acd8b165871e9e48.jpg 1600w, https://blog.uzimihsr.com/post/2020-03-09-golang-api-client/2020-03-09-sotochan_hu_89a0e2860508884c.jpg 2400w, https://blog.uzimihsr.com/post/2020-03-09-golang-api-client/2020-03-09-sotochan.jpg 3626w" width="3626"&gt;&lt;/p&gt;</description></item><item><title>Kubernetes完全に理解したい 5章</title><link>https://blog.uzimihsr.com/post/2020-02-26-kubernetes-guide-chap5/</link><pubDate>Wed, 26 Feb 2020 22:10:56 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-02-26-kubernetes-guide-chap5/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-02-26-kubernetes-guide-chap5/2020-02-26-sotochan.jpg" alt="Featured image of post Kubernetes完全に理解したい 5章" /&gt;&lt;h2 id="podとかdeploymentとか"&gt;PodとかDeploymentとか
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://book.impress.co.jp/books/1118101055" target="_blank" rel="noopener"
 &gt;Kubernetes完全ガイド&lt;/a&gt;の続き.&lt;br&gt;
Podとかの話.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="読んだもの"&gt;読んだもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://book.impress.co.jp/books/1118101055" target="_blank" rel="noopener"
 &gt;Kubernetes完全ガイド&lt;/a&gt; 5章(Workloadsリソース)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;重要そうなところとかよく使いそうなところだけまとめる.&lt;/p&gt;
&lt;h2 id="読んだことのまとめ"&gt;読んだことのまとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#pod" &gt;Pod&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#replicaset" &gt;ReplicaSet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#deployment" &gt;Deployment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#daemonset" &gt;DaemonSet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#statefulset" &gt;StatefulSet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#job" &gt;Job&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#cronjob" &gt;CronJob&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="pod"&gt;Pod
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Kubernetes&lt;/code&gt;の最小単位となるリソース.&lt;br&gt;
コンテナの起動を担当する.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;よく使いそうな設定項目&lt;/th&gt;
 &lt;th&gt;説明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.containers[].name&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;任意のコンテナ名&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.containers[].image&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;使用するイメージ&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.containers[].command&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;イメージの&lt;code&gt;ENTRYPOINT&lt;/code&gt;を上書きできる&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.containers[].args&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;イメージの&lt;code&gt;CMD&lt;/code&gt;を上書きできる&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.dnsPolicy&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;クラスタ外のDNSを利用する場合のみ&lt;br&gt;&lt;code&gt;&amp;quot;None&amp;quot;&lt;/code&gt;を指定する&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.dnsConfig&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;.spec.dnsPolicy&lt;/code&gt;が&lt;code&gt;&amp;quot;None&amp;quot;&lt;/code&gt;の場合の詳細な設定&lt;br&gt;(&lt;code&gt;/etc/resolv.conf&lt;/code&gt;に相当)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.hostAliases[]&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;全コンテナの&lt;code&gt;/etc/hosts&lt;/code&gt;を書き換える&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;1つの&lt;code&gt;Pod&lt;/code&gt;には複数のコンテナを内包することができ, それらは同じIPを共有する.&lt;br&gt;
それぞれのコンテナにはポート番号を変えてアクセスできる.&lt;br&gt;
また, &lt;code&gt;Pod&lt;/code&gt;内のコンテナに入って直接操作することもできる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# sample-2podはnginxとredisのコンテナを持つPod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2つのコンテナは同じIP(10.4.2.6)を共有している&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -o wide
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-2pod 2/2 Running &lt;span class="m"&gt;0&lt;/span&gt; 94s 10.4.2.6 gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-0dgf &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 確認のためポート転送する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# localhost:8080 -&amp;gt; sample-2pod:80(nginxが使用)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# localhost:8080 -&amp;gt; sample-2pod:6379(redisが使用)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl port-forward sample-2pod 8080:80 8081:6379
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Forwarding from 127.0.0.1:8080 -&amp;gt; &lt;span class="m"&gt;80&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Forwarding from &lt;span class="o"&gt;[&lt;/span&gt;::1&lt;span class="o"&gt;]&lt;/span&gt;:8080 -&amp;gt; &lt;span class="m"&gt;80&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Forwarding from 127.0.0.1:8081 -&amp;gt; &lt;span class="m"&gt;6379&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Forwarding from &lt;span class="o"&gt;[&lt;/span&gt;::1&lt;span class="o"&gt;]&lt;/span&gt;:8081 -&amp;gt; &lt;span class="m"&gt;6379&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 以下の確認が終わり次第Ctrl+Cで終了&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# nginxへの疎通を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl localhost:8080
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;!DOCTYPE html&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;html&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;head&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;title&amp;gt;Welcome to nginx!&amp;lt;/title&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;style&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; body &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; width: 35em&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; margin: &lt;span class="m"&gt;0&lt;/span&gt; auto&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; font-family: Tahoma, Verdana, Arial, sans-serif&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;/style&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;/head&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;body&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;h1&amp;gt;Welcome to nginx!&amp;lt;/h1&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;p&amp;gt;If you see this page, the nginx web server is successfully installed and
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;working. Further configuration is required.&amp;lt;/p&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;p&amp;gt;For online documentation and support please refer to
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;a &lt;span class="nv"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;http://nginx.org/&amp;#34;&lt;/span&gt;&amp;gt;nginx.org&amp;lt;/a&amp;gt;.&amp;lt;br/&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Commercial support is available at
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;a &lt;span class="nv"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;http://nginx.com/&amp;#34;&lt;/span&gt;&amp;gt;nginx.com&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;Thank you &lt;span class="k"&gt;for&lt;/span&gt; using nginx.&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;/body&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;/html&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# redisへの疎通を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -s telnet://localhost:8081
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;set&lt;/span&gt; key01 value01
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;+OK
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;get key01
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$7&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;value01
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;quit
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;+OK
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Pod内のnginxコンテナに入って環境変数を表示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it sample-2pod -c nginx-container -- /bin/sh -c &lt;span class="s2"&gt;&amp;#34;printenv&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;KUBERNETES_SERVICE_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;443&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;KUBERNETES_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;tcp://10.7.240.1:443
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;HOSTNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample-2pod
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/root
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;TERM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;xterm
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;KUBERNETES_PORT_443_TCP_ADDR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10.7.240.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;NGINX_VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.12.2-1~stretch
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;KUBERNETES_PORT_443_TCP_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;443&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;NJS_VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.12.2.0.1.14-1~stretch
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;KUBERNETES_PORT_443_TCP_PROTO&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;KUBERNETES_SERVICE_PORT_HTTPS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;443&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;KUBERNETES_PORT_443_TCP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;tcp://10.7.240.1:443
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;KUBERNETES_SERVICE_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10.7.240.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;PWD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/be0185d3970f97b3b8d7aaa2a51c07144ab54171/samples/chapter05/sample-2pod.yaml" target="_blank" rel="noopener"
 &gt;sample-2pod.yaml&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;コンテナで使用する&lt;code&gt;Docker image&lt;/code&gt;の&lt;code&gt;ENTRYPOINT&lt;/code&gt;と&lt;code&gt;CMD&lt;/code&gt;は&lt;code&gt;Pod&lt;/code&gt;定義で上書きできる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# .spec.containers[].commandと.spec.containers[].argsを設定したPod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Dockerfile: CMD:[&amp;#34;nginx&amp;#34;, &amp;#34;-g&amp;#34;, &amp;#34;daemon off;&amp;#34;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 上書きした内容: command:[&amp;#34;/bin/sleep&amp;#34;] args:[&amp;#34;3600&amp;#34;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# この場合はnginxが立ち上がらずに3600秒sleepする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-entrypoint 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 45s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ポート転送を行った状態(localhost:8080 -&amp;gt; sample-entrypoint:80)でアクセスしてもnginxが起動していないため何も返らない&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl localhost:8080
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl: &lt;span class="o"&gt;(&lt;/span&gt;52&lt;span class="o"&gt;)&lt;/span&gt; Empty reply from server
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/be0185d3970f97b3b8d7aaa2a51c07144ab54171/samples/chapter05/sample-entrypoint.yaml" target="_blank" rel="noopener"
 &gt;sample-entrypoint.yaml&lt;/a&gt;&lt;br&gt;
&lt;a class="link" href="https://github.com/nginxinc/docker-nginx/blob/e3bbc1131a683dabf868268e62b9d3fbd250191b/stable/alpine/Dockerfile" target="_blank" rel="noopener"
 &gt;Dockerfile(nginx)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Pod&lt;/code&gt;内の全コンテナの&lt;code&gt;/etc/resolv.conf&lt;/code&gt;, &lt;code&gt;/etc/hosts&lt;/code&gt;も&lt;code&gt;Pod&lt;/code&gt;定義で上書きできる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# .spec.dnsConfigを設定したPod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it sample-externaldns cat /etc/resolv.conf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nameserver 8.8.8.8
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nameserver 8.8.4.4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;search example.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;options ndots:5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# .spec.hostAliasesを設定したPod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it sample-hostaliases cat /etc/hosts
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Kubernetes-managed hosts file.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;127.0.0.1	localhost
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;::1	localhost ip6-localhost ip6-loopback
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;fe00::0	ip6-localnet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;fe00::0	ip6-mcastprefix
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;fe00::1	ip6-allnodes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;fe00::2	ip6-allrouters
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;10.4.2.9	sample-hostaliases
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Entries added by HostAliases.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;8.8.8.8	google-dns	google-public-dns
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/master/samples/chapter05/sample-externaldns.yaml" target="_blank" rel="noopener"
 &gt;sample-externaldns.yaml&lt;/a&gt;&lt;br&gt;
&lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/master/samples/chapter05/sample-hostaliases.yaml" target="_blank" rel="noopener"
 &gt;sample-hostaliases.yaml&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="replicaset"&gt;ReplicaSet
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Pod&lt;/code&gt;のレプリカ(複製)を指定した数だけ維持するリソース.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;よく使いそうな設定項目&lt;/th&gt;
 &lt;th&gt;説明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.replicas&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;維持する&lt;code&gt;Pod&lt;/code&gt;の数&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.selector.matchLabels&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;維持する&lt;code&gt;Pod&lt;/code&gt;のラベル&lt;br&gt;基本的に&lt;code&gt;.spec.template.metadata.labels&lt;/code&gt;と同じものを指定する&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.template&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;維持する&lt;code&gt;Pod&lt;/code&gt;の定義&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code&gt;ReplicaSet&lt;/code&gt;は生成時に指定した数の&lt;code&gt;Pod&lt;/code&gt;を作成し, それらをラベルで管理する.&lt;br&gt;
指定したラベルを持つ&lt;code&gt;Pod&lt;/code&gt;の数が&lt;code&gt;ReplicaSet&lt;/code&gt;定義で指定した数より少なくなったときは追加し(セルフヒーリング),&lt;br&gt;
それよりも多くなった場合は削除することで&lt;code&gt;Pod&lt;/code&gt;数を維持する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ReplicaSetが存在している状態&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get replicasets -o wide
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-rs &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; 72s nginx-container nginx:1.12 &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample-app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ReplicaSetによって管理されているPod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample-app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-rs-9vh82 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 6s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-rs-f8922 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 6s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-rs-ql2fq 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 6s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podを手動で削除してみる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl delete pod sample-rs-9vh82
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod &lt;span class="s2"&gt;&amp;#34;sample-rs-9vh82&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Pod数が3より少なくなったためPodが追加される(セルフヒーリング)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample-app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-rs-8f7tm 0/1 ContainerCreating &lt;span class="m"&gt;0&lt;/span&gt; 1s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-rs-9vh82 0/1 Terminating &lt;span class="m"&gt;0&lt;/span&gt; 28s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-rs-f8922 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 28s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-rs-ql2fq 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 28s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample-app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-rs-8f7tm 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 3s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-rs-9vh82 0/1 Terminating &lt;span class="m"&gt;0&lt;/span&gt; 30s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-rs-f8922 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 30s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-rs-ql2fq 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 30s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample-app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-rs-8f7tm 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 9s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-rs-f8922 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 36s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-rs-ql2fq 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 36s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ReplicaSetの.spec.replicasを2に減らす&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl scale rs sample-rs --replicas &lt;span class="m"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Pod数が2より多いので削除される&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample-app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-rs-8f7tm 0/1 Terminating &lt;span class="m"&gt;0&lt;/span&gt; 9m41s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-rs-f8922 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 10m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-rs-ql2fq 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 10m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample-app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-rs-f8922 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 10m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-rs-ql2fq 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 10m
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/master/samples/chapter05/sample-rs.yaml" target="_blank" rel="noopener"
 &gt;sample-rs.yaml&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="deployment"&gt;Deployment
&lt;/h3&gt;&lt;p&gt;複数の&lt;code&gt;ReplicaSet&lt;/code&gt;を管理するリソース.&lt;br&gt;
&lt;code&gt;Pod&lt;/code&gt;と&lt;code&gt;ReplicaSet&lt;/code&gt;の機能を内包しているので基本的にコンテナを扱うときは&lt;code&gt;Deployment&lt;/code&gt;を使用する.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;よく使いそうな設定項目&lt;/th&gt;
 &lt;th&gt;説明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.replicas&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;ReplicaSet&lt;/code&gt;と同じ&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.selector.matchLabels&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;ReplicaSet&lt;/code&gt;と同じ&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.template&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;維持する&lt;code&gt;Pod&lt;/code&gt;の定義&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.strategy.type&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;ローリングアップデートを使用しない場合のみ&lt;br&gt;&lt;code&gt;Recreate&lt;/code&gt;を指定する&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.strategy.rollingUpdate.maxUnavailable&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;ローリングアップデート時に許容できる&lt;br&gt;&lt;code&gt;Pod&lt;/code&gt;の不足数&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.strategy.rollingUpdate.maxSurge&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;ローリングアップデート時に許容できる&lt;br&gt;&lt;code&gt;Pod&lt;/code&gt;の超過数&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code&gt;Pod&lt;/code&gt;の更新を行う際は&lt;code&gt;Deployment&lt;/code&gt;定義で指定した数に対して&lt;br&gt;
許容できる&lt;code&gt;Pod&lt;/code&gt;の不足数~超過数の範囲で&lt;code&gt;Pod&lt;/code&gt;の追加と削除を行う(ローリングアップデート).&lt;br&gt;
これにより常にいくつかの&lt;code&gt;Pod&lt;/code&gt;が稼働しつづけるため,&lt;br&gt;
更新時にダウンタイムが発生しないメリットがある.&lt;br&gt;
このとき, 新しい&lt;code&gt;Pod&lt;/code&gt;は同じタイミングで作成される新しい&lt;code&gt;ReplicaSet&lt;/code&gt;によって管理される.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Deploymentが存在している状態&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get deployment -o wide
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get deployment -o wide
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment 3/3 &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; 11m nginx-container nginx:1.12 &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample-app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get rs -o wide
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6c5948bf66 &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; 17s nginx-container nginx:1.12 &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample-app,pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;6c5948bf66
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample-app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6c5948bf66-4tk5h 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 29s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6c5948bf66-6stnf 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 29s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6c5948bf66-72flm 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 29s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# コンテナイメージを更新する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;set&lt;/span&gt; image deployment sample-deployment nginx-container&lt;span class="o"&gt;=&lt;/span&gt;nginx:1.13
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.extensions/sample-deployment image updated
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podが段階的に更新される(ローリングアップデート)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 新たにReplicaSet(7b4f67c7bc)が作成され, そこに新しいPodが作成される&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get rs --watch
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME DESIRED CURRENT READY AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6c5948bf66 &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; 46s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-7b4f67c7bc &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; 0s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-7b4f67c7bc &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; 0s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-7b4f67c7bc &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; 0s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-7b4f67c7bc &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 2s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6c5948bf66 &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; 55s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-7b4f67c7bc &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 2s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6c5948bf66 &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; 55s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6c5948bf66 &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; 55s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-7b4f67c7bc &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 2s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-7b4f67c7bc &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 2s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-7b4f67c7bc &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; 3s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6c5948bf66 &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; 56s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-7b4f67c7bc &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; 3s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6c5948bf66 &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; 56s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6c5948bf66 &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 56s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-7b4f67c7bc &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; 4s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-7b4f67c7bc &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; 4s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-7b4f67c7bc &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; 5s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6c5948bf66 &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 58s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6c5948bf66 &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 58s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6c5948bf66 &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; 59s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 更新後&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get rs -o wide
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-6c5948bf66 &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; 108s nginx-container nginx:1.12 &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample-app,pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;6c5948bf66
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-7b4f67c7bc &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; 55s nginx-container nginx:1.13 &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample-app,pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;7b4f67c7bc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ReplicaSetと同様にスケーリングも可能&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl scale deployment sample-deployment --replicas &lt;span class="m"&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.extensions/sample-deployment scaled
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample-app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-7b4f67c7bc-28rq4 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 12m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-7b4f67c7bc-ctzmp 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 19s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-7b4f67c7bc-gmcvc 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 12m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-7b4f67c7bc-knx5z 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 12m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-deployment-7b4f67c7bc-vr5m4 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 19s
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/master/samples/chapter05/sample-deployment.yaml" target="_blank" rel="noopener"
 &gt;sample-deployment.yaml&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="daemonset"&gt;DaemonSet
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Pod&lt;/code&gt;を各Nodeに1個ずつ作成, 管理するリソース.&lt;br&gt;
監視などに使用される.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;よく使いそうな設定項目&lt;/th&gt;
 &lt;th&gt;説明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.selector.matchLabels&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;ReplicaSet&lt;/code&gt;と同じ&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.template&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;維持する&lt;code&gt;Pod&lt;/code&gt;の定義&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.updateStrategy.type&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;ローリングアップデートを使用しない場合のみ&lt;br&gt;&lt;code&gt;OnDelete&lt;/code&gt;を指定する&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.updateStrategy.rollingUpdate.maxUnavailable&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;ローリングアップデート時に許容できる&lt;br&gt;&lt;code&gt;Pod&lt;/code&gt;の不足数&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;各Nodeに&lt;code&gt;Pod&lt;/code&gt;を1つずつしか配置できないというルール以外,&lt;br&gt;
&lt;code&gt;Pod&lt;/code&gt;の管理方法は&lt;code&gt;ReplicaSet&lt;/code&gt;と同じ.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Nodeの確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get nodes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME STATUS ROLES AGE VERSION
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-0dgf Ready &amp;lt;none&amp;gt; 66d v1.13.11-gke.14
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-n2mf Ready &amp;lt;none&amp;gt; 66d v1.13.11-gke.14
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-wk64 Ready &amp;lt;none&amp;gt; 66d v1.13.11-gke.14
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# DaemonSetがある状態でPodを確認するとPodが各Nodeに1個ずつ存在している&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get ds
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-ds &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &amp;lt;none&amp;gt; 4s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -o wide -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample-app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-ds-5s6gx 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 4m16s 10.4.1.10 gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-wk64 &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-ds-9qs6j 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 4m16s 10.4.2.17 gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-0dgf &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-ds-srblh 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 4m16s 10.4.0.19 gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-n2mf &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 試しにPodを削除する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl delete pod sample-ds-5s6gx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod &lt;span class="s2"&gt;&amp;#34;sample-ds-5s6gx&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# DaemonSetと同様にセルフヒーリングが起こる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -o wide -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample-app --watch
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-ds-5s6gx 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 6m1s 10.4.1.10 gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-wk64 &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-ds-9qs6j 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 6m1s 10.4.2.17 gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-0dgf &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-ds-srblh 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 6m1s 10.4.0.19 gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-n2mf &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-ds-5s6gx 1/1 Terminating &lt;span class="m"&gt;0&lt;/span&gt; 6m14s 10.4.1.10 gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-wk64 &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-ds-5s6gx 0/1 Terminating &lt;span class="m"&gt;0&lt;/span&gt; 6m15s &amp;lt;none&amp;gt; gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-wk64 &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-ds-5s6gx 0/1 Terminating &lt;span class="m"&gt;0&lt;/span&gt; 6m21s &amp;lt;none&amp;gt; gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-wk64 &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-ds-5s6gx 0/1 Terminating &lt;span class="m"&gt;0&lt;/span&gt; 6m21s &amp;lt;none&amp;gt; gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-wk64 &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-ds-bg2bp 0/1 Pending &lt;span class="m"&gt;0&lt;/span&gt; 0s &amp;lt;none&amp;gt; &amp;lt;none&amp;gt; &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-ds-bg2bp 0/1 Pending &lt;span class="m"&gt;0&lt;/span&gt; 0s &amp;lt;none&amp;gt; gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-wk64 &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-ds-bg2bp 0/1 ContainerCreating &lt;span class="m"&gt;0&lt;/span&gt; 0s &amp;lt;none&amp;gt; gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-wk64 &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-ds-bg2bp 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 1s 10.4.1.11 gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-wk64 &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -o wide -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample-app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-ds-9qs6j 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 11m 10.4.2.17 gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-0dgf &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-ds-bg2bp 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 4m50s 10.4.1.11 gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-wk64 &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-ds-srblh 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 11m 10.4.0.19 gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-n2mf &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/master/samples/chapter05/sample-ds.yaml" target="_blank" rel="noopener"
 &gt;sample-ds.yaml&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="statefulset"&gt;StatefulSet
&lt;/h3&gt;&lt;p&gt;複数の&lt;code&gt;Pod&lt;/code&gt;に番号をつけて管理し, データの永続化を行うリソース.&lt;br&gt;
DBなどに使用される.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;よく使いそうな設定項目&lt;/th&gt;
 &lt;th&gt;説明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.replicas&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;ReplicaSet&lt;/code&gt;と同じ&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.selector.matchLabels&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;ReplicaSet&lt;/code&gt;と同じ&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.template&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;維持する&lt;code&gt;Pod&lt;/code&gt;の定義&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.updateStrategy.type&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;ローリングアップデートを使用しない場合のみ&lt;code&gt;OnDelete&lt;/code&gt;を指定する&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.updateStrategy.rollingUpdate.partition&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;ローリングアップデート時に更新しない&lt;code&gt;Pod&lt;/code&gt;の数&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.volumeClaimTemplates[]&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;各&lt;code&gt;Pod&lt;/code&gt;に紐づく&lt;code&gt;PersistentVolumeClaim&lt;/code&gt;の定義&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;データの永続化には&lt;code&gt;PersistentVolume&lt;/code&gt;を使用する.&lt;br&gt;
&lt;code&gt;PersistentVolume&lt;/code&gt;はPodが無くなっても残り続け,&lt;br&gt;
セルフヒーリングによって同じ番号のPodが作成された場合は自動でマウントされる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# StatefulSetを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f sample-statefulset.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;statefulset.apps/sample-statefulset created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podが順番に作成される&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -o wide -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample-app --watch
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-statefulset-0 0/1 Pending &lt;span class="m"&gt;0&lt;/span&gt; 1s &amp;lt;none&amp;gt; &amp;lt;none&amp;gt; &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-statefulset-0 0/1 Pending &lt;span class="m"&gt;0&lt;/span&gt; 1s &amp;lt;none&amp;gt; gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-wk64 &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-statefulset-0 0/1 ContainerCreating &lt;span class="m"&gt;0&lt;/span&gt; 1s &amp;lt;none&amp;gt; gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-wk64 &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-statefulset-0 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 12s 10.4.1.13 gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-wk64 &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-statefulset-1 0/1 Pending &lt;span class="m"&gt;0&lt;/span&gt; 0s &amp;lt;none&amp;gt; &amp;lt;none&amp;gt; &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-statefulset-1 0/1 Pending &lt;span class="m"&gt;0&lt;/span&gt; 0s &amp;lt;none&amp;gt; gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-0dgf &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-statefulset-1 0/1 ContainerCreating &lt;span class="m"&gt;0&lt;/span&gt; 0s &amp;lt;none&amp;gt; gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-0dgf &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-statefulset-1 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 10s 10.4.2.19 gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-0dgf &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-statefulset-2 0/1 Pending &lt;span class="m"&gt;0&lt;/span&gt; 0s &amp;lt;none&amp;gt; &amp;lt;none&amp;gt; &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-statefulset-2 0/1 Pending &lt;span class="m"&gt;0&lt;/span&gt; 0s &amp;lt;none&amp;gt; gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-n2mf &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-statefulset-2 0/1 ContainerCreating &lt;span class="m"&gt;0&lt;/span&gt; 0s &amp;lt;none&amp;gt; gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-n2mf &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-statefulset-2 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 11s 10.4.0.21 gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-n2mf &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -o wide -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample-app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-statefulset-0 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 5m58s 10.4.1.13 gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-wk64 &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-statefulset-1 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 5m46s 10.4.2.19 gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-0dgf &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-statefulset-2 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 5m36s 10.4.0.21 gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-n2mf &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 同時にPersistentVolume(永続化領域)が作成されている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get persistentvolumeclaims
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;www-sample-statefulset-0 Bound pvc-c325de12-53e6-11ea-9451-42010a8a005a 1Gi RWO standard 8m36s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;www-sample-statefulset-1 Bound pvc-cba6642f-53e6-11ea-9451-42010a8a005a 1Gi RWO standard 8m21s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;www-sample-statefulset-2 Bound pvc-d3f4bbce-53e6-11ea-9451-42010a8a005a 1Gi RWO standard 8m7s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get persistentvolumes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pvc-c325de12-53e6-11ea-9451-42010a8a005a 1Gi RWO Delete Bound default/www-sample-statefulset-0 standard 8m48s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pvc-cba6642f-53e6-11ea-9451-42010a8a005a 1Gi RWO Delete Bound default/www-sample-statefulset-1 standard 8m34s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pvc-d3f4bbce-53e6-11ea-9451-42010a8a005a 1Gi RWO Delete Bound default/www-sample-statefulset-2 standard 8m20s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 試しにPodにマウント(/usr/share/nginx/html)されたPersistentVolumeにファイルを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it sample-statefulset-1 touch /usr/share/nginx/html/hoge.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it sample-statefulset-0 ls /usr/share/nginx/html
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;lost+found
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it sample-statefulset-1 ls /usr/share/nginx/html
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hoge.txt lost+found
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it sample-statefulset-2 ls /usr/share/nginx/html
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;lost+found
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podを削除してみる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl delete pod sample-statefulset-1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod &lt;span class="s2"&gt;&amp;#34;sample-statefulset-1&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ReplicaSetと同様にセルフヒーリングが起こる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -o wide -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample-app --watch
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-statefulset-0 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 15m 10.4.1.13 gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-wk64 &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-statefulset-1 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 14m 10.4.2.19 gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-0dgf &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-statefulset-2 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 14m 10.4.0.21 gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-n2mf &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-statefulset-1 1/1 Terminating &lt;span class="m"&gt;0&lt;/span&gt; 15m 10.4.2.19 gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-0dgf &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-statefulset-1 0/1 Terminating &lt;span class="m"&gt;0&lt;/span&gt; 15m 10.4.2.19 gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-0dgf &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-statefulset-1 0/1 Terminating &lt;span class="m"&gt;0&lt;/span&gt; 15m 10.4.2.19 gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-0dgf &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-statefulset-1 0/1 Terminating &lt;span class="m"&gt;0&lt;/span&gt; 15m 10.4.2.19 gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-0dgf &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-statefulset-1 0/1 Pending &lt;span class="m"&gt;0&lt;/span&gt; 0s &amp;lt;none&amp;gt; &amp;lt;none&amp;gt; &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-statefulset-1 0/1 Pending &lt;span class="m"&gt;0&lt;/span&gt; 0s &amp;lt;none&amp;gt; gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-0dgf &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-statefulset-1 0/1 ContainerCreating &lt;span class="m"&gt;0&lt;/span&gt; 0s &amp;lt;none&amp;gt; gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-0dgf &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-statefulset-1 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 11s 10.4.2.20 gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-0dgf &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 新しく作成されたPodに同じPersistentVolumeがマウントされるのでファイルが残っている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it sample-statefulset-1 ls /usr/share/nginx/html
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hoge.txt lost+found
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# StatefulSetごとPodを全削除してみる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl delete statefulsets sample-statefulset
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;statefulset.apps &lt;span class="s2"&gt;&amp;#34;sample-statefulset&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# StatefulSetが消えてもPersistentVolumeは残る&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get persistentvolumes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pvc-c325de12-53e6-11ea-9451-42010a8a005a 1Gi RWO Delete Bound default/www-sample-statefulset-0 standard 22m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pvc-cba6642f-53e6-11ea-9451-42010a8a005a 1Gi RWO Delete Bound default/www-sample-statefulset-1 standard 22m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pvc-d3f4bbce-53e6-11ea-9451-42010a8a005a 1Gi RWO Delete Bound default/www-sample-statefulset-2 standard 22m
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/master/samples/chapter05/sample-statefulset.yaml" target="_blank" rel="noopener"
 &gt;sample-statefulset.yaml&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="job"&gt;Job
&lt;/h3&gt;&lt;p&gt;使い切りの&lt;code&gt;Pod&lt;/code&gt;を作成するリソース.&lt;br&gt;
バッチ処理などに使用される.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;よく使いそうな設定項目&lt;/th&gt;
 &lt;th&gt;説明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.completions&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Pod&lt;/code&gt;が正常終了する回数の上限&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.parallelism&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;並列に動かす&lt;code&gt;Pod&lt;/code&gt;の数&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.backoffLimit&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Pod&lt;/code&gt;が失敗する回数の上限&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.activeDeadlineSeconds&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Job&lt;/code&gt;の制限時間&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.template&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;実行する&lt;code&gt;Pod&lt;/code&gt;の定義&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.template.restartPolicy&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Pod&lt;/code&gt;失敗時の挙動&lt;br&gt;&lt;code&gt;Never&lt;/code&gt; : 新たに&lt;code&gt;Pod&lt;/code&gt;を作成&lt;br&gt;&lt;code&gt;OnFailure&lt;/code&gt; : 同じ&lt;code&gt;Pod&lt;/code&gt;を再実行&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code&gt;Pod&lt;/code&gt;が正常終了する(終了ステータス0を返す)前提で使用する.&lt;br&gt;
指定した数の&lt;code&gt;Pod&lt;/code&gt;が正常終了した場合に&lt;code&gt;Job&lt;/code&gt;が完了扱いとなる.&lt;br&gt;
失敗回数の上限や制限時間を超過した場合は&lt;code&gt;Job&lt;/code&gt;が失敗となる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 60秒sleepするJobを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f sample-job.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;job.batch/sample-job created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podが起動し60秒後にCompletedとなる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods --watch
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-job-7k6bs 0/1 Pending &lt;span class="m"&gt;0&lt;/span&gt; 0s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-job-7k6bs 0/1 Pending &lt;span class="m"&gt;0&lt;/span&gt; 0s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-job-7k6bs 0/1 ContainerCreating &lt;span class="m"&gt;0&lt;/span&gt; 0s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-job-7k6bs 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 13s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-job-7k6bs 0/1 Completed &lt;span class="m"&gt;0&lt;/span&gt; 73s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 30秒sleepするJobを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 合計10回成功するまでPodを2個並列で実行する設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f sample-paralleljob.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;job.batch/sample-paralleljob created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods --watch
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-npscc 0/1 Pending &lt;span class="m"&gt;0&lt;/span&gt; 0s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-2vlfk 0/1 Pending &lt;span class="m"&gt;0&lt;/span&gt; 0s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-npscc 0/1 ContainerCreating &lt;span class="m"&gt;0&lt;/span&gt; 0s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-2vlfk 0/1 ContainerCreating &lt;span class="m"&gt;0&lt;/span&gt; 0s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-npscc 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 2s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-2vlfk 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 2s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-2vlfk 0/1 Completed &lt;span class="m"&gt;0&lt;/span&gt; 33s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-262xj 0/1 Pending &lt;span class="m"&gt;0&lt;/span&gt; 0s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-262xj 0/1 ContainerCreating &lt;span class="m"&gt;0&lt;/span&gt; 0s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-npscc 0/1 Completed &lt;span class="m"&gt;0&lt;/span&gt; 33s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-p755p 0/1 Pending &lt;span class="m"&gt;0&lt;/span&gt; 0s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-p755p 0/1 ContainerCreating &lt;span class="m"&gt;0&lt;/span&gt; 0s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-p755p 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 2s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-262xj 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 2s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-p755p 0/1 Completed &lt;span class="m"&gt;0&lt;/span&gt; 32s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-dk5fg 0/1 Pending &lt;span class="m"&gt;0&lt;/span&gt; 0s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-dk5fg 0/1 ContainerCreating &lt;span class="m"&gt;0&lt;/span&gt; 0s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-262xj 0/1 Completed &lt;span class="m"&gt;0&lt;/span&gt; 32s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-jbmdm 0/1 Pending &lt;span class="m"&gt;0&lt;/span&gt; 0s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-jbmdm 0/1 ContainerCreating &lt;span class="m"&gt;0&lt;/span&gt; 0s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-jbmdm 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 3s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-dk5fg 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 3s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-jbmdm 0/1 Completed &lt;span class="m"&gt;0&lt;/span&gt; 33s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-gnmsk 0/1 Pending &lt;span class="m"&gt;0&lt;/span&gt; 0s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-dk5fg 0/1 Completed &lt;span class="m"&gt;0&lt;/span&gt; 33s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-6qr2q 0/1 Pending &lt;span class="m"&gt;0&lt;/span&gt; 0s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-gnmsk 0/1 ContainerCreating &lt;span class="m"&gt;0&lt;/span&gt; 0s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-6qr2q 0/1 ContainerCreating &lt;span class="m"&gt;0&lt;/span&gt; 0s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-6qr2q 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 2s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-gnmsk 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 2s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-6qr2q 0/1 Completed &lt;span class="m"&gt;0&lt;/span&gt; 33s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-6hdkq 0/1 Pending &lt;span class="m"&gt;0&lt;/span&gt; 1s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-gnmsk 0/1 Completed &lt;span class="m"&gt;0&lt;/span&gt; 33s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-pp8pz 0/1 Pending &lt;span class="m"&gt;0&lt;/span&gt; 0s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-6hdkq 0/1 ContainerCreating &lt;span class="m"&gt;0&lt;/span&gt; 1s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-pp8pz 0/1 ContainerCreating &lt;span class="m"&gt;0&lt;/span&gt; 0s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-pp8pz 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 2s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-6hdkq 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 3s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-6hdkq 0/1 Completed &lt;span class="m"&gt;0&lt;/span&gt; 33s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-paralleljob-pp8pz 0/1 Completed &lt;span class="m"&gt;0&lt;/span&gt; 32s
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/master/samples/chapter05/sample-job.yaml" target="_blank" rel="noopener"
 &gt;sample-job.yaml&lt;/a&gt;&lt;br&gt;
&lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/master/samples/chapter05/sample-paralleljob.yaml" target="_blank" rel="noopener"
 &gt;sample-paralleljob.yaml&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="cronjob"&gt;CronJob
&lt;/h3&gt;&lt;p&gt;設定されたスケジュールに基づいて&lt;code&gt;Job&lt;/code&gt;を実行するリソース.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;よく使いそうな設定項目&lt;/th&gt;
 &lt;th&gt;説明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.schedule&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Job&lt;/code&gt;を実行するスケジュール&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.concurrencyPolicy&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;実行中の&lt;code&gt;Job&lt;/code&gt;が終わる前に&lt;br&gt;次の実行タイミングになったときの挙動&lt;br&gt;&lt;code&gt;Allow&lt;/code&gt; : 次の&lt;code&gt;Job&lt;/code&gt;を実行&lt;br&gt;&lt;code&gt;Forbid&lt;/code&gt; : 次の&lt;code&gt;Job&lt;/code&gt;を実行しない&lt;br&gt;&lt;code&gt;Replace&lt;/code&gt; : 実行中の&lt;code&gt;Job&lt;/code&gt;を中止して次の&lt;code&gt;Job&lt;/code&gt;を実行&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.startingDeadlineSeconds&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;開始時刻が&lt;code&gt;.spec.schedule&lt;/code&gt;より遅れる場合に許容できる秒数&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.successfulJobsHistoryLimit&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;成功した&lt;code&gt;Job&lt;/code&gt;を保存する数の上限&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.failedJobsHistoryLimit&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;失敗した&lt;code&gt;Job&lt;/code&gt;を保存する数の上限&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.suspend&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;CronJob&lt;/code&gt;を停止するかどうかの設定&lt;br&gt;(&lt;code&gt;true&lt;/code&gt;/&lt;code&gt;false&lt;/code&gt;)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;.spec.jobTemplate&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;実行する&lt;code&gt;Job&lt;/code&gt;の定義&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# CronJobを起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f sample-cronjob.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# .spec.scheduleに設定したタイミングでJobが実行される&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get &lt;span class="nb"&gt;jobs&lt;/span&gt; --watch
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME COMPLETIONS DURATION AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-cronjob-1582722300 0/1 1s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-cronjob-1582722300 0/1 1s 1s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-cronjob-1582722300 0/1 43s 43s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-cronjob-1582722360 0/1 0s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-cronjob-1582722360 0/1 0s 0s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-cronjob-1582722300 1/1 85s 85s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-cronjob-1582722360 1/1 41s 41s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-cronjob-1582722420 0/1 0s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-cronjob-1582722420 0/1 0s 0s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-cronjob-1582722420 0/1 42s 42s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-cronjob-1582722480 0/1 1s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-cronjob-1582722480 0/1 0s 1s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-cronjob-1582722420 0/1 94s 94s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-cronjob-1582722480 1/1 42s 43s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-cronjob-1582722540 0/1 0s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-cronjob-1582722540 0/1 0s 0s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-cronjob-1582722540 1/1 41s 42s
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="しもべのお腹の上には乗ってくれるけどなぜかお尻を向けてくるにゃーにゃ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-02-26-kubernetes-guide-chap5/2020-02-26-sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-02-26-kubernetes-guide-chap5/2020-02-26-sotochan_hu_44a1164da695ee64.jpg 800w, https://blog.uzimihsr.com/post/2020-02-26-kubernetes-guide-chap5/2020-02-26-sotochan_hu_4e3000d25f595563.jpg 1600w, https://blog.uzimihsr.com/post/2020-02-26-kubernetes-guide-chap5/2020-02-26-sotochan_hu_dc30d8c4acc61688.jpg 2400w, https://blog.uzimihsr.com/post/2020-02-26-kubernetes-guide-chap5/2020-02-26-sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>Prometheusとかをnginxでリバースプロキシした</title><link>https://blog.uzimihsr.com/post/2020-01-29-nginx/</link><pubDate>Wed, 29 Jan 2020 21:52:57 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-01-29-nginx/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-01-29-nginx/2020-01-29-sotochan.jpg" alt="Featured image of post Prometheusとかをnginxでリバースプロキシした" /&gt;&lt;h2 id="リバースプロキシ"&gt;リバースプロキシ
&lt;/h2&gt;&lt;p&gt;最近監視用にラズパイ上でいろいろ動かしてるけど, だんだんポート番号を覚えきれなくなってきたのでいい感じにリバースプロキシした.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;ラズパイにnginxを突っ込んでリバースプロキシにした&lt;/li&gt;
&lt;li&gt;リクエストパスを使った監視関係へのリバースプロキシの設定がちょっと面倒だった&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Raspberry Pi 3 Model B+
&lt;ul&gt;
&lt;li&gt;OSはRaspbian(10.0)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Prometheus
&lt;ul&gt;
&lt;li&gt;version 2.15.2&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2020-01-15-prometheus-grafana-raspberry-pi/" target="_blank" rel="noopener"
 &gt;インストール済み&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Grafana
&lt;ul&gt;
&lt;li&gt;v6.5.2&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2020-01-15-prometheus-grafana-raspberry-pi/" target="_blank" rel="noopener"
 &gt;インストール済み&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Alertmanager
&lt;ul&gt;
&lt;li&gt;version 0.20.0&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2020-01-27-alertmanager-gmail/" target="_blank" rel="noopener"
 &gt;インストール済み&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;nginx
&lt;ul&gt;
&lt;li&gt;今回入れる&lt;/li&gt;
&lt;li&gt;リバースプロキシとして使用&lt;/li&gt;
&lt;li&gt;version 1.14.2&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="構成"&gt;構成
&lt;/h2&gt;&lt;p&gt;&lt;img alt="component" class="gallery-image" data-flex-basis="483px" data-flex-grow="201" height="1069" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-29-nginx/2020-01-29-component.png" srcset="https://blog.uzimihsr.com/post/2020-01-29-nginx/2020-01-29-component_hu_2cfd9c77b7bc126.png 800w, https://blog.uzimihsr.com/post/2020-01-29-nginx/2020-01-29-component_hu_87609969f0af4b7d.png 1600w, https://blog.uzimihsr.com/post/2020-01-29-nginx/2020-01-29-component.png 2155w" width="2155"&gt;&lt;br&gt;
Icons made by &lt;a href="https://www.flaticon.com/authors/smashicons" title="Smashicons"&gt;Smashicons&lt;/a&gt; from &lt;a href="https://www.flaticon.com/" title="Flaticon"&gt; &lt;a class="link" href="https://www.flaticon.com" target="_blank" rel="noopener"
 &gt;www.flaticon.com&lt;/a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;現在ラズパイ上のPrometheus等のUIにアクセスする場合, &lt;strong&gt;192.168.3.200:9090&lt;/strong&gt; のように&lt;br&gt;
各アプリが起動しているポート番号を指定してアクセスしているが,&lt;br&gt;
アプリのポート番号なんてすぐ忘れちゃう(バカ)のでラズパイ側でnginxを立ててリバースプロキシをかけることにする.&lt;br&gt;
リバースプロキシは8080番ポートでリクエストを受けて, パス(/prometheus)によってアクセスするアプリを変えるようにする.&lt;br&gt;
(例: &lt;strong&gt;192.168.3.200:8080/prometheus&lt;/strong&gt; 宛のリクエストに &lt;strong&gt;192.168.3.200:9090&lt;/strong&gt; で動くアプリのレスポンスを返す)&lt;br&gt;
ポート番号よりはパスのほうが覚えやすいので便利になる. はず&amp;hellip;&lt;br&gt;
Node exporterはUIがないので今回は対象外.&lt;/p&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#nginx%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" &gt;nginxのインストール&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%aa%e3%83%90%e3%83%bc%e3%82%b9%e3%83%97%e3%83%ad%e3%82%ad%e3%82%b7%e3%81%ae%e8%a8%ad%e5%ae%9a" &gt;リバースプロキシの設定&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="nginxのインストール"&gt;nginxのインストール
&lt;/h3&gt;&lt;p&gt;nginxのインストール自体は簡単. aptで入れるだけ.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# nginxのインストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt install nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# service起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl start nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ systemctl status nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;● nginx.service - A high performance web server and a reverse proxy server
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Loaded: loaded &lt;span class="o"&gt;(&lt;/span&gt;/lib/systemd/system/nginx.service&lt;span class="p"&gt;;&lt;/span&gt; enabled&lt;span class="p"&gt;;&lt;/span&gt; vendor preset: enabled&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Active: active &lt;span class="o"&gt;(&lt;/span&gt;running&lt;span class="o"&gt;)&lt;/span&gt; since Tue 2020-01-28 22:12:54 JST&lt;span class="p"&gt;;&lt;/span&gt; 7min ago
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Docs: man:nginx&lt;span class="o"&gt;(&lt;/span&gt;8&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Process: &lt;span class="m"&gt;23808&lt;/span&gt; &lt;span class="nv"&gt;ExecStartPre&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/sbin/nginx -t -q -g daemon on&lt;span class="p"&gt;;&lt;/span&gt; master_process on&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;exited, &lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0/SUCCESS&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Process: &lt;span class="m"&gt;23809&lt;/span&gt; &lt;span class="nv"&gt;ExecStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/sbin/nginx -g daemon on&lt;span class="p"&gt;;&lt;/span&gt; master_process on&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;exited, &lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0/SUCCESS&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Main PID: &lt;span class="m"&gt;23810&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;nginx&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Tasks: &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;limit: 2200&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Memory: 3.5M
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; CGroup: /system.slice/nginx.service
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ├─23810 nginx: master process /usr/sbin/nginx -g daemon on&lt;span class="p"&gt;;&lt;/span&gt; master_process on&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ├─23811 nginx: worker process
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ├─23812 nginx: worker process
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ├─23813 nginx: worker process
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └─23814 nginx: worker process
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Jan &lt;span class="m"&gt;28&lt;/span&gt; 22:12:54 raspberrypi systemd&lt;span class="o"&gt;[&lt;/span&gt;1&lt;span class="o"&gt;]&lt;/span&gt;: Starting A high performance web server and a reverse proxy server...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Jan &lt;span class="m"&gt;28&lt;/span&gt; 22:12:54 raspberrypi systemd&lt;span class="o"&gt;[&lt;/span&gt;1&lt;span class="o"&gt;]&lt;/span&gt;: Started A high performance web server and a reverse proxy server.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;試しに&lt;code&gt;&amp;lt;ラズパイのIP&amp;gt;:80&lt;/code&gt;にアクセスするとnginxの初期画面のhtmlが表示される. かんたん.&lt;/p&gt;
&lt;p&gt;&lt;img alt="nginx" class="gallery-image" data-flex-basis="1249px" data-flex-grow="520" height="553" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-29-nginx/2020-01-29-sc01.png" srcset="https://blog.uzimihsr.com/post/2020-01-29-nginx/2020-01-29-sc01_hu_9c2c10875eaacd59.png 800w, https://blog.uzimihsr.com/post/2020-01-29-nginx/2020-01-29-sc01_hu_9c75b703d6103095.png 1600w, https://blog.uzimihsr.com/post/2020-01-29-nginx/2020-01-29-sc01_hu_ac51d7462a8fa949.png 2400w, https://blog.uzimihsr.com/post/2020-01-29-nginx/2020-01-29-sc01.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;h3 id="リバースプロキシの設定"&gt;リバースプロキシの設定
&lt;/h3&gt;&lt;p&gt;このnginxをリバースプロキシとして使うための設定をする.&lt;br&gt;
デフォルトで作成されているnginxの設定ファイル&lt;code&gt;/etc/nginx/nginx.conf&lt;/code&gt;は&lt;br&gt;
&lt;code&gt;/etc/nginx/conf.d/*.conf&lt;/code&gt;を読み込むようになっているので,&lt;br&gt;
新たに&lt;code&gt;/etc/nginx/conf.d/default.conf&lt;/code&gt;(名前は何でも良い)を作成する.&lt;br&gt;
今回は8080番ポートで受けてパス(location)により各アプリのポートに割り振るリバースプロキシを設定する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# nginxの設定ファイルを確認する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 編集はしない &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat /etc/nginx/nginx.conf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# リバースプロキシ設定を作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo vim /etc/nginx/conf.d/default.conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;details&gt;&lt;summary&gt;nginx.conf(初期設定のまま)&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-nginx" data-lang="nginx"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;user&lt;/span&gt; &lt;span class="s"&gt;www-data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;worker_processes&lt;/span&gt; &lt;span class="s"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;pid&lt;/span&gt; &lt;span class="s"&gt;/run/nginx.pid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;include&lt;/span&gt; &lt;span class="n"&gt;/etc/nginx/modules-enabled/*.conf&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;events&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="kn"&gt;worker_connections&lt;/span&gt; &lt;span class="mi"&gt;768&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="c1"&gt;# multi_accept on;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;http&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="c1"&gt;##
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="c1"&gt;# Basic Settings
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="c1"&gt;##
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="kn"&gt;sendfile&lt;/span&gt; &lt;span class="no"&gt;on&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="kn"&gt;tcp_nopush&lt;/span&gt; &lt;span class="no"&gt;on&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="kn"&gt;tcp_nodelay&lt;/span&gt; &lt;span class="no"&gt;on&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="kn"&gt;keepalive_timeout&lt;/span&gt; &lt;span class="mi"&gt;65&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="kn"&gt;types_hash_max_size&lt;/span&gt; &lt;span class="mi"&gt;2048&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="c1"&gt;# server_tokens off;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="c1"&gt;# server_names_hash_bucket_size 64;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="c1"&gt;# server_name_in_redirect off;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="kn"&gt;include&lt;/span&gt; &lt;span class="s"&gt;/etc/nginx/mime.types&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="kn"&gt;default_type&lt;/span&gt; &lt;span class="s"&gt;application/octet-stream&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="c1"&gt;##
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="c1"&gt;# SSL Settings
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="c1"&gt;##
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="kn"&gt;ssl_protocols&lt;/span&gt; &lt;span class="s"&gt;TLSv1&lt;/span&gt; &lt;span class="s"&gt;TLSv1.1&lt;/span&gt; &lt;span class="s"&gt;TLSv1.2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# Dropping SSLv3, ref: POODLE
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="kn"&gt;ssl_prefer_server_ciphers&lt;/span&gt; &lt;span class="no"&gt;on&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="c1"&gt;##
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="c1"&gt;# Logging Settings
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="c1"&gt;##
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="kn"&gt;access_log&lt;/span&gt; &lt;span class="s"&gt;/var/log/nginx/access.log&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="kn"&gt;error_log&lt;/span&gt; &lt;span class="s"&gt;/var/log/nginx/error.log&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="c1"&gt;##
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="c1"&gt;# Gzip Settings
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="c1"&gt;##
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="kn"&gt;gzip&lt;/span&gt; &lt;span class="no"&gt;on&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="c1"&gt;# gzip_vary on;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="c1"&gt;# gzip_proxied any;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="c1"&gt;# gzip_comp_level 6;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="c1"&gt;# gzip_buffers 16 8k;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="c1"&gt;# gzip_http_version 1.1;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="c1"&gt;# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="c1"&gt;##
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="c1"&gt;# Virtual Host Configs
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="c1"&gt;##
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="c1"&gt;# ここでdefault.confを参照する
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="kn"&gt;include&lt;/span&gt; &lt;span class="s"&gt;/etc/nginx/conf.d/*.conf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="kn"&gt;include&lt;/span&gt; &lt;span class="s"&gt;/etc/nginx/sites-enabled/*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;default.conf&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-nginx" data-lang="nginx"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="kn"&gt;listen&lt;/span&gt;	&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/prometheus/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="kn"&gt;proxy_pass&lt;/span&gt;	&lt;span class="s"&gt;http://localhost:9090/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/alertmanager/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="kn"&gt;proxy_pass&lt;/span&gt;	&lt;span class="s"&gt;http://localhost:9093/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/grafana/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="kn"&gt;proxy_pass&lt;/span&gt;	&lt;span class="s"&gt;http://localhost:3000/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;また, このリバースプロキシが効くように各アプリの外部URL(nginxが見るやつ)を変える必要がある.&lt;br&gt;
どれも起動時に読み込むオプションで指定できるので, 設定ファイルを編集する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 各アプリのserviceファイルを修正する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Prometheus&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo vim /etc/systemd/system/prometheus.service
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Alertmanager&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo vim /etc/systemd/system/alertmanager.service
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Grafanaだけはパッケージインストールしたので別の設定ファイルを編集する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo vim /etc/grafana/grafana.ini
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;details&gt;&lt;summary&gt;prometheus.service&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-service" data-lang="service"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Unit]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Prometheus Server&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Service]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;User&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;prometheus&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;ExecStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/local/prometheus/prometheus &lt;/span&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; --config.file=/usr/local/prometheus/prometheus.yml &lt;/span&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; --storage.tsdb.path=/var/lib/prometheus/data &lt;/span&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; --web.external-url=http://localhost:8080/prometheus/ &lt;/span&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; --web.route-prefix=/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Install]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;WantedBy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;multi-user.target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;alertmanager.service&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-service" data-lang="service"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Unit]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Alertmanager&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Service]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;User&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;alertmanager&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;ExecStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/local/alertmanager/alertmanager &lt;/span&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; --config.file=/usr/local/alertmanager/alertmanager.yml &lt;/span&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; --storage.path=/var/lib/alertmanager/data &lt;/span&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; --web.external-url=http://localhost:8080/alertmanager/ &lt;/span&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; --web.route-prefix=/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Install]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;WantedBy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;multi-user.target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;grafana.ini(一部抜粋)&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[server]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# The public facing domain name used to access grafana from a browser&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;domain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;localhost&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# The full public facing url you use in browser, used for redirects and emails&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# If you use reverse proxy and sub path specify full url (with sub path)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;root_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;%(protocol)s://%(domain)s/grafana/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;PrometheusとAlertmanagerの設定はほぼ同じ.&lt;br&gt;
重要なのはnginxから見える外部URLのフラグ&lt;code&gt;--web.external-url&lt;/code&gt;の設定で&lt;br&gt;
実際に起動している場所(&lt;strong&gt;localhost:9090&lt;/strong&gt;, &lt;strong&gt;localhost:9093&lt;/strong&gt;)とは違うパス(&lt;strong&gt;localhost:8080/prometheus&lt;/strong&gt;, &lt;strong&gt;localhost:8080/alertmanager&lt;/strong&gt;)からアクセスできるようにしていることと,&lt;br&gt;
Prometheus(Alertmanager)がリクエストを処理するルートパスのフラグ&lt;code&gt;--web.route-prefix&lt;/code&gt;を &lt;strong&gt;/&lt;/strong&gt; のみにすることで&lt;br&gt;
リバースプロキシを経由する場合としない場合で同じルートパスを扱えるようにしていることである.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;--web.route-prefixを指定しない例(Prometheus):
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;--web.route-prefixはデフォルトだと--web.external-urlのパス(/prometheus/)と同じになってしまうため,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;リバースプロキシを経由しない場合のリクエストが処理できない.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nginxを経由せずlocalhost内のアプリ同士で通信する場合などに不便.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;リクエスト 処理
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;localhost:8080/prometheus/metrics -&amp;gt; /metrics(リバースプロキシ)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;localhost:9090/metrics -&amp;gt; ルートパスが/prometheus/でないため解釈できずBad Request
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;localhost:9090/prometheus/metrics -&amp;gt; /metrics(リバースプロキシなし), しかし不便
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Grafanaの設定も似たようなことをやっていて,&lt;br&gt;
こちらは &lt;strong&gt;localhost:8080/grafana&lt;/strong&gt; でアクセスできるようになっているが,&lt;br&gt;
リバースプロキシをかけない場合(&lt;strong&gt;localhost:3000&lt;/strong&gt;)はエラーになる.&lt;br&gt;
(ただしGrafanaに人間以外がアクセスすることはほとんど無いのでPrometheusの場合と違って困ることはない)&lt;/p&gt;
&lt;p&gt;このあたりはかなり難しかったので以下の記事を参考にした.&lt;br&gt;
&lt;a class="link" href="https://www.robustperception.io/external-urls-and-path-prefixes" target="_blank" rel="noopener"
 &gt;https://www.robustperception.io/external-urls-and-path-prefixes&lt;/a&gt;&lt;br&gt;
&lt;a class="link" href="https://grafana.com/docs/grafana/latest/installation/behind_proxy/" target="_blank" rel="noopener"
 &gt;https://grafana.com/docs/grafana/latest/installation/behind_proxy/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ここまで設定できたら, 各サービスを再起動する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# serviceファイルが書き換わっているのでリロード&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl daemon-reload
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 全部まとめて再起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl restart prometheus alertmanager grafana-server nginx
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;試しに&lt;code&gt;&amp;lt;ラズパイのIP&amp;gt;:8080/prometheus&lt;/code&gt;, &lt;code&gt;&amp;lt;ラズパイのIP&amp;gt;:8080/alertmanager&lt;/code&gt;, &lt;code&gt;&amp;lt;ラズパイのIP&amp;gt;:8080/grafana&lt;/code&gt;にそれぞれアクセスするとそれぞれのUIが開く.&lt;/p&gt;
&lt;p&gt;&lt;img alt="prometheus" class="gallery-image" data-flex-basis="691px" data-flex-grow="288" height="1000" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-29-nginx/2020-01-29-sc02.png" srcset="https://blog.uzimihsr.com/post/2020-01-29-nginx/2020-01-29-sc02_hu_24f8c0280908a619.png 800w, https://blog.uzimihsr.com/post/2020-01-29-nginx/2020-01-29-sc02_hu_a507970195ec520f.png 1600w, https://blog.uzimihsr.com/post/2020-01-29-nginx/2020-01-29-sc02_hu_f2ada404971ffbc9.png 2400w, https://blog.uzimihsr.com/post/2020-01-29-nginx/2020-01-29-sc02.png 2880w" width="2880"&gt;&lt;br&gt;
&lt;img alt="alertmanager" class="gallery-image" data-flex-basis="755px" data-flex-grow="314" height="915" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-29-nginx/2020-01-29-sc03.png" srcset="https://blog.uzimihsr.com/post/2020-01-29-nginx/2020-01-29-sc03_hu_549272cad0ea96a7.png 800w, https://blog.uzimihsr.com/post/2020-01-29-nginx/2020-01-29-sc03_hu_b8fdda79a9ac31a9.png 1600w, https://blog.uzimihsr.com/post/2020-01-29-nginx/2020-01-29-sc03_hu_2e82e31bab0cdf75.png 2400w, https://blog.uzimihsr.com/post/2020-01-29-nginx/2020-01-29-sc03.png 2880w" width="2880"&gt;&lt;br&gt;
&lt;img alt="grafana" class="gallery-image" data-flex-basis="402px" data-flex-grow="167" height="1716" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-29-nginx/2020-01-29-sc04.png" srcset="https://blog.uzimihsr.com/post/2020-01-29-nginx/2020-01-29-sc04_hu_dbf92c8878aa6d73.png 800w, https://blog.uzimihsr.com/post/2020-01-29-nginx/2020-01-29-sc04_hu_71d2f1cb546d1f1f.png 1600w, https://blog.uzimihsr.com/post/2020-01-29-nginx/2020-01-29-sc04_hu_bdf62cc954e45226.png 2400w, https://blog.uzimihsr.com/post/2020-01-29-nginx/2020-01-29-sc04.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;やったぜ.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;これでリバースプロキシの8080番だけ覚えればあとは名前だけで各アプリにたどり着けるようになったのでとても便利.&lt;br&gt;
リバースプロキシの練習にもなったのでよかった.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="パソコンの邪魔して怒られて暇なそとちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-29-nginx/2020-01-29-sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-01-29-nginx/2020-01-29-sotochan_hu_3637b3e60938ae8f.jpg 800w, https://blog.uzimihsr.com/post/2020-01-29-nginx/2020-01-29-sotochan_hu_26cd26eae3766ad9.jpg 1600w, https://blog.uzimihsr.com/post/2020-01-29-nginx/2020-01-29-sotochan_hu_e03cabd54d167256.jpg 2400w, https://blog.uzimihsr.com/post/2020-01-29-nginx/2020-01-29-sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>AlertmanagerからGmailを使って通知するようにした</title><link>https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/</link><pubDate>Mon, 27 Jan 2020 22:52:41 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sotochan.jpg" alt="Featured image of post AlertmanagerからGmailを使って通知するようにした" /&gt;&lt;h2 id="やばい時には通知する"&gt;やばい時には通知する
&lt;/h2&gt;&lt;p&gt;監視の練習として, Alertmanagerを使ってラズパイから通知をGmailで送るようにした.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Googleアカウントの設定をしてSMTPサーバーを使えるようにした&lt;/li&gt;
&lt;li&gt;ラズパイにAlertmanagerを突っ込んでGmail経由で通知を送るようにした&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Raspberry Pi 3 Model B+
&lt;ul&gt;
&lt;li&gt;OSはRaspbian(10.0)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Node exporter
&lt;ul&gt;
&lt;li&gt;version=&amp;ldquo;0.18.1&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Prometheus
&lt;ul&gt;
&lt;li&gt;version=&amp;ldquo;2.15.2&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Alertmanager
&lt;ul&gt;
&lt;li&gt;version=&amp;ldquo;0.20.0&amp;rdquo;&lt;/li&gt;
&lt;li&gt;今回入れる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Googleのアカウント&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Node exporterとPrometheusは&lt;a class="link" href="https://uzimihsr.github.io/post/2020-01-15-prometheus-grafana-raspberry-pi/" target="_blank" rel="noopener"
 &gt;ラズパイにインストール済み&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="構成"&gt;構成
&lt;/h2&gt;&lt;p&gt;&lt;img alt="構成図" class="gallery-image" data-flex-basis="423px" data-flex-grow="176" height="1078" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-component.png" srcset="https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-component_hu_ae281c46a4591237.png 800w, https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-component_hu_ed9aefb207a4f80d.png 1600w, https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-component.png 1903w" width="1903"&gt;&lt;/p&gt;
&lt;div&gt;Icons made by &lt;a href="https://www.flaticon.com/authors/smashicons" title="Smashicons"&gt;Smashicons&lt;/a&gt; from &lt;a href="https://www.flaticon.com/" title="Flaticon"&gt;www.flaticon.com&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;今回は図のような構成で通知を送る.&lt;br&gt;
&lt;strong&gt;Prometheus&lt;/strong&gt; は各 &lt;strong&gt;exporter&lt;/strong&gt; を常に監視しており,&lt;br&gt;
監視対象(ラズパイ)に何か問題が発生した場合 &lt;strong&gt;Node exporter&lt;/strong&gt; のメトリクスが変化する.&lt;br&gt;
&lt;strong&gt;Prometheus&lt;/strong&gt; では監視対象のメトリクスについて設定した条件(放っておいたらまずい状態)を満たした際にアラートを発火させる.&lt;br&gt;
&lt;strong&gt;Alertmanager&lt;/strong&gt; は発火したアラートに応じた処理を行うが,&lt;br&gt;
今回はGmail経由で管理者に通知するようにする.&lt;/p&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#smtp%e3%82%b5%e3%83%bc%e3%83%90%e3%83%bc%e3%81%ae%e8%a8%ad%e5%ae%9a" &gt;SMTPサーバーの設定&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#alertmanager%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" &gt;Alertmanagerのインストール&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e9%80%9a%e7%9f%a5%e8%a8%ad%e5%ae%9a%e3%81%a8%e3%83%86%e3%82%b9%e3%83%88" &gt;通知設定とテスト&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="smtpサーバーの設定"&gt;SMTPサーバーの設定
&lt;/h3&gt;&lt;p&gt;まずはラズパイ上のアプリケーションからメールを送れるようにSMTPサーバーの設定を行う.&lt;br&gt;
今回はGmailをSMTPサーバーとして使用するが, 他に利用可能なメールサーバーがあれば飛ばしても良い.&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://support.google.com/mail/answer/185833" target="_blank" rel="noopener"
 &gt;ここ&lt;/a&gt;を参考に, Googleアカウントでアプリ用パスワードを設定する.&lt;br&gt;
&lt;a class="link" href="https://myaccount.google.com/u/1/security" target="_blank" rel="noopener"
 &gt;https://myaccount.google.com/u/1/security&lt;/a&gt; を開き, &lt;code&gt;セキュリティ&lt;/code&gt;-&amp;gt;&lt;code&gt;2段階認証プロセス&lt;/code&gt;と進む.&lt;/p&gt;
&lt;p&gt;&lt;img alt="アカウント設定" class="gallery-image" data-flex-basis="422px" data-flex-grow="176" height="1636" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc01.png" srcset="https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc01_hu_2b19f2b126e17044.png 800w, https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc01_hu_ae21b422668ee9a5.png 1600w, https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc01_hu_17107b3e91c3d6ee.png 2400w, https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc01.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;もろもろの設定をして2段階認証を有効化する.&lt;br&gt;
細かい設定手順は&lt;a class="link" href="https://support.google.com/accounts/answer/185839" target="_blank" rel="noopener"
 &gt;ここ&lt;/a&gt;を参考にする.&lt;/p&gt;
&lt;p&gt;&lt;img alt="2段階認証" class="gallery-image" data-flex-basis="421px" data-flex-grow="175" height="1639" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc02.png" srcset="https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc02_hu_d424fd3ad3be5105.png 800w, https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc02_hu_3479d288a094ca4c.png 1600w, https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc02_hu_e7261bce30230eed.png 2400w, https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc02.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;再度 &lt;a class="link" href="https://myaccount.google.com/u/1/security" target="_blank" rel="noopener"
 &gt;https://myaccount.google.com/u/1/security&lt;/a&gt; を開くと&lt;code&gt;アプリパスワード&lt;/code&gt;の項目が増えているので進む.&lt;br&gt;
&lt;code&gt;アプリを選択&lt;/code&gt;から&lt;code&gt;その他(名前を入力)&lt;/code&gt;を選び, 適当な名前(alertmanager)を入力して&lt;code&gt;生成&lt;/code&gt;を押す.&lt;/p&gt;
&lt;p&gt;&lt;img alt="アプリパスワードの生成" class="gallery-image" data-flex-basis="422px" data-flex-grow="176" height="1636" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc03.png" srcset="https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc03_hu_3b069fed2d9e62d3.png 800w, https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc03_hu_9c07fa537ca9d24c.png 1600w, https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc03_hu_c47c8ff54f8bff6d.png 2400w, https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc03.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;16文字の&lt;code&gt;アプリパスワード&lt;/code&gt;が生成されるので覚えておく.&lt;br&gt;
このパスワードを使ってラズパイからメールを送る.&lt;/p&gt;
&lt;p&gt;&lt;img alt="生成されたパスワード" class="gallery-image" data-flex-basis="422px" data-flex-grow="175" height="1637" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc04.png" srcset="https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc04_hu_dbe45483a6f7c06c.png 800w, https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc04_hu_d821be7543128ebe.png 1600w, https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc04_hu_5bda52bcec712b92.png 2400w, https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc04.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;SMTPサーバーの設定は&lt;a class="link" href="https://support.google.com/a/answer/176600" target="_blank" rel="noopener"
 &gt;ここ&lt;/a&gt;を参考に後ほどAlertmanagerの設定に記述する.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;項目&lt;/th&gt;
 &lt;th&gt;値&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;SMTPホスト名&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;smtp.gmail.com&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;ポート番号&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;587&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;アカウント&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;アプリパスワードを発行したアカウント名&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;パスワード&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;アプリパスワード&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;以上でGmailをSMTPサーバーとして使うための準備は完了.&lt;/p&gt;
&lt;h3 id="alertmanagerのインストール"&gt;Alertmanagerのインストール
&lt;/h3&gt;&lt;p&gt;次にPrometheusで発火したアラートを処理するためのAlertmanagerをインストールする.&lt;br&gt;
ファイルは&lt;a class="link" href="https://uzimihsr.github.io/post/2020-01-15-prometheus-grafana-raspberry-pi/" target="_blank" rel="noopener"
 &gt;前回&lt;/a&gt;と同じように&lt;a class="link" href="https://prometheus.io/download/#alertmanager" target="_blank" rel="noopener"
 &gt;ここ&lt;/a&gt;からダウンロードする. &lt;code&gt;Architecture&lt;/code&gt;は&lt;code&gt;armv7&lt;/code&gt;であることに注意.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 任意のディレクトリで実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; /path/to/workspace
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Alertmanagerをダウンロードして展開, フォルダを移動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ wget https://github.com/prometheus/alertmanager/releases/download/v0.20.0/alertmanager-0.20.0.linux-armv7.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ tar -xzf alertmanager-0.20.0.linux-armv7.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo cp -a alertmanager-0.20.0.linux-armv7 /usr/local/alertmanager
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# service用ユーザの作成, データ保存用ディレクトリの作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo useradd -U -s /sbin/nologin -M -d / alertmanager
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo mkdir -p /var/lib/alertmanager/data
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo chown -R alertmanager:alertmanager /var/lib/alertmanager
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# serviceファイルを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo vim /etc/systemd/system/alertmanager.service
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# serviceを起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl daemon-reload
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; alertmanager
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Created symlink /etc/systemd/system/multi-user.target.wants/alertmanager.service → /etc/systemd/system/alertmanager.service.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl start alertmanager
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ systemctl status alertmanager
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;● alertmanager.service - Alertmanager
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Loaded: loaded &lt;span class="o"&gt;(&lt;/span&gt;/etc/systemd/system/alertmanager.service&lt;span class="p"&gt;;&lt;/span&gt; enabled&lt;span class="p"&gt;;&lt;/span&gt; vendor preset: enabled&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Active: active &lt;span class="o"&gt;(&lt;/span&gt;running&lt;span class="o"&gt;)&lt;/span&gt; since Mon 2020-01-27 00:10:38 JST&lt;span class="p"&gt;;&lt;/span&gt; 4s ago
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Main PID: &lt;span class="m"&gt;9413&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;alertmanager&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Tasks: &lt;span class="m"&gt;13&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;limit: 2200&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Memory: 7.7M
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; CGroup: /system.slice/alertmanager.service
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └─9413 /usr/local/alertmanager/alertmanager --config.file&lt;span class="o"&gt;=&lt;/span&gt;/usr/local/alertmanager/alertmanager.yml --storage.path&lt;span class="o"&gt;=&lt;/span&gt;/var/lib/alertmanager/data
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Jan &lt;span class="m"&gt;27&lt;/span&gt; 00:10:38 raspberrypi alertmanager&lt;span class="o"&gt;[&lt;/span&gt;9413&lt;span class="o"&gt;]&lt;/span&gt;: &lt;span class="nv"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;info &lt;span class="nv"&gt;ts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2020-01-26T15:10:38.829Z &lt;span class="nv"&gt;caller&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;main.go:497 &lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Listening &lt;span class="nv"&gt;address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;:9093
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;details&gt;&lt;summary&gt;alertmanager.service&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-service" data-lang="service"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Unit]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Alertmanager&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Service]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;User&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;alertmanager&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;ExecStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/local/alertmanager/alertmanager &lt;/span&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; --config.file=/usr/local/alertmanager/alertmanager.yml &lt;/span&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; --storage.path=/var/lib/alertmanager/data&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Install]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;WantedBy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;multi-user.target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;ラズパイのIP&amp;gt;:9093&lt;/code&gt;をブラウザで開くとAlertmanagerのUI画面が表示される.&lt;br&gt;
(ラズパイのブラウザで開く場合は&lt;code&gt;localhost:9093&lt;/code&gt;)&lt;/p&gt;
&lt;p&gt;&lt;img alt="AlertmanagerのUI画面" class="gallery-image" data-flex-basis="782px" data-flex-grow="326" height="883" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc05.png" srcset="https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc05_hu_3e05ce5a560c2ff4.png 800w, https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc05_hu_b67acadae5667bd.png 1600w, https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc05_hu_30a122141ad60dfe.png 2400w, https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc05.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;これでAlertmanagerのインストールと起動ができた.&lt;/p&gt;
&lt;h3 id="通知設定とテスト"&gt;通知設定とテスト
&lt;/h3&gt;&lt;p&gt;次にPrometheusでアラートを発生させるための設定を行う.&lt;br&gt;
アラートルールの設定ファイル&lt;code&gt;rules.yml&lt;/code&gt;で監視対象がダウンしたときに発火するInstanceDownアラートを定義し,&lt;br&gt;
&lt;code&gt;prometheus.yml&lt;/code&gt;でこれを参照するよう設定する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# アラートの条件を記述するファイルを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim /usr/local/prometheus/rules.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# prometheusの設定ファイルを修正&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim /usr/local/prometheus/prometheus.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# prometheusのserviceを再起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl restart prometheus
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;details&gt;&lt;summary&gt;rules.yml&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;instance&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;InstanceDown&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;up == 0 &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 監視対象のupが0(down)になり&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;1m &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# かつその状態が1分以上続くと発火&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;prometheus.yml&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;global&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;scrape_interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;15s&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;evaluation_interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;15s&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;rule_files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;rules.yml&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# アラート設定を読み込む&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;alerting&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;alertmanagers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;localhost:9093&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 9093番ポートで起動しているAlertmanagerにアラートを送る&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;scrape_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;prometheus&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;localhost:9090&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;node&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;localhost:9100&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;この時点で&lt;code&gt;&amp;lt;ラズパイのIP&amp;gt;:9090&lt;/code&gt;をブラウザで開き, &lt;code&gt;Alerts&lt;/code&gt;を選択するとアラート設定が有効になっていることがわかる.&lt;/p&gt;
&lt;p&gt;&lt;img alt="PrometheusのUI画面" class="gallery-image" data-flex-basis="808px" data-flex-grow="336" height="855" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc06.png" srcset="https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc06_hu_afe4ff981efef5d8.png 800w, https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc06_hu_e4fc21a301cd1c2b.png 1600w, https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc06_hu_822e7e2de4075077.png 2400w, https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc06.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;ここで試しに監視対象のNode exporterを止めてアラートを発火させてみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Node exporterのサービスを止める&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl stop node_exporter
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# アラートの動作確認(発火)が完了した後で再度サービスを起動する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl start node_exporter
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;rules.yml&lt;/code&gt;で定義したとおり,&lt;br&gt;
監視対象(Node exporter)がダウンして1分経つとアラートが発火する.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Prometheusのアラートが発火" class="gallery-image" data-flex-basis="683px" data-flex-grow="284" height="1012" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc07.png" srcset="https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc07_hu_9fc92834c3ea6b14.png 800w, https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc07_hu_b58d2746671e7ebe.png 1600w, https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc07_hu_bfa2498643cf19d7.png 2400w, https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc07.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;また, PrometheusからAlertmanagerにアラートが飛んできていることが確認できる.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Alertmanagerの画面" class="gallery-image" data-flex-basis="693px" data-flex-grow="289" height="996" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc08.png" srcset="https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc08_hu_6a4c931fbafe0b5a.png 800w, https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc08_hu_61155679ed9ebb2f.png 1600w, https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc08_hu_a329354e30b0128e.png 2400w, https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc08.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;以上でPrometheusのアラート設定は完了.&lt;/p&gt;
&lt;p&gt;次にAlertmanagerでアラートを処理する設定を行う.&lt;br&gt;
Alertmanagerの設定ファイル&lt;code&gt;alertmanager.yaml&lt;/code&gt;を修正し,&lt;br&gt;
アラートが飛んできた際の処理を設定する.&lt;br&gt;
メール設定の部分に&lt;a class="link" href="#smtp%e3%82%b5%e3%83%bc%e3%83%90%e3%83%bc%e3%81%ae%e8%a8%ad%e5%ae%9a" &gt;SMTPサーバーの設定&lt;/a&gt;で確認した項目を書き込む.&lt;br&gt;
設定の書き方は&lt;a class="link" href="https://prometheus.io/docs/alerting/configuration/#email_config" target="_blank" rel="noopener"
 &gt;ここ&lt;/a&gt;を参考にする.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Alertmanagerの設定ファイルを編集&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim /usr/local/alertmanager/alertmanager.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# サービスを再起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl restart alertmanager
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;details&gt;&lt;summary&gt;alertmanager.yml&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;global&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;resolve_timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;5m&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;smtp_smarthost&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;smtp.gmail.com:587&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# SMTPサーバーのホスト名&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;smtp_from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;xxxxxxxxx@gmail.com&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 先程設定したアカウントのメールアドレスを送信元に設定&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;smtp_auth_username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;xxxxxxxxx&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# アカウント名&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;smtp_auth_password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;wwwwwwwwwwwwwwww&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# アプリパスワード&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;route&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;group_by&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;alertname&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;group_wait&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;10s&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;group_interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;10s&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;repeat_interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;1h&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;receiver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;alert-email&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;receivers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;alert-email&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;email_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;yyyyyyyyy@gmail.com&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 通知を受け取るメールアドレスを設定&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;以上でAlertmanagerからGmail経由で通知メールを送る設定は完了.&lt;/p&gt;
&lt;p&gt;動作確認のため, 先程と同様にNode exporterを再度落としてみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Node exporterのサービスを止める&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl stop node_exporter
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# アラートの動作確認(発火)が完了したら再度サービスを起動する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl start node_exporter
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;宛先に指定したメールアドレス(&lt;code&gt;yyyyyyyyy@gmail.com&lt;/code&gt;)の受信トレイを確認すると,&lt;br&gt;
アラートメールが送信されていることがわかる.&lt;/p&gt;
&lt;p&gt;&lt;img alt="届いたメール" class="gallery-image" data-flex-basis="453px" data-flex-grow="189" height="1171" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc09.png" srcset="https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc09_hu_23187b409934f628.png 800w, https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc09_hu_cd222fda7e53c2b4.png 1600w, https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sc09.png 2214w" width="2214"&gt;&lt;/p&gt;
&lt;p&gt;やったぜ.&lt;br&gt;
これでPrometheusのアラートをGmail経由で通知できるようになった.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;以上でラズパイ監視のアラートを通知できるようになった.&lt;br&gt;
いよいよ監視っぽくなってきた&amp;hellip;&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="かわいいちゃんちゃんこを着るそとちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sotochan_hu_3ba2443283561b18.jpg 800w, https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sotochan_hu_7280ab87ca018446.jpg 1600w, https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sotochan_hu_9956ed2fe236eee6.jpg 2400w, https://blog.uzimihsr.com/post/2020-01-27-alertmanager-gmail/2020-01-27-sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>ラズパイに公開鍵でSSHするようにした</title><link>https://blog.uzimihsr.com/post/2020-01-23-raspberry-pi-ssh-key/</link><pubDate>Thu, 23 Jan 2020 22:49:13 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-01-23-raspberry-pi-ssh-key/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-01-23-raspberry-pi-ssh-key/2020-01-23-sotochan.jpg" alt="Featured image of post ラズパイに公開鍵でSSHするようにした" /&gt;&lt;h2 id="パスワード打つのめんどい"&gt;パスワード打つのめんどい
&lt;/h2&gt;&lt;p&gt;家にあるラズパイにSSHできるようにしたはいいものの, 毎回パスワード入れるのも面倒だし真面目に考えたらセキュリティ的にもよろしくないので公開鍵認証で入るようにした.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;MacBookの公開鍵をラズパイ側に登録してログインできるようにした&lt;/li&gt;
&lt;li&gt;ラズパイ側でパスワードログインを無効化した&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Raspberry Pi 3 Model B+
&lt;ul&gt;
&lt;li&gt;SSHサーバー(入られる側)&lt;/li&gt;
&lt;li&gt;OSはRaspbian(10.0)&lt;/li&gt;
&lt;li&gt;IPは&lt;a class="link" href="https://uzimihsr.github.io/post/2020-01-07-raspberry-pi-static-id/#%E3%83%A9%E3%82%BA%E3%83%91%E3%82%A4%E3%81%AEip%E3%82%A2%E3%83%89%E3%83%AC%E3%82%B9%E5%9B%BA%E5%AE%9A" target="_blank" rel="noopener"
 &gt;固定済み&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;MacBook
&lt;ul&gt;
&lt;li&gt;SSHクライアント(入る側)&lt;/li&gt;
&lt;li&gt;opensshがあれば正直なんでもいい&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="構成"&gt;構成
&lt;/h2&gt;&lt;p&gt;&lt;img alt="構成" class="gallery-image" data-flex-basis="465px" data-flex-grow="193" height="765" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-23-raspberry-pi-ssh-key/2020-01-23-component.png" srcset="https://blog.uzimihsr.com/post/2020-01-23-raspberry-pi-ssh-key/2020-01-23-component_hu_28eb14df5f9b9d72.png 800w, https://blog.uzimihsr.com/post/2020-01-23-raspberry-pi-ssh-key/2020-01-23-component.png 1483w" width="1483"&gt;&lt;/p&gt;
&lt;div&gt;Icons made by &lt;a href="https://www.flaticon.com/authors/smashicons" title="Smashicons"&gt;Smashicons&lt;/a&gt; from &lt;a href="https://www.flaticon.com/" title="Flaticon"&gt;www.flaticon.com&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;公開鍵認証のざっくりとしたおさらい&amp;hellip;&lt;br&gt;
MacBook(クライアント)の秘密鍵(&lt;code&gt;id_rsa&lt;/code&gt;)と公開鍵(&lt;code&gt;id_rsa.pub&lt;/code&gt;)を&lt;br&gt;
ラズパイ(サーバー)の鍵リスト(&lt;code&gt;authorized_keys&lt;/code&gt;)に登録する.&lt;br&gt;
秘密鍵と公開鍵は1つのペアになっていて, それぞれ片方からもう片方を作成できないようになっている.&lt;br&gt;
また, 秘密鍵と公開鍵を照らし合わせるとペアになっているかどうかを判別できるようになっているので,&lt;br&gt;
MacBookからラズパイにSSHする際にはラズパイ側の鍵リストに事前に登録された公開鍵と&lt;br&gt;
MacBookが持つ秘密鍵を照らし合わせ, ペアと認められた場合にログインを許可する(認証).&lt;/p&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e5%85%ac%e9%96%8b%e9%8d%b5%e3%82%92%e3%83%a9%e3%82%ba%e3%83%91%e3%82%a4%e5%81%b4%e3%81%ab%e7%99%bb%e9%8c%b2" &gt;公開鍵をラズパイ側に登録&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%91%e3%82%b9%e3%83%af%e3%83%bc%e3%83%89%e8%aa%8d%e8%a8%bc%e3%82%92%e7%84%a1%e5%8a%b9%e5%8c%96" &gt;パスワード認証を無効化&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="公開鍵をラズパイ側に登録"&gt;公開鍵をラズパイ側に登録
&lt;/h3&gt;&lt;p&gt;まずはクライアント(MacBook)側で秘密鍵と公開鍵のペアを作成する.&lt;br&gt;
すでに&lt;code&gt;~/.ssh/id_rsa&lt;/code&gt;(秘密鍵)と&lt;code&gt;~/.ssh/id_rsa.pub&lt;/code&gt;(公開鍵)がある場合は飛ばしていい.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# MacBookで実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 秘密鍵と公開鍵のペアを作成する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ssh-keygen
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls ~/.ssh
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;id_rsa id_rsa.pub known_hosts
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;次にMacBookの公開鍵をラズパイ側に登録する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 全てMacBookで実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ラズパイに公開鍵を保存するためのファイル(~/.ssh/authorized_keys)を作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ここではまだパスワード認証&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ssh pi@192.168.3.200 &lt;span class="s2"&gt;&amp;#34;touch ~/.ssh/authorized_keys; ls ~/.ssh&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;authorized_keys &lt;span class="c1"&gt;# このファイルにMacBookの公開鍵を書き込む&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;id_rsa &lt;span class="c1"&gt;# これはラズパイの秘密鍵なので関係ない&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;id_rsa.pub &lt;span class="c1"&gt;# 同じく関係なし&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;known_hosts &lt;span class="c1"&gt;# 同じく関係なし&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ラズパイのauthorized_keysにMacBookの公開鍵を書き込んで権限を変更&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# まだパスワード認証&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat ~/.ssh/id_rsa.pub &lt;span class="p"&gt;|&lt;/span&gt; ssh pi@192.168.3.200 &lt;span class="s2"&gt;&amp;#34;cat &amp;gt;&amp;gt; ~/.ssh/authorized_keys; chmod 700 ~/.ssh/authorized_keys&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 念の為鍵が登録されたか確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat ~/.ssh/id_rsa.pub
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ssh-rsa AAAB3...wlj uzimihsr@macbook.local
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# MacBookの公開鍵が登録されているのでパスワードを聞かれなくなっている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ssh pi@192.168.3.200 &lt;span class="s2"&gt;&amp;#34;cat ~/.ssh/authorized_keys&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ssh-rsa AAAB3...wlj uzimihsr@macbook.local
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;やったぜ.&lt;br&gt;
これでパスワードなしでもSSHできるようになった.&lt;/p&gt;
&lt;h3 id="パスワード認証を無効化"&gt;パスワード認証を無効化
&lt;/h3&gt;&lt;p&gt;このままでもいいんだけど, セキュリティ的にパスワード認証はあまりよろしくない(総当りされたらクソ雑魚ナメクジ)ので,&lt;br&gt;
パスワード認証を無効化する.&lt;br&gt;
ラズパイの&lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt;を編集してパスワード認証の可否を変更する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 全てラズパイで実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# SSHサーバー側の設定ファイルを編集&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo vim /etc/ssh/sshd_config
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# To disable tunneled clear text passwords, change to no here!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;PasswordAuthentication no &lt;span class="c1"&gt;# ここをyesからnoに変更&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#PermitEmptyPasswords no&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 念の為sshd.serviceを再起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl restart ssh.service
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ちゃんとパスワード認証が無効化されているか確認する.&lt;br&gt;
公開鍵認証ではクライアント(MacBook)の秘密鍵とサーバー(ラズパイ)に登録された公開鍵が対応していないと認証が通らないので,&lt;br&gt;
MacBook側の秘密鍵を使えなくするとログインできなくなる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 全てMacBookで実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 秘密鍵の名前を変えて読めない状態にする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mv ~/.ssh/id_rsa ~/.ssh/id_rsa.bkup
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ラズパイにSSHを試みる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# MacBookの秘密鍵が使えず, パスワード認証が禁止されているので弾かれる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ssh pi@192.168.3.200
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pi@192.168.3.200: Permission denied &lt;span class="o"&gt;(&lt;/span&gt;publickey&lt;span class="o"&gt;)&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 秘密鍵の名前をもとに戻して使えるようにする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mv ~/.ssh/id_rsa.bkup ~/.ssh/id_rsa
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 再びラズパイにSSHを試みる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 今度は秘密鍵が使えるので問題なくログインできる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ssh pi@192.168.3.200
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Last login: Thu Jan &lt;span class="m"&gt;23&lt;/span&gt; 23:24:24 &lt;span class="m"&gt;2020&lt;/span&gt; from ...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;やったぜ.&lt;br&gt;
これで鍵認証でしかログインできなくなった.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;ラズパイでの作業がだいぶ楽になった.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="パソコンばっかりさわってるしもべに愛想をつかすそとちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-23-raspberry-pi-ssh-key/2020-01-23-sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-01-23-raspberry-pi-ssh-key/2020-01-23-sotochan_hu_87775c2ed4f4d552.jpg 800w, https://blog.uzimihsr.com/post/2020-01-23-raspberry-pi-ssh-key/2020-01-23-sotochan_hu_2186b9b6fab331d5.jpg 1600w, https://blog.uzimihsr.com/post/2020-01-23-raspberry-pi-ssh-key/2020-01-23-sotochan_hu_e8cfcd5e18c50789.jpg 2400w, https://blog.uzimihsr.com/post/2020-01-23-raspberry-pi-ssh-key/2020-01-23-sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>Raspberry PiにPrometheusとGrafanaを突っ込んだ</title><link>https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/</link><pubDate>Wed, 15 Jan 2020 21:31:01 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sotochan.jpg" alt="Featured image of post Raspberry PiにPrometheusとGrafanaを突っ込んだ" /&gt;&lt;h2 id="監視の練習"&gt;監視の練習
&lt;/h2&gt;&lt;p&gt;ラズパイを使ってPrometheusによる監視の練習をしてみた.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;ラズパイにNode exporterとPrometheusを入れてメトリクスを取れるようにした&lt;/li&gt;
&lt;li&gt;Grafanaも突っ込んでダッシュボードを作ってみた&lt;/li&gt;
&lt;li&gt;全部サービス化して自動起動するようにした&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;実際につくったもの.&lt;br&gt;
ラズパイのシステム情報がブラウザから簡単に確認できる.&lt;br&gt;
&lt;img alt="dashboard" class="gallery-image" data-flex-basis="421px" data-flex-grow="175" height="1639" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc12.png" srcset="https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc12_hu_ecf8a91b1ec5fa2.png 800w, https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc12_hu_8d0e2463145890fd.png 1600w, https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc12_hu_330ce2a32068ec1e.png 2400w, https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc12.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Raspberry Pi 3 Model B+
&lt;ul&gt;
&lt;li&gt;OSはRaspbian(10.0)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Node exporter
&lt;ul&gt;
&lt;li&gt;version=&amp;ldquo;0.18.1&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Prometheus
&lt;ul&gt;
&lt;li&gt;version=&amp;ldquo;2.15.2&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Grafana
&lt;ul&gt;
&lt;li&gt;v6.5.2&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="構成"&gt;構成
&lt;/h2&gt;&lt;p&gt;&lt;img alt="コンポーネント" class="gallery-image" data-flex-basis="649px" data-flex-grow="270" height="781" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-component.png" srcset="https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-component_hu_1be20ffbf9585fe9.png 800w, https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-component_hu_8ab570a65317a71.png 1600w, https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-component.png 2114w" width="2114"&gt;&lt;/p&gt;
&lt;p&gt;こんな感じの構成でラズパイのシステム情報を可視化する.&lt;br&gt;
&lt;strong&gt;Node exporter&lt;/strong&gt; がマシンのシステム情報(CPU使用率など)を数値化したメトリクスを吐き出し続け,&lt;br&gt;
&lt;strong&gt;Prometheus&lt;/strong&gt; でexporterの吐き出すメトリクスをモニタリングして時系列化.&lt;br&gt;
最後に &lt;strong&gt;Grafana&lt;/strong&gt; が &lt;strong&gt;Prometheus&lt;/strong&gt; の持つ時系列データを取り出して可視化する,&lt;br&gt;
という基本的な構成.&lt;br&gt;
&lt;strong&gt;Grafana&lt;/strong&gt; で可視化したデータは同じネットワークのブラウザから見ることができる.&lt;br&gt;
今回はこれらのコンポーネントを1台のマシンにまとめてしまうが, 複数台のマシンに分散させることも可能である.&lt;/p&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#node-exporter%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" &gt;Node exporterのインストール&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#prometheus%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" &gt;Prometheusのインストール&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#grafana%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" &gt;Grafanaのインストール&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="node-exporterのインストール"&gt;Node exporterのインストール
&lt;/h3&gt;&lt;p&gt;まずは&lt;a class="link" href="https://github.com/prometheus/node_exporter" target="_blank" rel="noopener"
 &gt;Node exporter&lt;/a&gt;をインストールする.&lt;br&gt;
ブラウザで&lt;a class="link" href="https://prometheus.io/download" target="_blank" rel="noopener"
 &gt;Prometheusのダウンロードページ&lt;/a&gt;を開き, &lt;code&gt;Architecture&lt;/code&gt;を&lt;code&gt;armv7&lt;/code&gt;にした状態で&lt;code&gt;node_exporter-0.18.1.linux-armv7.tar.gz&lt;/code&gt;をダウンロードする.&lt;/p&gt;
&lt;p&gt;&lt;img alt="ダウンロードページ" class="gallery-image" data-flex-basis="1341px" data-flex-grow="558" height="414" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc01.png" srcset="https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc01_hu_b5321ce411fe68ba.png 800w, https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc01_hu_84833cb957458588.png 1600w, https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc01.png 2314w" width="2314"&gt;&lt;/p&gt;
&lt;p&gt;もしくは, コマンドラインから&lt;code&gt;wget&lt;/code&gt;する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 任意のディレクトリで実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; /path/to/workspace
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# node_exporterをダウンロードして展開, バイナリを移動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ wget https://github.com/prometheus/node_exporter/releases/download/v0.18.1/node_exporter-0.18.1.linux-armv7.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ tar -xzf node_exporter-0.18.1.linux-armv7.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo cp node_exporter-0.18.1.linux-armv7/node_exporter /usr/local/bin
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;動作確認してみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Node exporterを起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ /usr/local/bin/node_exporter
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;INFO&lt;span class="o"&gt;[&lt;/span&gt;0000&lt;span class="o"&gt;]&lt;/span&gt; Starting node_exporter &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.18.1, &lt;span class="nv"&gt;branch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;HEAD, &lt;span class="nv"&gt;revision&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3db77732e925c08f675d7404a8c46466b2ece83e&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;node_exporter.go:156&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;INFO&lt;span class="o"&gt;[&lt;/span&gt;0000&lt;span class="o"&gt;]&lt;/span&gt; Build context &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;go&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;go1.12.5, &lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;root@b50852a1acba, &lt;span class="nv"&gt;date&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;20190604-16:42:57&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;node_exporter.go:157&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;INFO&lt;span class="o"&gt;[&lt;/span&gt;0000&lt;span class="o"&gt;]&lt;/span&gt; Enabled collectors: &lt;span class="nv"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;node_exporter.go:97&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;INFO&lt;span class="o"&gt;[&lt;/span&gt;0000&lt;span class="o"&gt;]&lt;/span&gt; - arp &lt;span class="nv"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;node_exporter.go:104&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;INFO&lt;span class="o"&gt;[&lt;/span&gt;0000&lt;span class="o"&gt;]&lt;/span&gt; - zfs &lt;span class="nv"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;node_exporter.go:104&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;INFO&lt;span class="o"&gt;[&lt;/span&gt;0000&lt;span class="o"&gt;]&lt;/span&gt; Listening on :9100 &lt;span class="nv"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;node_exporter.go:170&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 動作確認が終わり次第Ctrl+Cで終了する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;9100番ポートで起動しているので, ラズパイか同じネットワークにあるマシンのブラウザから&lt;code&gt;&amp;lt;ラズパイのIP&amp;gt;:9100/metrics&lt;/code&gt;を開くと, メトリクスの一覧が表示される.&lt;/p&gt;
&lt;p&gt;&lt;img alt="node_exporterのメトリクス" class="gallery-image" data-flex-basis="397px" data-flex-grow="165" height="636" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc02.png" srcset="https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc02_hu_ef2d1925fd642f45.png 800w, https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc02.png 1054w" width="1054"&gt;&lt;/p&gt;
&lt;p&gt;(画像にあるIPは&lt;a class="link" href="https://uzimihsr.github.io/post/2020-01-07-raspberry-pi-static-id/" target="_blank" rel="noopener"
 &gt;前回固定したもの&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;毎回手動で起動するのは不便なのでサービス化しておく.&lt;br&gt;
こちらの&lt;a class="link" href="https://github.com/prometheus/node_exporter/tree/master/examples/systemd" target="_blank" rel="noopener"
 &gt;サンプル&lt;/a&gt;の通りにやってみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# service起動に必要なuser(node_exporter)を追加する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo useradd -U -s /sbin/nologin -M -d / node_exporter
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# serviceファイルを作成する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo vim /etc/systemd/system/node_exporter.service
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# serviceの起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl daemon-reload
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; node_exporter
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Created symlink /etc/systemd/system/multi-user.target.wants/node_exporter.service → /etc/systemd/system/node_exporter.service.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl start node_exporter
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ systemctl status node_exporter
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;● node_exporter.service - Node Exporter
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Loaded: loaded &lt;span class="o"&gt;(&lt;/span&gt;/etc/systemd/system/node_exporter.service&lt;span class="p"&gt;;&lt;/span&gt; enabled&lt;span class="p"&gt;;&lt;/span&gt; vendor preset: enabled&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Active: active &lt;span class="o"&gt;(&lt;/span&gt;running&lt;span class="o"&gt;)&lt;/span&gt; since Wed 2020-01-15 22:50:41 JST&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; days ago
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Main PID: &lt;span class="m"&gt;19378&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;node_exporter&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Tasks: &lt;span class="m"&gt;13&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;limit: 2200&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Memory: 17.8M
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; CGroup: /system.slice/node_exporter.service
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └─19378 /usr/local/bin/node_exporter
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Jan &lt;span class="m"&gt;15&lt;/span&gt; 22:50:41 raspberrypi node_exporter&lt;span class="o"&gt;[&lt;/span&gt;19378&lt;span class="o"&gt;]&lt;/span&gt;: &lt;span class="nv"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;2020-01-15T22:50:41+09:00&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;info &lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Listening on :9100&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;node_exporter.go:170&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;details&gt;&lt;summary&gt;node_exporter.service&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-service" data-lang="service"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Unit]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Node Exporter&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Service]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;User&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;node_exporter&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;ExecStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/local/bin/node_exporter&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Install]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;WantedBy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;multi-user.target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;(&lt;a class="link" href="https://github.com/prometheus/node_exporter/blob/master/examples/systemd/node_exporter.service" target="_blank" rel="noopener"
 &gt;https://github.com/prometheus/node_exporter/blob/master/examples/systemd/node_exporter.service&lt;/a&gt; を改変)&lt;br&gt;
これでNode exporterが自動起動するようになった.&lt;br&gt;
動作確認時と同様にブラウザでアクセスしても同じメトリクスが表示される.&lt;/p&gt;
&lt;h3 id="prometheusのインストール"&gt;Prometheusのインストール
&lt;/h3&gt;&lt;p&gt;次に&lt;a class="link" href="https://github.com/prometheus/prometheus" target="_blank" rel="noopener"
 &gt;Prometheus&lt;/a&gt;をインストールする.&lt;br&gt;
Node exporterと同様にブラウザで&lt;a class="link" href="https://prometheus.io/download" target="_blank" rel="noopener"
 &gt;Prometheusのダウンロードページ&lt;/a&gt;を開き, &lt;code&gt;Architecture&lt;/code&gt;を&lt;code&gt;armv7&lt;/code&gt;にした状態で&lt;code&gt;prometheus-2.15.2.linux-armv7.tar.gz&lt;/code&gt;をダウンロードするか, コマンドラインから&lt;code&gt;wget&lt;/code&gt;する.&lt;/p&gt;
&lt;p&gt;&lt;img alt="ダウンロードページ" class="gallery-image" data-flex-basis="1364px" data-flex-grow="568" height="406" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc03.png" srcset="https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc03_hu_1f3fac4d279a5495.png 800w, https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc03_hu_9d3264762506a5be.png 1600w, https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc03.png 2308w" width="2308"&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 任意のディレクトリで実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; /path/to/workspace
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# prometheusをダウンロードして展開, 移動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ wget https://github.com/prometheus/prometheus/releases/download/v2.15.2/prometheus-2.15.2.linux-armv7.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ tar -xzf prometheus-2.15.2.linux-armv7.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo cp -a prometheus-2.15.2.linux-armv7 /usr/local/prometheus
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;すでに起動中のNode exporterのメトリクスを取得するために設定ファイルを編集し, 動作確認する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 設定ファイルを編集&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo vim /usr/local/prometheus/prometheus.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Prometheusを起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ /usr/local/prometheus/prometheus --config.file&lt;span class="o"&gt;=&lt;/span&gt;/usr/local/prometheus/prometheus.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;info &lt;span class="nv"&gt;ts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2020-01-15T14:14:00.683Z &lt;span class="nv"&gt;caller&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;main.go:294 &lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;no time or size retention was set so using the default time retention&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;duration&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;15d
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;info &lt;span class="nv"&gt;ts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2020-01-15T14:14:00.684Z &lt;span class="nv"&gt;caller&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;main.go:330 &lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Starting Prometheus&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;(version=2.15.2, branch=HEAD, revision=d9613e5c466c6e9de548c4dae1b9aabf9aaf7c57)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;info &lt;span class="nv"&gt;ts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2020-01-15T14:14:00.703Z &lt;span class="nv"&gt;caller&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;web.go:506 &lt;span class="nv"&gt;component&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;web &lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Start listening for connections&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.0.0.0:9090
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;info &lt;span class="nv"&gt;ts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2020-01-15T14:14:00.748Z &lt;span class="nv"&gt;caller&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;main.go:617 &lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Server is ready to receive web requests.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 動作確認が終わり次第Ctrl+Cで終了する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;details&gt;&lt;summary&gt;prometheus.yaml&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;global&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;scrape_interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;15s&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;evaluation_interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;15s&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;scrape_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;prometheus&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;localhost:9090&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;node&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;localhost:9100&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;9090番ポートで起動しているので, Node exporterのときと同様に&lt;code&gt;&amp;lt;ラズパイのIP&amp;gt;:9090&lt;/code&gt;をブラウザで開く.&lt;br&gt;
PrometheusのUI画面が表示される.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Prometheus" class="gallery-image" data-flex-basis="684px" data-flex-grow="285" height="1010" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc04.png" srcset="https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc04_hu_44ec6df25a4815c3.png 800w, https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc04_hu_8b5ec63f9fc86305.png 1600w, https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc04_hu_150fddb89095f0dd.png 2400w, https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc04.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;試しにメニューバーから&lt;code&gt;Status&lt;/code&gt;-&amp;gt;&lt;code&gt;Targets&lt;/code&gt;と進むとNode exporterのメトリクスをモニタリングしていることがわかる.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Targets" class="gallery-image" data-flex-basis="516px" data-flex-grow="215" height="1020" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc05.png" srcset="https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc05_hu_bbb46d9e782c5d1.png 800w, https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc05_hu_f787f6198547410c.png 1600w, https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc05.png 2194w" width="2194"&gt;&lt;/p&gt;
&lt;p&gt;こちらもNode exporterと同じようにサービス化する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# service起動に必要なuser(prometheus)を追加する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo useradd -U -s /sbin/nologin -M -d / prometheus
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Prometheusが時系列データを保存するためのディレクトリを作成する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo mkdir -p /var/lib/prometheus/data
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo chown -R prometheus:prometheus /var/lib/prometheus
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# serviceファイルを作成する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo vim /etc/systemd/system/prometheus.service
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# serviceの起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl daemon-reload
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; prometheus
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Created symlink /etc/systemd/system/multi-user.target.wants/prometheus.service → /etc/systemd/system/prometheus.service.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl start prometheus
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ systemctl status prometheus
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;● prometheus.service - Prometheus Server
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Loaded: loaded &lt;span class="o"&gt;(&lt;/span&gt;/etc/systemd/system/prometheus.service&lt;span class="p"&gt;;&lt;/span&gt; enabled&lt;span class="p"&gt;;&lt;/span&gt; vendor preset: enabled&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Active: active &lt;span class="o"&gt;(&lt;/span&gt;running&lt;span class="o"&gt;)&lt;/span&gt; since Sun 2020-01-19 12:14:50 JST&lt;span class="p"&gt;;&lt;/span&gt; 14min ago
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Main PID: &lt;span class="m"&gt;20933&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;prometheus&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Tasks: &lt;span class="m"&gt;14&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;limit: 2200&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Memory: 27.8M
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; CGroup: /system.slice/prometheus.service
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └─20933 /usr/local/prometheus/prometheus --config.file&lt;span class="o"&gt;=&lt;/span&gt;/usr/local/prometheus/prometheus.yml --storage.tsdb.path&lt;span class="o"&gt;=&lt;/span&gt;/var/lib/prometheus/data
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Jan &lt;span class="m"&gt;19&lt;/span&gt; 12:14:51 raspberrypi prometheus&lt;span class="o"&gt;[&lt;/span&gt;20933&lt;span class="o"&gt;]&lt;/span&gt;: &lt;span class="nv"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;info &lt;span class="nv"&gt;ts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2020-01-19T03:14:51.079Z &lt;span class="nv"&gt;caller&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;web.go:506 &lt;span class="nv"&gt;component&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;web &lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Start listening for connections&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.0.0.0:9090
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Jan &lt;span class="m"&gt;19&lt;/span&gt; 12:14:51 raspberrypi prometheus&lt;span class="o"&gt;[&lt;/span&gt;20933&lt;span class="o"&gt;]&lt;/span&gt;: &lt;span class="nv"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;info &lt;span class="nv"&gt;ts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2020-01-19T03:14:51.125Z &lt;span class="nv"&gt;caller&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;main.go:617 &lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Server is ready to receive web requests.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;details&gt;&lt;summary&gt;prometheus.service&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-service" data-lang="service"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Unit]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Prometheus Server&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Service]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;User&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;prometheus&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;ExecStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/local/prometheus/prometheus &lt;/span&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; --config.file=/usr/local/prometheus/prometheus.yml &lt;/span&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; --storage.tsdb.path=/var/lib/prometheus/data&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Install]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;WantedBy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;multi-user.target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;これでPrometheusも自動起動するようになった.&lt;/p&gt;
&lt;h3 id="grafanaのインストール"&gt;Grafanaのインストール
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://grafana.com/grafana/download?platform=arm" target="_blank" rel="noopener"
 &gt;こちらの手順&lt;/a&gt;を参考に&lt;a class="link" href="https://github.com/grafana/grafana" target="_blank" rel="noopener"
 &gt;Grafana&lt;/a&gt;をインストールする.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# devファイルからGrafanaをインストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt-get install -y adduser libfontconfig1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ wget https://dl.grafana.com/oss/release/grafana_6.5.2_armhf.deb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo dpkg -i grafana_6.5.2_armhf.deb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# サービスを起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl daemon-reload
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; grafana-server
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Synchronizing state of grafana-server.service with SysV service script with /lib/systemd/systemd-sysv-install.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Executing: /lib/systemd/systemd-sysv-install &lt;span class="nb"&gt;enable&lt;/span&gt; grafana-server
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Created symlink /etc/systemd/system/multi-user.target.wants/grafana-server.service → /usr/lib/systemd/system/grafana-server.service.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl start grafana-server
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ systemctl status grafana-server
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;● grafana-server.service - Grafana instance
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Loaded: loaded &lt;span class="o"&gt;(&lt;/span&gt;/usr/lib/systemd/system/grafana-server.service&lt;span class="p"&gt;;&lt;/span&gt; enabled&lt;span class="p"&gt;;&lt;/span&gt; vendor preset: enabled&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Active: active &lt;span class="o"&gt;(&lt;/span&gt;running&lt;span class="o"&gt;)&lt;/span&gt; since Tue 2020-01-14 22:24:02 JST&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt; days ago
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Docs: http://docs.grafana.org
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Main PID: &lt;span class="m"&gt;7445&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;grafana-server&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Tasks: &lt;span class="m"&gt;16&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;limit: 2200&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Memory: 29.3M
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; CGroup: /system.slice/grafana-server.service
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └─7445 /usr/sbin/grafana-server --config&lt;span class="o"&gt;=&lt;/span&gt;/etc/grafana/grafana.ini --pidfile&lt;span class="o"&gt;=&lt;/span&gt;/var/run/grafana/grafana-server.pid --packaging&lt;span class="o"&gt;=&lt;/span&gt;deb cfg:default.paths.logs&lt;span class="o"&gt;=&lt;/span&gt;/var/log/grafana cfg:default.paths.data&lt;span class="o"&gt;=&lt;/span&gt;/v
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Jan &lt;span class="m"&gt;14&lt;/span&gt; 22:24:09 raspberrypi grafana-server&lt;span class="o"&gt;[&lt;/span&gt;7445&lt;span class="o"&gt;]&lt;/span&gt;: &lt;span class="nv"&gt;t&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2020-01-14T22:24:09+0900 &lt;span class="nv"&gt;lvl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;info &lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;HTTP Server Listen&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http.server &lt;span class="nv"&gt;address&lt;/span&gt;&lt;span class="o"&gt;=[&lt;/span&gt;::&lt;span class="o"&gt;]&lt;/span&gt;:3000 &lt;span class="nv"&gt;protocol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http &lt;span class="nv"&gt;subUrl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;3000番ポートで起動しているので, ブラウザで&lt;code&gt;&amp;lt;ラズパイのIP&amp;gt;:3000&lt;/code&gt;を開く.&lt;br&gt;
ログイン画面が開かれるので, 初期ID(admin)とパスワード(admin)で入る.&lt;br&gt;
ホームダッシュボードが開かれる.&lt;/p&gt;
&lt;p&gt;&lt;img alt="login" class="gallery-image" data-flex-basis="472px" data-flex-grow="196" height="706" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc06.png" srcset="https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc06_hu_6ee1212416ada4b2.png 800w, https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc06.png 1390w" width="1390"&gt;&lt;br&gt;
&lt;img alt="home" class="gallery-image" data-flex-basis="549px" data-flex-grow="228" height="1259" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc07.png" srcset="https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc07_hu_fe51094a6bdff683.png 800w, https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc07_hu_31400c343443f2f3.png 1600w, https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc07_hu_773cf9b7f3a2bf4c.png 2400w, https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc07.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;これでGrafanaの立ち上げは完了.&lt;/p&gt;
&lt;p&gt;Prometheusのが取得したメトリクスを読めるようにdata sourceの設定を行う.&lt;br&gt;
ホームダッシュボードの&lt;code&gt;Add data source&lt;/code&gt;を開き, Prometheusを選択する.&lt;/p&gt;
&lt;p&gt;&lt;img alt="dataSource" class="gallery-image" data-flex-basis="672px" data-flex-grow="280" height="690" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc08.png" srcset="https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc08_hu_7cc85bf6c2507515.png 800w, https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc08_hu_39e28bc940e7c2c7.png 1600w, https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc08.png 1934w" width="1934"&gt;&lt;/p&gt;
&lt;p&gt;設定画面でPrometheusのURL(&lt;code&gt;http://localhost:9090&lt;/code&gt;)を入力し, &lt;code&gt;Save &amp;amp; Test&lt;/code&gt;を押すとPrometheusが登録される.&lt;/p&gt;
&lt;p&gt;&lt;img alt="settings" class="gallery-image" data-flex-basis="179px" data-flex-grow="74" height="1546" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc09.png" srcset="https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc09_hu_ac0fbcdb696cb81f.png 800w, https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc09.png 1155w" width="1155"&gt;&lt;/p&gt;
&lt;p&gt;次はダッシュボードを作る.&lt;br&gt;
ホームダッシュボードの&lt;code&gt;New dashboard&lt;/code&gt;を開き, &lt;code&gt;Add Query&lt;/code&gt;を選択する.&lt;/p&gt;
&lt;p&gt;&lt;img alt="dashboard" class="gallery-image" data-flex-basis="794px" data-flex-grow="331" height="870" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc10.png" srcset="https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc10_hu_d5177edf5e986053.png 800w, https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc10_hu_f5284f7db9be84d.png 1600w, https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc10_hu_bc87b421258304a4.png 2400w, https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc10.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;編集画面で試しにメモリの空きを表すメトリクス名&lt;code&gt;node_memory_MemAvailable_bytes&lt;/code&gt;を入力すると, その時系列データがグラフ化される.&lt;br&gt;
すごい.&lt;/p&gt;
&lt;p&gt;&lt;img alt="query" class="gallery-image" data-flex-basis="538px" data-flex-grow="224" height="1284" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc11.png" srcset="https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc11_hu_8c864f0f36ac060c.png 800w, https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc11_hu_72b29ef3b74f1ed8.png 1600w, https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc11_hu_69ac5c593d0cf8ae.png 2400w, https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc11.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;他にも&lt;a class="link" href="https://prometheus.io/docs/prometheus/latest/querying/basics/" target="_blank" rel="noopener"
 &gt;PromQL&lt;/a&gt;と&lt;a class="link" href="https://grafana.com/docs/grafana/latest/features/panels/graph/" target="_blank" rel="noopener"
 &gt;Grafanaの機能&lt;/a&gt;をいじり始めると楽しくて時間が飛ぶので割愛するが,&lt;br&gt;
同様にしてPrometheusが取得した各種メトリクスをグラフ化することができる.&lt;br&gt;
下の画像は今回作ったダッシュボードのスクリーンショットで,&lt;br&gt;
CPU使用率, メモリ使用率, ディスク使用率などが可視化されている.&lt;/p&gt;
&lt;p&gt;&lt;img alt="dashboard" class="gallery-image" data-flex-basis="421px" data-flex-grow="175" height="1639" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc12.png" srcset="https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc12_hu_ecf8a91b1ec5fa2.png 800w, https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc12_hu_8d0e2463145890fd.png 1600w, https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc12_hu_330ce2a32068ec1e.png 2400w, https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sc12.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;ダッシュボードをJSON形式で出力したもの&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;annotations&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;list&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;builtIn&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;datasource&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;-- Grafana --&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;enable&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;hide&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;iconColor&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;rgba(0, 211, 255, 1)&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Annotations &amp;amp; Alerts&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;dashboard&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;editable&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;gnetId&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;graphTooltip&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;links&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;panels&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;cacheTimeout&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;colorBackground&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;colorPrefix&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;colorValue&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;colors&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;#d44a3a&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;rgba(237, 129, 40, 0.89)&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;#299c46&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;datasource&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;format&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;none&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;gauge&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;maxValue&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;minValue&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;show&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;thresholdLabels&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;thresholdMarkers&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;gridPos&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;h&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;w&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;x&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;y&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;interval&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;links&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;mappingType&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;mappingTypes&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;value to text&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;range to text&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;maxDataPoints&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;nullPointMode&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;connected&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;nullText&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;options&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;postfix&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;postfixFontSize&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;50%&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;prefix&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;prefixFontSize&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;50%&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;rangeMaps&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;from&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;null&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;text&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;N/A&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;to&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;null&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;sparkline&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;fillColor&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;rgba(31, 118, 189, 0.18)&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;full&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;lineColor&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;rgb(31, 120, 193)&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;show&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;ymax&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;ymin&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;tableColumn&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;targets&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;expr&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;up{job=\&amp;#34;node\&amp;#34;}&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;refId&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;A&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;thresholds&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;0.1, 0.9&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;timeFrom&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;timeShift&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Node exporter&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;singlestat&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;valueFontSize&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;200%&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;valueMaps&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;op&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;=&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;text&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;N/A&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;null&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;op&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;=&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;text&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;down&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;op&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;=&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;text&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;up&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;valueName&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;current&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;datasource&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;gridPos&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;h&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;w&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;x&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;y&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;options&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;fieldOptions&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;calcs&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;last&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;defaults&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;mappings&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;max&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;min&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;thresholds&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;color&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;green&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;color&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;#E24D42&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;color&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;#EAB839&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;unit&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;percentunit&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;override&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;values&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;orientation&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;auto&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;showThresholdLabels&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;showThresholdMarkers&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;pluginVersion&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;6.5.2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;targets&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;expr&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;1.0 - (avg without(cpu) (rate(node_cpu_seconds_total{mode=\&amp;#34;idle\&amp;#34;}[1m])))&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;refId&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;A&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;timeFrom&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;timeShift&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;CPU Usage&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;gauge&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;cacheTimeout&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;datasource&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;gridPos&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;h&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;w&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;x&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;y&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;links&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;options&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;fieldOptions&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;calcs&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;last&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;defaults&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;links&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;mappings&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;max&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;min&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;nullValueMode&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;connected&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;thresholds&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;color&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;green&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;color&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;#EAB839&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;color&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;#E24D42&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;unit&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;percentunit&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;override&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;values&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;orientation&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;horizontal&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;showThresholdLabels&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;showThresholdMarkers&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;pluginVersion&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;6.5.2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;targets&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;expr&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;instant&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;refId&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;A&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;timeFrom&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;timeShift&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Memory Usage&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;gauge&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;datasource&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;gridPos&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;h&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;w&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;x&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;y&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;options&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;fieldOptions&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;calcs&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;last&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;defaults&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;mappings&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;max&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;min&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;thresholds&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;color&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;green&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;color&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;red&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;color&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;#EAB839&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;unit&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;percentunit&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;override&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;values&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;orientation&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;auto&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;showThresholdLabels&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;showThresholdMarkers&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;pluginVersion&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;6.5.2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;targets&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;expr&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;1 - (node_filesystem_avail_bytes{mountpoint=\&amp;#34;/\&amp;#34;} / node_filesystem_size_bytes{mountpoint=\&amp;#34;/\&amp;#34;})&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;refId&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;A&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;timeFrom&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;timeShift&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Disk Usage&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;gauge&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;aliasColors&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;bars&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;dashLength&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;dashes&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;datasource&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;fill&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;fillGradient&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;gridPos&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;h&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;w&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;x&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;y&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;hiddenSeries&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;legend&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;avg&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;current&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;max&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;min&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;show&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;total&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;values&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;lines&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;linewidth&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;nullPointMode&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;null&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;options&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;dataLinks&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;percentage&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;pointradius&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;points&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;renderer&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;flot&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;seriesOverrides&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;spaceLength&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;stack&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;steppedLine&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;targets&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;expr&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;avg without(cpu) (rate(node_cpu_seconds_total{mode!=\&amp;#34;idle\&amp;#34;}[1m]))&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;legendFormat&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;{{mode}}&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;refId&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;A&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;thresholds&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;timeFrom&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;timeRegions&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;timeShift&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;CPU Usage&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;tooltip&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;shared&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;sort&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;value_type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;individual&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;graph&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;xaxis&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;buckets&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;mode&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;show&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;values&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;yaxes&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;format&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;percentunit&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;label&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;logBase&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;max&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;min&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;show&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;format&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;short&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;label&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;logBase&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;max&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;min&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;show&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;yaxis&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;align&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;alignLevel&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;aliasColors&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;bars&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;dashLength&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;dashes&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;datasource&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;fill&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;fillGradient&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;gridPos&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;h&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;w&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;x&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;y&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;hiddenSeries&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;legend&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;avg&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;current&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;max&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;min&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;show&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;total&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;values&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;lines&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;linewidth&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;nullPointMode&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;null&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;options&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;dataLinks&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;percentage&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;pointradius&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;points&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;renderer&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;flot&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;seriesOverrides&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;spaceLength&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;stack&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;steppedLine&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;targets&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;expr&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;instant&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;intervalFactor&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;legendFormat&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Memory in Use&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;refId&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;A&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;expr&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;node_memory_MemTotal_bytes&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;legendFormat&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Memory Total&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;refId&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;B&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;thresholds&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;timeFrom&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;timeRegions&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;timeShift&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Memory Usage&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;tooltip&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;shared&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;sort&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;value_type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;individual&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;graph&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;xaxis&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;buckets&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;mode&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;show&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;values&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;yaxes&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;format&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;decbytes&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;label&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;logBase&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;max&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;min&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;show&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;format&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;short&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;label&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;logBase&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;max&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;min&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;show&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;yaxis&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;align&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;alignLevel&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;aliasColors&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;bars&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;dashLength&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;dashes&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;datasource&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;fill&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;fillGradient&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;gridPos&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;h&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;w&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;x&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;y&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;hiddenSeries&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;legend&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;avg&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;current&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;max&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;min&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;show&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;total&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;values&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;lines&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;linewidth&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;nullPointMode&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;null&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;options&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;dataLinks&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;percentage&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;pointradius&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;points&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;renderer&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;flot&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;seriesOverrides&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;spaceLength&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;stack&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;steppedLine&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;targets&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;expr&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;node_filesystem_avail_bytes{mountpoint=\&amp;#34;/\&amp;#34;}&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;refId&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;A&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;expr&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;node_filesystem_size_bytes{mountpoint=\&amp;#34;/\&amp;#34;}&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;refId&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;B&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;thresholds&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;timeFrom&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;timeRegions&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;timeShift&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Disk Usage&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;tooltip&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;shared&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;sort&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;value_type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;individual&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;graph&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;xaxis&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;buckets&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;mode&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;show&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;values&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;yaxes&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;format&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;decbytes&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;label&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;logBase&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;max&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;min&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;show&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;format&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;short&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;label&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;logBase&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;max&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;min&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;show&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;yaxis&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;align&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;alignLevel&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;refresh&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;30s&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;schemaVersion&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;style&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;dark&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;tags&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;templating&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;list&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;from&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;now-6h&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;to&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;now&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;timepicker&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;refresh_intervals&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;5s&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;10s&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;30s&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;1m&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;5m&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;15m&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;30m&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;1h&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;2h&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;1d&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;timezone&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Node exporter&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;uid&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;JuC2wgWgk&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;version&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;やったぜ.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;Node exporterが吐き出したメトリクスをPrometheusで収集し,&lt;br&gt;
それをGrafanaでグラフ化するまでの流れをラズパイで試すことができた.&lt;br&gt;
オタクなのでいろんな情報が1つのダッシュボードに表示されていると気持ちよくなってしまう&amp;hellip;&lt;br&gt;
Grafanaは色んな意味で時間泥棒.&lt;br&gt;
後で気が向いたら&lt;a class="link" href="https://github.com/prometheus/alertmanager" target="_blank" rel="noopener"
 &gt;Alertmanager&lt;/a&gt;を入れてみる.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="しっぽがかわいいそとちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sotochan_hu_e05cabf29ca9de50.jpg 800w, https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sotochan_hu_9a185a3ae6b2717f.jpg 1600w, https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sotochan_hu_47f7e4f551f245cf.jpg 2400w, https://blog.uzimihsr.com/post/2020-01-15-prometheus-grafana-raspberry-pi/2020-01-15-sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>Raspberry PiのIPを固定していろいろできるようにした</title><link>https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/</link><pubDate>Tue, 07 Jan 2020 11:35:15 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sotochan.jpg" alt="Featured image of post Raspberry PiのIPを固定していろいろできるようにした" /&gt;&lt;h2 id="部屋のラズパイにsshとかしたい"&gt;部屋のラズパイにSSHとかしたい
&lt;/h2&gt;&lt;p&gt;適当に作ったアプリの動作確認とかでたまに使ってるラズパイが部屋に転がってるんだけど,&lt;br&gt;
使うたびに画面につないだりするのが面倒なので部屋のMacBookからサクッとSSHとかVNCで作業できるようにした.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;ラズパイにSSHする設定を行った&lt;/li&gt;
&lt;li&gt;ラズパイのIPを固定した&lt;/li&gt;
&lt;li&gt;ついでにVNCでGUIを触れるようにした&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Raspberry Pi 3 Model B+
&lt;ul&gt;
&lt;li&gt;IP固定したいラズパイ&lt;/li&gt;
&lt;li&gt;ルーターに無線接続している状態&lt;/li&gt;
&lt;li&gt;OSはRaspbian(10.0)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;E-WMTA2.3
&lt;ul&gt;
&lt;li&gt;うちにあるルーター&lt;/li&gt;
&lt;li&gt;SoftBank光にすると使わざるを得ないやつ&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.softbank.jp/support/faq/view/24536" target="_blank" rel="noopener"
 &gt;スペック&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;MacBook
&lt;ul&gt;
&lt;li&gt;ラズパイと同じルーターに無線接続してるコンピュータ&lt;/li&gt;
&lt;li&gt;動作確認くらいにしか使わないのでSSHが使えればなんでも良い&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%a9%e3%82%ba%e3%83%91%e3%82%a4%e3%81%aessh%e8%a8%ad%e5%ae%9a" &gt;ラズパイのSSH設定&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%a9%e3%82%ba%e3%83%91%e3%82%a4%e3%81%aeip%e3%82%a2%e3%83%89%e3%83%ac%e3%82%b9%e5%9b%ba%e5%ae%9a" &gt;ラズパイのIPアドレス固定&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#vnc%e3%81%ae%e8%a8%ad%e5%ae%9a" &gt;VNCの設定&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="ラズパイのssh設定"&gt;ラズパイのSSH設定
&lt;/h3&gt;&lt;p&gt;まずはラズパイにSSHできるように設定する.&lt;/p&gt;
&lt;p&gt;ラズパイのデスクトップ左上のメニューから,&lt;br&gt;
&lt;code&gt;Preferences&lt;/code&gt;-&amp;gt;&lt;code&gt;Raspberry Pi Configuration&lt;/code&gt;-&amp;gt;&lt;code&gt;Interfaces&lt;/code&gt;と進み, &lt;code&gt;SSH&lt;/code&gt;の&lt;code&gt;Enable&lt;/code&gt;を選択して&lt;code&gt;OK&lt;/code&gt;を押す.&lt;br&gt;
これでSSHの準備は完了.&lt;/p&gt;
&lt;p&gt;&lt;img alt="SSH設定" class="gallery-image" data-flex-basis="258px" data-flex-grow="107" height="500" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-raspberry-pi-sc01.png" width="539"&gt;&lt;/p&gt;
&lt;p&gt;試しにラズパイのIPが固定されていない状態でMacBookからSSHしてみる.&lt;/p&gt;
&lt;p&gt;まずはラズパイ側でIPアドレスを確認.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ラズパイで実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 無線接続しているのでwlan0のinetを見る&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ifconfig
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;eth0: ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;lo: ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;wlan0: &lt;span class="nv"&gt;flags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4163&amp;lt;UP,BROADCAST,RUNNING,MULTICAST&amp;gt; mtu &lt;span class="m"&gt;1500&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; inet 192.168.3.11 netmask 255.255.255.0 broadcast 192.168.3.255
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以上よりラズパイのIP(DHCPで割り振られたもの)は &lt;strong&gt;192.168.3.11&lt;/strong&gt; であることがわかったので, MacBookからSSHしてみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# MacBookで実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ hostname
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;macbook.local
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ラズパイのデフォルトユーザー(pi)で入る&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 先程確認したラズパイのIPを指定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ssh pi@192.168.3.11
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pi@192.168.3.11&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;s password: &lt;span class="c1"&gt;# piのパスワードを入力&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Linux raspberrypi 4.19.50-v7+ &lt;span class="c1"&gt;#896 SMP Thu Jun 20 16:11:44 BST 2019 armv7l&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;The programs included with the Debian GNU/Linux system are free software&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;the exact distribution terms &lt;span class="k"&gt;for&lt;/span&gt; each program are described in the
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;individual files in /usr/share/doc/*/copyright.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;permitted by applicable law.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Last login: Tue Jan &lt;span class="m"&gt;7&lt;/span&gt; 00:21:34 &lt;span class="m"&gt;2020&lt;/span&gt; from 192.168.3.2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;pi@192.168.3.11&lt;span class="o"&gt;]&lt;/span&gt;$ hostname
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;raspberrypi
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;やったぜ.&lt;br&gt;
ラズパイにSSHできた.&lt;/p&gt;
&lt;h3 id="ラズパイのipアドレス固定"&gt;ラズパイのIPアドレス固定
&lt;/h3&gt;&lt;p&gt;上記の手順だとラズパイの電源を入れ直したときなどDHCPで新しいIPが振られるたびに確認が必要になって手間になるので,&lt;br&gt;
次はラズパイのIPをDHCPではなく固定するようにする.&lt;/p&gt;
&lt;p&gt;まずは&lt;a class="link" href="http://ybb.softbank.jp/support/connect/hikari/router/bbu23-menu.php" target="_blank" rel="noopener"
 &gt;こちらの手順&lt;/a&gt;を参考にブラウザで以下のアドレスからルーター(E-WMTA2.3)の設定画面を開く.&lt;br&gt;
ラズパイのブラウザは見づらいので自分はMacBookのChromeを使った.&lt;br&gt;
http://172.16.255.254/&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ルーター機能の設定&lt;/code&gt;-&amp;gt;&lt;code&gt;IPアドレス／DHCPサーバの設定&lt;/code&gt;と進んで&lt;code&gt;割当IPアドレスの範囲&lt;/code&gt;を確認する.&lt;/p&gt;
&lt;p&gt;&lt;img alt="ルーター設定" class="gallery-image" data-flex-basis="599px" data-flex-grow="249" height="880" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sc01.png" srcset="https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sc01_hu_6bcd4732d46e6a06.png 800w, https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sc01_hu_7260a27bd8c0d6df.png 1600w, https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sc01.png 2198w" width="2198"&gt;&lt;/p&gt;
&lt;p&gt;この場合は &lt;strong&gt;192.168.3.2&lt;/strong&gt; ~ &lt;strong&gt;192.168.3.254&lt;/strong&gt; までがDHCPで使われるIPになっている.&lt;br&gt;
(他のルーターでも同じようにDHCPで使うIPの範囲を確認できるはず)&lt;/p&gt;
&lt;p&gt;おそらく&lt;a class="link" href="https://www.softbank.jp/support/faq/view/19680" target="_blank" rel="noopener"
 &gt;この手順&lt;/a&gt;を使えばラズパイ側で設定しなくてもラズパイのMACアドレスに対してIPを固定できるんだけど(正確にはDHCPで振られるIPが固定される?),&lt;br&gt;
今回はラズパイの設定をいじる形でやってみる.&lt;/p&gt;
&lt;p&gt;このままだと他のデバイスが増えた場合にDHCPで使われる範囲が固定したいIPとかぶるかもしれない(ほんまか?)ので, 念の為範囲を &lt;strong&gt;192.168.3.2&lt;/strong&gt; ~ &lt;strong&gt;192.168.3.128&lt;/strong&gt; に変更しておく.&lt;/p&gt;
&lt;p&gt;&lt;img alt="ルーター設定" class="gallery-image" data-flex-basis="571px" data-flex-grow="238" height="920" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sc02.png" srcset="https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sc02_hu_6456c653a9b21e42.png 800w, https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sc02_hu_935b2ef664690fbc.png 1600w, https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sc02.png 2190w" width="2190"&gt;&lt;/p&gt;
&lt;p&gt;ルーターを再起動する.&lt;/p&gt;
&lt;p&gt;次にラズパイの設定ファイル&lt;code&gt;/etc/dhcpcd.conf&lt;/code&gt;を編集し, 任意のIPで固定する.&lt;br&gt;
今回は &lt;strong&gt;192.168.3.200&lt;/strong&gt; で固定する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 以下は全てラズパイで実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# デフォルトゲートウェイの確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ route
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Kernel IP routing table
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Destination Gateway Genmask Flags Metric Ref Use Iface
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;default 192.168.3.1 0.0.0.0 UG &lt;span class="m"&gt;303&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; wlan0 &lt;span class="c1"&gt;# この行の情報を使う&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;192.168.3.0 0.0.0.0 255.255.255.0 U &lt;span class="m"&gt;303&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; wlan0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 設定ファイルを編集&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim /etc/dhcpcd.conf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 以下の記述を末尾に追加&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;interface wlan0 &lt;span class="c1"&gt;# routeで確認したIface&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;static &lt;span class="nv"&gt;ip_address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;192.168.3.200/24 &lt;span class="c1"&gt;# 任意の固定IP&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;static &lt;span class="nv"&gt;routers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;192.168.3.1 &lt;span class="c1"&gt;# Gateway&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;static &lt;span class="nv"&gt;domain_name_servers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;192.168.3.1 &lt;span class="c1"&gt;# 特にDNSの設定をしていなければroutersと同じ値で問題ないはず&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;編集後, ラズパイを再起動する&amp;hellip;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 再度ラズパイでIPを確認する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ifconfig
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;eth0: ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;lo: ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;wlan0: &lt;span class="nv"&gt;flags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4163&amp;lt;UP,BROADCAST,RUNNING,MULTICAST&amp;gt; mtu &lt;span class="m"&gt;1500&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; inet 192.168.3.200 netmask 255.255.255.0 broadcast 192.168.3.255
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;電源何回入れ直しても同じIPになる.&lt;br&gt;
どうやら指定したIPで固定されたっぽい.&lt;/p&gt;
&lt;p&gt;今度はMacBookから固定IPを指定してSSHする.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# MacBookで実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 固定IPを指定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ssh pi@192.168.3.200
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;The authenticity of host &lt;span class="s1"&gt;&amp;#39;192.168.3.200 (192.168.3.200)&amp;#39;&lt;/span&gt; can&lt;span class="s1"&gt;&amp;#39;t be established.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;ECDSA key fingerprint is SHA256:...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;Are you sure you want to continue connecting (yes/no)? yes
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;Warning: Permanently added &amp;#39;&lt;/span&gt;192.168.3.200&lt;span class="s1"&gt;&amp;#39; (ECDSA) to the list of known hosts.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;pi@192.168.3.200&amp;#39;&lt;/span&gt;s password:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Linux raspberrypi 4.19.50-v7+ &lt;span class="c1"&gt;#896 SMP Thu Jun 20 16:11:44 BST 2019 armv7l&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;The programs included with the Debian GNU/Linux system are free software&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;the exact distribution terms &lt;span class="k"&gt;for&lt;/span&gt; each program are described in the
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;individual files in /usr/share/doc/*/copyright.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;permitted by applicable law.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Last login: Tue Jan &lt;span class="m"&gt;7&lt;/span&gt; 01:45:23 &lt;span class="m"&gt;2020&lt;/span&gt; from 192.168.3.5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;pi@192.168.3.200&lt;span class="o"&gt;]&lt;/span&gt;$ hostname
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;raspberrypi
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;できた.&lt;br&gt;
やったぜ.&lt;/p&gt;
&lt;h3 id="vncの設定"&gt;VNCの設定
&lt;/h3&gt;&lt;p&gt;SSHできるようになったので, ついでにVNCでGUIをいじれるようにする.&lt;br&gt;
ラズパイのGUIはあんまり触らなさそうだけど, 念の為.&lt;/p&gt;
&lt;p&gt;といってもRaspbianにはRealVNCが最初から入っているので, 必要な設定はほとんどない.&lt;br&gt;
SSHを有効にしたときと同様にやればいい.&lt;/p&gt;
&lt;p&gt;ラズパイのデスクトップ左上のメニューから,&lt;br&gt;
&lt;code&gt;Preferences&lt;/code&gt;-&amp;gt;&lt;code&gt;Raspberry Pi Configuration&lt;/code&gt;-&amp;gt;&lt;code&gt;Interfaces&lt;/code&gt;と進み, &lt;code&gt;VNC&lt;/code&gt;の&lt;code&gt;Enable&lt;/code&gt;を選択して&lt;code&gt;OK&lt;/code&gt;を押す.&lt;br&gt;
&lt;img alt="VNC設定" class="gallery-image" data-flex-basis="258px" data-flex-grow="107" height="500" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-raspberry-pi-sc01.png" width="539"&gt;&lt;/p&gt;
&lt;p&gt;ラズパイ側の準備は完了.&lt;br&gt;
MacBookに最初から入ってる画面共有.appで固定IPを指定して接続を試みると失敗する.&lt;/p&gt;
&lt;p&gt;&lt;img alt="デフォルトの画面共有だとだめ" class="gallery-image" data-flex-basis="485px" data-flex-grow="202" height="526" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sc03.png" srcset="https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sc03_hu_545829e151e5a1ae.png 800w, https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sc03.png 1064w" width="1064"&gt;&lt;/p&gt;
&lt;p&gt;対処法がよくわかんないので普通に&lt;a class="link" href="https://www.realvnc.com/en/connect/download/viewer/" target="_blank" rel="noopener"
 &gt;VNC Viewer&lt;/a&gt;をMacBookにインストールして起動.&lt;br&gt;
検索窓みたいなやつにラズパイのIPを打ち込んでEnterを押すとなんか色々聞かれるけど問題なし.&lt;/p&gt;
&lt;p&gt;&lt;img alt="なんか聞かれる" class="gallery-image" data-flex-basis="326px" data-flex-grow="136" height="1321" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sc05.png" srcset="https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sc05_hu_8bc1ceca440916ed.png 800w, https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sc05_hu_8157017eab6d82ad.png 1600w, https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sc05.png 1799w" width="1799"&gt;&lt;/p&gt;
&lt;p&gt;ラズパイのユーザー名とパスワードを聞かれるので入力.&lt;/p&gt;
&lt;p&gt;&lt;img alt="たのむ" class="gallery-image" data-flex-basis="326px" data-flex-grow="135" height="1323" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sc06.png" srcset="https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sc06_hu_be85e60145b5c9da.png 800w, https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sc06_hu_acd80b58842e6b8d.png 1600w, https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sc06.png 1799w" width="1799"&gt;&lt;/p&gt;
&lt;p&gt;ラズパイの画面が開く.&lt;br&gt;
やったぜ.&lt;/p&gt;
&lt;p&gt;&lt;img alt="VNCできた画面" class="gallery-image" data-flex-basis="298px" data-flex-grow="124" height="1140" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sc07.png" srcset="https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sc07_hu_3f6cb6892076a8f7.png 800w, https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sc07.png 1416w" width="1416"&gt;&lt;/p&gt;
&lt;p&gt;このままだと解像度が低くてストレスがマッハなので,&lt;br&gt;
ラズパイ側で再度設定を行う.&lt;/p&gt;
&lt;p&gt;ラズパイのデスクトップ左上のメニューから,&lt;br&gt;
&lt;code&gt;Preferences&lt;/code&gt;-&amp;gt;&lt;code&gt;Raspberry Pi Configuration&lt;/code&gt;-&amp;gt;&lt;code&gt;System&lt;/code&gt;と進み, &lt;code&gt;Resolution&lt;/code&gt;を&lt;code&gt;Default&lt;/code&gt;から好みの解像度(自分の場合は&lt;code&gt;DMT Mode 82&lt;/code&gt;)に変更する.&lt;br&gt;
ラズパイの再起動を求められるのでYesを押す.&lt;/p&gt;
&lt;p&gt;&lt;img alt="解像度の設定" class="gallery-image" data-flex-basis="298px" data-flex-grow="124" height="1140" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sc08.png" srcset="https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sc08_hu_133a61564b22d34e.png 800w, https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sc08.png 1416w" width="1416"&gt;&lt;/p&gt;
&lt;p&gt;少し時間がかかるが, ラズパイが再起動すると自動的にVNC Viewerの画面も再接続され,&lt;br&gt;
解像度が上がった画面が表示される.&lt;/p&gt;
&lt;p&gt;&lt;img alt="解像度が上がったラズパイ画面" class="gallery-image" data-flex-basis="382px" data-flex-grow="159" height="1890" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sc09.png" srcset="https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sc09_hu_569501140ca6dd19.png 800w, https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sc09_hu_4058836986e3a719.png 1600w, https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sc09_hu_39c4e9c5a24696fc.png 2400w, https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sc09.png 3016w" width="3016"&gt;&lt;/p&gt;
&lt;p&gt;やったぜ.&lt;br&gt;
これでGUIも使えるようになった(たぶんあんまり使わない).&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;以上の手順で家の中のパソコンからいつでもラズパイに接続できるようになった.&lt;br&gt;
ラズパイに毎回ディスプレイとキーボード繋ぐのめんどくさかったし, もっと早くやればよかった&amp;hellip;&lt;br&gt;
ルーターでポート周りの設定をすれば家の外からも接続できるっぽいんだけど,&lt;br&gt;
自宅サーバーの運用とかよくわかってないしちょっとセキュリティ的にも怖いので当分の間はこれで遊ぶつもり.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="ねずみ年そとちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sotochan_hu_d0f350f586af7a8a.jpg 800w, https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sotochan_hu_51e3731d9412c6b2.jpg 1600w, https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sotochan_hu_18b5023960fb0f50.jpg 2400w, https://blog.uzimihsr.com/post/2020-01-07-raspberry-pi-static-id/2020-01-07-sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>Kubernetes完全に理解したい 4章</title><link>https://blog.uzimihsr.com/post/2019-12-16-kubernetes-guide-chap4/</link><pubDate>Mon, 16 Dec 2019 21:26:15 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2019-12-16-kubernetes-guide-chap4/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2019-12-16-kubernetes-guide-chap4/2019-12-16-sotochan.jpg" alt="Featured image of post Kubernetes完全に理解したい 4章" /&gt;&lt;h2 id="完全に理解したい"&gt;完全に理解したい
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://book.impress.co.jp/books/1118101055" target="_blank" rel="noopener"
 &gt;Kubernetes完全ガイド&lt;/a&gt;をまじめに読み始めたのでちょっとずつまとめていきたい.&lt;br&gt;
1~3章はDockerのおさらいだったりKubernetesとは?みたいな話だったので割愛.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="読んだもの"&gt;読んだもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://book.impress.co.jp/books/1118101055" target="_blank" rel="noopener"
 &gt;Kubernetes完全ガイド&lt;/a&gt; 4章(APIリソースとkubectl)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;重要そうなところとかよく使いそうなところだけまとめる.&lt;/p&gt;
&lt;h2 id="読んだことのまとめ"&gt;読んだことのまとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Kubernetes&lt;/code&gt;には役割の異なるたくさんのリソースがある.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Namespace&lt;/code&gt;によりクラスタを仮想的に分離できる.&lt;/li&gt;
&lt;li&gt;リソースに関する操作は&lt;code&gt;Kubernetes API&lt;/code&gt;を通じて行う. CLIなら&lt;code&gt;kubectl&lt;/code&gt;でいろいろ操作できる.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="kubernetesリソースの種類"&gt;Kubernetesリソースの種類
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Kubernetes&lt;/code&gt;のリソースはだいたい5種類に分けられるらしい.&lt;/p&gt;
&lt;h4 id="workloads"&gt;Workloads
&lt;/h4&gt;&lt;p&gt;コンテナを実行する部分に関わるリソース. 基本的に&lt;code&gt;Pod&lt;/code&gt;と各種&lt;code&gt;Controller&lt;/code&gt;で構成される.&lt;br&gt;
重要そうなものだけ以下にまとめる.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;リソース&lt;/th&gt;
 &lt;th&gt;概要&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;Pod&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Kubernetes&lt;/code&gt;の最小単位&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;ReplicaSet&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Pod&lt;/code&gt;のレプリカを複数維持する&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;Deployment&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;ReplicaSet&lt;/code&gt;を複数管理する&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;DaemonSet&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;各&lt;code&gt;Node&lt;/code&gt;に&lt;code&gt;Pod&lt;/code&gt;を1台ずつ維持する&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;StatefulSet&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;ステートフルな&lt;code&gt;Deployment&lt;/code&gt;と&lt;code&gt;Pod&lt;/code&gt;を管理する&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;Job&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;回数制限付きの&lt;code&gt;Pod&lt;/code&gt;の処理を行う&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;CronJob&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Job&lt;/code&gt;のスケジューリングを行う&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id="discovery--lb"&gt;Discovery &amp;amp; LB
&lt;/h4&gt;&lt;p&gt;コンテナの通信に関わるリソース.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;リソース&lt;/th&gt;
 &lt;th&gt;概要&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;Service&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;複数の&lt;code&gt;Pod&lt;/code&gt;で構成されるアプリケーションを外部に公開するL4レベルのLB&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;Ingress&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;外部から&lt;code&gt;Service&lt;/code&gt;へのアクセスを可能にするL7レベルのLB&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id="config--storage"&gt;Config &amp;amp; Storage
&lt;/h4&gt;&lt;p&gt;コンテナの設定ファイルや機密情報, 永続化ボリュームに関するリソース.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;リソース&lt;/th&gt;
 &lt;th&gt;概要&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;Secret&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Pod&lt;/code&gt;で扱うパスワードや鍵などの機密情報を管理する&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;ConfigMap&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Pod&lt;/code&gt;で扱う設定情報を管理する&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;PersistentVolumeClaim&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;PersistentVolume&lt;/code&gt;(後述)を管理する&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id="cluster"&gt;Cluster
&lt;/h4&gt;&lt;p&gt;クラスタ自体の挙動に関するリソース.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;リソース&lt;/th&gt;
 &lt;th&gt;概要&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;Node&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Master&lt;/code&gt;によって管理されるワーカーマシン&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;Namespace&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;クラスタを仮想的に分離させる&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;PersistentVolume&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Pod&lt;/code&gt;から利用できる永続化ボリューム&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;ResourceQuota&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Namespace&lt;/code&gt;ごとに使用できるリソースの数に制限をかける&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;ServiceAccount&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Namespace&lt;/code&gt;に紐付いたユーザ情報&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;Role&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Namespace&lt;/code&gt;レベルで許可される操作の情報&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;ClusterRole&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;クラスタレベルで許可される操作の情報&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;RoleBinding&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Namespace&lt;/code&gt;レベルでユーザ情報と&lt;code&gt;Role&lt;/code&gt;を紐付けて権限管理を行う&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;ClusterRoleBinding&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;クラスタレベルでユーザ情報と&lt;code&gt;ClusterRole&lt;/code&gt;を紐付けて権限管理を行う&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;NetworkPolicy&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;クラスタ内の&lt;code&gt;Pod&lt;/code&gt;同士の通信を制限する&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id="metadata"&gt;Metadata
&lt;/h4&gt;&lt;p&gt;クラスタ内の他のリソースを操作するためのリソース.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;リソース&lt;/th&gt;
 &lt;th&gt;概要&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;LimitRange&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Namespace&lt;/code&gt;レベルで&lt;code&gt;Pod&lt;/code&gt;が使用できるCPUやメモリの制限を行う&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;HorizontalPodAutoscaler&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Deployment&lt;/code&gt;または&lt;code&gt;ReplicaSet&lt;/code&gt;のオートスケーリングを行う&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;PodDisruptionBudget&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Node&lt;/code&gt;更新処理の際に維持する&lt;code&gt;Pod&lt;/code&gt;の数を設定する&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;CustomRessourceDefinition&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;独自のリソースを作って&lt;code&gt;Kubernetes&lt;/code&gt;を拡張する&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="namespaceによる仮想クラスタ分離"&gt;Namespaceによる仮想クラスタ分離
&lt;/h3&gt;&lt;p&gt;クラスタ作成時にデフォルトで作成される&lt;code&gt;Namespace&lt;/code&gt;は3つ.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;kube-system&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;クラスタの各種コンポーネントやアドオンといったシステムがデプロイされる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;kube-public&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;全ユーザが使用可能な&lt;code&gt;ConfigMap&lt;/code&gt;などの情報が配置される&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;default&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;ユーザーがデフォルトで使用し, 任意のリソースが作成される&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Namespaceの一覧を表示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get namespaces
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME STATUS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;default Active 90m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube-public Active 90m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube-system Active 90m
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="kubectl"&gt;kubectl
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;kubectl&lt;/code&gt;は&lt;code&gt;Master&lt;/code&gt;の&lt;code&gt;kube-apiserver&lt;/code&gt;と通信を行うCLIツール.&lt;br&gt;
&lt;code&gt;Kubernetes API&lt;/code&gt;自体はRESTfulであるから代わりに各言語のクライアントライブラリを使うこともできる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ローカルからAPIにアクセスするためにproxyを別ターミナルで起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl proxy
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Starting to serve on 127.0.0.1:8001
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# APIを直接叩いてNamespaceの一覧を表示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# $(kubectl get namespaces)と同じ情報を取得できる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl 127.0.0.1:8001/api/v1/namespaces
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;kind&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;NamespaceList&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;apiVersion&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;v1&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;metadata&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;selfLink&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;/api/v1/namespaces&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;resourceVersion&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;23058&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;items&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;metadata&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;default&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;selfLink&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;/api/v1/namespaces/default&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;uid&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;...&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;resourceVersion&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;25&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;creationTimestamp&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;2019-12-16T12:29:50Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;spec&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;finalizers&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;kubernetes&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;status&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;phase&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;Active&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;metadata&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;kube-public&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;selfLink&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;/api/v1/namespaces/kube-public&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;uid&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;...&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;resourceVersion&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;35&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;creationTimestamp&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;2019-12-16T12:29:50Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;spec&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;finalizers&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;kubernetes&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;status&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;phase&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;Active&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;metadata&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;kube-system&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;selfLink&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;/api/v1/namespaces/kube-system&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;uid&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;...&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;resourceVersion&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;166&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;creationTimestamp&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;2019-12-16T12:29:50Z&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;annotations&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;kubectl.kubernetes.io/last-applied-configuration&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;{\&amp;#34;apiVersion\&amp;#34;:\&amp;#34;v1\&amp;#34;,\&amp;#34;kind\&amp;#34;:\&amp;#34;Namespace\&amp;#34;,\&amp;#34;metadata\&amp;#34;:{\&amp;#34;annotations\&amp;#34;:{},\&amp;#34;name\&amp;#34;:\&amp;#34;kube-system\&amp;#34;,\&amp;#34;namespace\&amp;#34;:\&amp;#34;\&amp;#34;}}\n&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;spec&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;finalizers&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;kubernetes&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;status&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;phase&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;Active&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;上の例では&lt;code&gt;curl&lt;/code&gt;で認証情報を渡すのが面倒なのでproxyを使用したが,&lt;br&gt;
本来&lt;code&gt;kubectl&lt;/code&gt;が&lt;code&gt;kube-apiserver&lt;/code&gt;と通信するために必要な認証情報は&lt;code&gt;kubeconfig(~/.kube/config)&lt;/code&gt;に記述する.&lt;br&gt;
各種サービスを使用してクラスタを構築した場合はデフォルトで記述されていることが多い.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# kubeconfigを確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat ~/.kube/config
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apiVersion: v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;clusters:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- cluster:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; certificate-authority-data: ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; server: https://34.83.155.176
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: gke_uzimihsr-01_us-west1-a_uzimihsr-k8s-perfect-guide
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- cluster:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; certificate-authority: /Users/uzimihsr/.minikube/ca.crt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; server: https://192.168.99.110:8443
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;contexts:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- context:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cluster: gke_uzimihsr-01_us-west1-a_uzimihsr-k8s-perfect-guide
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; user: gke_uzimihsr-01_us-west1-a_uzimihsr-k8s-perfect-guide
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: gke_uzimihsr-01_us-west1-a_uzimihsr-k8s-perfect-guide
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- context:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cluster: minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; user: minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;current-context: gke_uzimihsr-01_us-west1-a_uzimihsr-k8s-perfect-guide
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kind: Config
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;preferences: &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;users:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- name: gke_uzimihsr-01_us-west1-a_uzimihsr-k8s-perfect-guide
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; user:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; auth-provider:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; config:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; access-token: ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cmd-args: config config-helper --format&lt;span class="o"&gt;=&lt;/span&gt;json
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cmd-path: /Users/uzimihsr/google-cloud-sdk/bin/gcloud
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; expiry: 2019-12-16T14:59:54Z
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; expiry-key: &lt;span class="s1"&gt;&amp;#39;{.credential.token_expiry}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; token-key: &lt;span class="s1"&gt;&amp;#39;{.credential.access_token}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: gcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- name: minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; user:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; client-certificate: /Users/uzimihsr/.minikube/client.crt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; client-key: /Users/uzimihsr/.minikube/client.key
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;kubectl&lt;/code&gt;では&lt;code&gt;kubeconfig&lt;/code&gt;の&lt;code&gt;Context&lt;/code&gt;を切り替えることで異なるクラスタへ接続することができる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Contextの一覧を表示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# GKE用のContextを使用している&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl config get-contexts
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;CURRENT NAME CLUSTER AUTHINFO NAMESPACE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* gke_uzimihsr-01_us-west1-a_uzimihsr-k8s-perfect-guide gke_uzimihsr-01_us-west1-a_uzimihsr-k8s-perfect-guide gke_uzimihsr-01_us-west1-a_uzimihsr-k8s-perfect-guide
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; minikube minikube minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 使用するContextを変更&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl config use-context minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Switched to context &lt;span class="s2"&gt;&amp;#34;minikube&amp;#34;&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 現在のContextを確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl config current-context
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;minikube
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;kubectl&lt;/code&gt;とマニフェストファイルを使ってリソースの操作をすることができる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# リソース(Pod)の作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f sample-pod.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/sample-pod created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podの一覧表示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-pod 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 18s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# リソースの削除&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl delete -f sample-pod.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod &lt;span class="s2"&gt;&amp;#34;sample-pod&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/master/samples/chapter04/sample-pod.yaml" target="_blank" rel="noopener"
 &gt;sample-pod.yaml&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;リソースにKey-Value形式のラベルをつけることで, 管理がしやすくなる.&lt;br&gt;
&lt;code&gt;ReplicaSet&lt;/code&gt;や&lt;code&gt;Service&lt;/code&gt;ではこのラベルを使用して&lt;code&gt;Pod&lt;/code&gt;の管理を行っている.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Pod(sample-label)はlabel1(Key)=val1(Value)とlabel2=val2の2つのラベルを持つ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl describe pod sample-label
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: &lt;span class="nv"&gt;label1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;val1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;label2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;val2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podの一覧表示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-label 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 59s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-pod 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 29s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ラベル(label1=val1)で絞り込む&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -l &lt;span class="nv"&gt;label1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;val1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-label 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 5m55s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ラベルのValueを表示させる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -L label1 -L label2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE LABEL1 LABEL2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-label 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 7m41s val1 val2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-pod 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 7m11s
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="link" href="https://github.com/MasayaAoyama/kubernetes-perfect-guide/blob/master/samples/chapter04/sample-label.yaml" target="_blank" rel="noopener"
 &gt;sample-label.yaml&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;kubectl get&lt;/code&gt;はオプションを付けることで出力形式を指定することができる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 詳細な情報を付与して一覧表示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -o wide
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-label 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 11m 10.4.2.4 gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-0dgf &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-pod 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 10m 10.4.2.5 gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-0dgf &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# YAML形式でPod(sample-pod)の情報を出力&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pod sample-pod -o yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apiVersion: v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kind: Pod
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;status:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; hostIP: 10.138.0.5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 表示項目を指定して一覧表示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podのmetadata.nameの値をNAME, status.hostIPの値をNodeIPとして表示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -o custom-columns&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;NAME:{.metadata.name},NodeIP:{.status.hostIP}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME NodeIP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-label 10.138.0.5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-pod 10.138.0.5
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;kubectl top&lt;/code&gt;でCPUやメモリの使用量を確認できる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# NodeのCPU, メモリ使用量を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl top nodes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME CPU&lt;span class="o"&gt;(&lt;/span&gt;cores&lt;span class="o"&gt;)&lt;/span&gt; CPU% MEMORY&lt;span class="o"&gt;(&lt;/span&gt;bytes&lt;span class="o"&gt;)&lt;/span&gt; MEMORY%
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-0dgf 51m 5% 674Mi 25%
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-n2mf 117m 12% 786Mi 29%
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-wk64 37m 3% 651Mi 24%
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# PodのCPU, メモリ使用量をコンテナ情報つきで確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl top pods --containers
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;POD NAME CPU&lt;span class="o"&gt;(&lt;/span&gt;cores&lt;span class="o"&gt;)&lt;/span&gt; MEMORY&lt;span class="o"&gt;(&lt;/span&gt;bytes&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-label nginx-container 0m 1Mi
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-pod nginx-container 0m 1Mi
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;kubectl exec&lt;/code&gt;で&lt;code&gt;Pod&lt;/code&gt;上でコマンドを実行することができる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podのコンテナでshを起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it sample-pod -c nginx-container /bin/sh
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Ctrl+Dまたはexitコマンドで終了&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# コマンドに引数がある場合は--の後に指定する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it sample-pod -c nginx-container -- /bin/sh -c &lt;span class="s2"&gt;&amp;#34;ls --all --classify | grep media&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;media/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;kubectl logs&lt;/code&gt;で&lt;code&gt;Pod&lt;/code&gt;のログが確認できる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# コンテナを指定してPodのログを確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl logs sample-pod -c nginx-container
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 全コンテナのログを垂れ流す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl logs -f sample-pod --all-containers
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 期間を指定して出力&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1時間前から10件分のログをタイムスタンプ付きで表示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl logs --since&lt;span class="o"&gt;=&lt;/span&gt;1h --tail&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt; --timestamps&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; sample-pod
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;kubectl cp&lt;/code&gt;で&lt;code&gt;Pod&lt;/code&gt;とローカルマシンでファイルのコピーができる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podの/etc/hostnameをローカルにコピー&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl cp sample-pod:/etc/hostname ./
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat ./hostname
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-pod
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ローカルのファイルをPodの/tmp/newfileにコピー&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl cp ./hostname sample-pod:/tmp/newfile
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it sample-pod -- /bin/sh -c &lt;span class="s2"&gt;&amp;#34;cat /tmp/newfile&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sample-pod
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;kubectl port-forward&lt;/code&gt;でポート転送ができる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# localhostの8888番ポートをPodの80番ポートに転送&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl port-forward sample-pod 8888:80
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Forwarding from 127.0.0.1:8888 -&amp;gt; &lt;span class="m"&gt;80&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Forwarding from &lt;span class="o"&gt;[&lt;/span&gt;::1&lt;span class="o"&gt;]&lt;/span&gt;:8888 -&amp;gt; &lt;span class="m"&gt;80&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 確認できたらCtrl+Cで終了&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 別ターミナルで疎通確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -I localhost:8888
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;HTTP/1.1 &lt;span class="m"&gt;200&lt;/span&gt; OK
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Server: nginx/1.12.2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="おててしまってお上品に座るそとちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-12-16-kubernetes-guide-chap4/2019-12-16-sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2019-12-16-kubernetes-guide-chap4/2019-12-16-sotochan_hu_2cd05df10e3941c.jpg 800w, https://blog.uzimihsr.com/post/2019-12-16-kubernetes-guide-chap4/2019-12-16-sotochan_hu_6b8f61352198a9dd.jpg 1600w, https://blog.uzimihsr.com/post/2019-12-16-kubernetes-guide-chap4/2019-12-16-sotochan_hu_faef3b46554adc4f.jpg 2400w, https://blog.uzimihsr.com/post/2019-12-16-kubernetes-guide-chap4/2019-12-16-sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>KubernetesのJobを試してみる</title><link>https://blog.uzimihsr.com/post/2019-12-09-pod-args/</link><pubDate>Mon, 09 Dec 2019 22:40:21 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2019-12-09-pod-args/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2019-12-09-pod-args/2019-12-09-sotochan.jpg" alt="Featured image of post KubernetesのJobを試してみる" /&gt;&lt;h2 id="yaml書いてみる"&gt;YAML書いてみる
&lt;/h2&gt;&lt;p&gt;なんだかんだで一度もリソースを手で書いたことが無いので, 自分でつくってみる.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;任意のコマンドが実行できる&lt;code&gt;Docker image&lt;/code&gt;を作成して&lt;code&gt;Kubernetes&lt;/code&gt;の&lt;code&gt;Job&lt;/code&gt;を実行してみた&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="jobとは"&gt;Jobとは
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;使い切りの&lt;code&gt;Pod&lt;/code&gt;を実行し, 設定した回数ぶん終了したら完了となるリソース
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Pod&lt;/code&gt;が処理を行った後停止することが前提&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Pod&lt;/code&gt;を監視し, 正常終了の回数が設定値を満たすまで再起動等の処理を行う&lt;/li&gt;
&lt;li&gt;一回の処理を確実に行いたい場合やバッチ的な処理に向いている&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;参考 : &lt;a class="link" href="https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/" target="_blank" rel="noopener"
 &gt;https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#docker-image%e3%81%ae%e4%bd%9c%e6%88%90" &gt;Docker imageの作成&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%9e%e3%83%8b%e3%83%95%e3%82%a7%e3%82%b9%e3%83%88%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab%e3%81%ae%e4%bd%9c%e6%88%90" &gt;マニフェストファイルの作成&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#job%e3%81%ae%e5%ae%9f%e8%a1%8c" &gt;Jobの実行&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="docker-imageの作成"&gt;Docker imageの作成
&lt;/h3&gt;&lt;p&gt;まずは&lt;code&gt;Docker image&lt;/code&gt;をつくる.&lt;br&gt;
&lt;code&gt;Dockerfile&lt;/code&gt;の書き方はだいたいわかっているつもり&amp;hellip;&lt;/p&gt;
&lt;p&gt;下記の&lt;code&gt;Dockerfile&lt;/code&gt;を適当なディレクトリで作成する.&lt;br&gt;
特に何かの処理をするわけではなく, ただ &lt;strong&gt;alpine&lt;/strong&gt; の&lt;a class="link" href="https://hub.docker.com/_/alpine" target="_blank" rel="noopener"
 &gt;image&lt;/a&gt;をベースにして適当な環境変数等を設定しただけ.&lt;br&gt;
&lt;code&gt;ENTRYPOINT&lt;/code&gt;に &lt;strong&gt;/bin/sh&lt;/strong&gt; を指定することで引数で任意のコマンドを渡せるようにする.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Dockerfile&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-docker" data-lang="docker"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# ベースイメージはalpine&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;alpine:3.10.3&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 管理者の名前&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;MAINTAINER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;uzimihsr-01&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# ディレクトリを変更&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/uzimihsr/workdir&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 環境変数を設定&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ENV&lt;/span&gt; AUTHOR uzimihsr&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ENV&lt;/span&gt; NUMBER &lt;span class="m"&gt;777&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# エントリーポイントはsh&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/bin/sh&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# デフォルトでは環境変数AUTHORを表示する&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CMD&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;-c&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;echo ${AUTHOR}&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;image&lt;/code&gt;をビルドしてDocker Hubにアップロードする.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Dockerfileがあるところで作業&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; path/to/Dockerfile
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Dockerfile
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# uzimihsr(Docker HubのID)とrepository, tagを指定してビルド&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image build -t uzimihsr/uzimihsr-sample-image:0.1 .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Sending build context to Docker daemon 58.37kB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 1/7 : FROM alpine:3.10.3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; 965ea09ff2eb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 2/7 : MAINTAINER uzimihsr-01
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; Using cache
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; be67ea5322ce
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 3/7 : WORKDIR /uzimihsr/workdir
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; Using cache
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; d953d022ec9e
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 4/7 : ENV AUTHOR uzimihsr
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; Using cache
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; f2e3624824fd
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 5/7 : ENV NUMBER &lt;span class="m"&gt;777&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; Using cache
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; c5ccb27bba82
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 6/7 : ENTRYPOINT &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/bin/sh&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; Using cache
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; 42d33fa1c9ab
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 7/7 : CMD &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;-c&amp;#34;&lt;/span&gt;, &lt;span class="s2"&gt;&amp;#34;echo &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;AUTHOR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; Using cache
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; ec0ff7287ea6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Successfully built ec0ff7287ea6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Successfully tagged uzimihsr/uzimihsr-sample-image:0.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# imageをDocker Hubにpush&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image push uzimihsr/uzimihsr-sample-image:0.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;The push refers to repository &lt;span class="o"&gt;[&lt;/span&gt;docker.io/uzimihsr/uzimihsr-sample-image&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;47cb607f05a0: Pushed
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;77cae8ab23bf: Mounted from library/alpine
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;0.1: digest: sha256:eab7f925c7b33c5604196d30a9daa3e2d9c763166543069b8f31676a74003702 size: &lt;span class="m"&gt;735&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="link" href="https://hub.docker.com/r/uzimihsr/uzimihsr-sample-image" target="_blank" rel="noopener"
 &gt;https://hub.docker.com/r/uzimihsr/uzimihsr-sample-image&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;試しにローカルにある &lt;strong&gt;uzimihsr/uzimihsr-sample-image:0.1&lt;/strong&gt; を削除した状態でコンテナを実行してみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Docker Hubにあるimageを指定してコンテナを実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Dockerfileで指定した通り$AUTHORが表示される&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run uzimihsr/uzimihsr-sample-image:0.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Unable to find image &lt;span class="s1"&gt;&amp;#39;uzimihsr/uzimihsr-sample-image:0.1&amp;#39;&lt;/span&gt; locally
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;0.1: Pulling from uzimihsr/uzimihsr-sample-image
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Digest: sha256:eab7f925c7b33c5604196d30a9daa3e2d9c763166543069b8f31676a74003702
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Status: Downloaded newer image &lt;span class="k"&gt;for&lt;/span&gt; uzimihsr/uzimihsr-sample-image:0.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;動作確認はOK.&lt;/p&gt;
&lt;h3 id="マニフェストファイルの作成"&gt;マニフェストファイルの作成
&lt;/h3&gt;&lt;p&gt;いよいよ&lt;code&gt;YAML&lt;/code&gt;を書いていく.&lt;br&gt;
基本的には&lt;code&gt;apiVersion&lt;/code&gt;, &lt;code&gt;kind&lt;/code&gt;, &lt;code&gt;metadata&lt;/code&gt;, &lt;code&gt;spec&lt;/code&gt;の項目を埋めていけばいいはず.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;apiVersion&lt;/code&gt;: このマニフェストを読む&lt;code&gt;Kubernetes API&lt;/code&gt;のバージョンを指定
&lt;ul&gt;
&lt;li&gt;今回は&lt;code&gt;Job&lt;/code&gt;を使うので&lt;code&gt;batch/v1&lt;/code&gt;を指定する&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.16/#job-v1-batch" target="_blank" rel="noopener"
 &gt;https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.16/#job-v1-batch&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;kind&lt;/code&gt;: 今回定義するリソースの種類
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Job&lt;/code&gt;を定義する&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;metadata&lt;/code&gt;: リソースを識別するためのメタ情報
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Job&lt;/code&gt;に名前をつける&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.16/#objectmeta-v1-meta" target="_blank" rel="noopener"
 &gt;https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.16/#objectmeta-v1-meta&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;spec&lt;/code&gt;: このリソースのパラメータや設定
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Job&lt;/code&gt;のパラメータや設定を定義する&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.16/#jobspec-v1-batch" target="_blank" rel="noopener"
 &gt;https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.16/#jobspec-v1-batch&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;job.yaml&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;batch/v1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# APIのバージョン&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Job&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# リソースの種類&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# メタ情報&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;uzimihsr-echo-number&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# リソース名&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Jobの定義&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Pod情報&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Jobで作成されるPodの定義&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Podに含まれるコンテナ&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;echo-number&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# コンテナ名&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;uzimihsr/uzimihsr-sample-image:0.1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 使用するimage&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;-c&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;echo ${NUMBER}&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# imageのCMDを上書きする&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;restartPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Never&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Podが失敗した場合の挙動&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;backoffLimit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 再トライ回数の制限&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ちょっとコメントを多めに入れたのでごちゃごちゃしているが, やっていることは非常にシンプル.&lt;br&gt;
&lt;code&gt;spec&lt;/code&gt;には&lt;code&gt;Job&lt;/code&gt;で実行される&lt;code&gt;Pod&lt;/code&gt;内のコンテナとその設定を書いている.&lt;br&gt;
今回は先程作った&lt;code&gt;image&lt;/code&gt;の実行時引数を&lt;code&gt;args&lt;/code&gt;で指定すると&lt;code&gt;Dockerfile&lt;/code&gt;で指定した&lt;code&gt;CMD&lt;/code&gt;を上書きしてくれるので,&lt;br&gt;
&lt;code&gt;image&lt;/code&gt;が持つ環境変数 &lt;strong&gt;NUMBER&lt;/strong&gt; を表示するように指定している.&lt;br&gt;
&lt;code&gt;Job&lt;/code&gt;では&lt;code&gt;Pod&lt;/code&gt;失敗時の挙動を指定する&lt;code&gt;restartPolicy&lt;/code&gt;に&lt;code&gt;Never&lt;/code&gt;(新しい&lt;code&gt;Pod&lt;/code&gt;を作成)か&lt;code&gt;OnFailure&lt;/code&gt;(&lt;code&gt;Node&lt;/code&gt;に&lt;code&gt;Pod&lt;/code&gt;を残したままコンテナを再実行)が指定できるが, &lt;code&gt;Never&lt;/code&gt;にしておくのが無難そう.&lt;/p&gt;
&lt;h3 id="jobの実行"&gt;Jobの実行
&lt;/h3&gt;&lt;p&gt;いよいよマニフェストを実行する.&lt;br&gt;
&lt;code&gt;kubectl&lt;/code&gt;でリソースを作成して, その後の挙動を確認する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# リソースの作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f job.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;job.batch/uzimihsr-echo-number created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Jobの一覧を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get &lt;span class="nb"&gt;jobs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME COMPLETIONS DURATION AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr-echo-number 1/1 5s 5s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podの一覧を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# JobによってPodが起動している&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr-echo-number-vpbg7 0/1 Completed &lt;span class="m"&gt;0&lt;/span&gt; 14s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podのログを確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# imageの元々の挙動ではなくJobで定義した処理が実行されている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl logs uzimihsr-echo-number-vpbg7
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;777&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podが作成された際のeventを確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get events
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;LAST SEEN TYPE REASON OBJECT MESSAGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;unknown&amp;gt; Normal Scheduled pod/uzimihsr-echo-number-vpbg7 Successfully assigned default/uzimihsr-echo-number-vpbg7 to minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3m Normal Pulled pod/uzimihsr-echo-number-vpbg7 Container image &lt;span class="s2"&gt;&amp;#34;uzimihsr/uzimihsr-sample-image:0.1&amp;#34;&lt;/span&gt; already present on machine
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3m Normal Created pod/uzimihsr-echo-number-vpbg7 Created container echo-number
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3m Normal Started pod/uzimihsr-echo-number-vpbg7 Started container echo-number
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3m1s Normal SuccessfulCreate job/uzimihsr-echo-number Created pod: uzimihsr-echo-number-vpbg7
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Jobの情報を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Job定義の他, Podのステータス監視情報などが表示される&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl describe job uzimihsr-echo-number
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: uzimihsr-echo-number
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Selector: controller-uid&lt;span class="o"&gt;=&lt;/span&gt;77d09e29-33f9-4175-a8e4-7b903ee44a9c
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: controller-uid&lt;span class="o"&gt;=&lt;/span&gt;77d09e29-33f9-4175-a8e4-7b903ee44a9c
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; job-name&lt;span class="o"&gt;=&lt;/span&gt;uzimihsr-echo-number
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: kubectl.kubernetes.io/last-applied-configuration&lt;span class="o"&gt;={&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;apiVersion&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;batch/v1&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;kind&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;Job&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;metadata&amp;#34;&lt;/span&gt;:&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;annotations&amp;#34;&lt;/span&gt;:&lt;span class="o"&gt;{}&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;uzimihsr-echo-number&amp;#34;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;namespace&amp;#34;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;#34;default&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;,&lt;span class="s2"&gt;&amp;#34;spec&amp;#34;&lt;/span&gt;:&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;backoffLimit&amp;#34;&lt;/span&gt;:1,&lt;span class="s2"&gt;&amp;#34;templ...&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Parallelism: &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Completions: &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Start Time: Sun, &lt;span class="m"&gt;15&lt;/span&gt; Dec &lt;span class="m"&gt;2019&lt;/span&gt; 20:29:29 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Pods Statuses: &lt;span class="m"&gt;0&lt;/span&gt; Running / &lt;span class="m"&gt;1&lt;/span&gt; Succeeded / &lt;span class="m"&gt;0&lt;/span&gt; Failed
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Pod Template:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Labels: controller-uid&lt;span class="o"&gt;=&lt;/span&gt;77d09e29-33f9-4175-a8e4-7b903ee44a9c
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; job-name&lt;span class="o"&gt;=&lt;/span&gt;uzimihsr-echo-number
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Containers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; echo-number:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image: uzimihsr/uzimihsr-sample-image:0.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Host Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Args:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -c
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NUMBER&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Environment: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Mounts: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Volumes: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Reason Age From Message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---- ------ ---- ---- -------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal SuccessfulCreate 3m job-controller Created pod: uzimihsr-echo-number-vpbg7
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podの情報を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl describe pod uzimihsr-echo-number-vpbg7
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: uzimihsr-echo-number-vpbg7
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Priority: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;PriorityClassName: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node: minikube/192.168.99.110
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Start Time: Sun, &lt;span class="m"&gt;15&lt;/span&gt; Dec &lt;span class="m"&gt;2019&lt;/span&gt; 20:29:29 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: controller-uid&lt;span class="o"&gt;=&lt;/span&gt;77d09e29-33f9-4175-a8e4-7b903ee44a9c
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; job-name&lt;span class="o"&gt;=&lt;/span&gt;uzimihsr-echo-number
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Status: Succeeded
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IP: 172.17.0.6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Controlled By: Job/uzimihsr-echo-number
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Containers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; echo-number:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Container ID: docker://d3cb3192f650cb916995ad25d533fb4f9edcd42a800cbf41bf2bbc0221ef204c
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image: uzimihsr/uzimihsr-sample-image:0.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image ID: docker-pullable://uzimihsr/uzimihsr-sample-image@sha256:eab7f925c7b33c5604196d30a9daa3e2d9c763166543069b8f31676a74003702
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Host Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Args:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -c
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NUMBER&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; State: Terminated
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Reason: Completed
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Exit Code: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Started: Sun, &lt;span class="m"&gt;15&lt;/span&gt; Dec &lt;span class="m"&gt;2019&lt;/span&gt; 20:29:30 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Finished: Sun, &lt;span class="m"&gt;15&lt;/span&gt; Dec &lt;span class="m"&gt;2019&lt;/span&gt; 20:29:30 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready: False
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Restart Count: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Environment: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Mounts:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; /var/run/secrets/kubernetes.io/serviceaccount from default-token-smq54 &lt;span class="o"&gt;(&lt;/span&gt;ro&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Conditions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Initialized True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready False
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ContainersReady False
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; PodScheduled True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Volumes:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; default-token-smq54:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type: Secret &lt;span class="o"&gt;(&lt;/span&gt;a volume populated by a Secret&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; SecretName: default-token-smq54
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Optional: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;QoS Class: BestEffort
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node-Selectors: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Tolerations: node.kubernetes.io/not-ready:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; node.kubernetes.io/unreachable:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Reason Age From Message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---- ------ ---- ---- -------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Scheduled &amp;lt;unknown&amp;gt; default-scheduler Successfully assigned default/uzimihsr-echo-number-vpbg7 to minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Pulled 10m kubelet, minikube Container image &lt;span class="s2"&gt;&amp;#34;uzimihsr/uzimihsr-sample-image:0.1&amp;#34;&lt;/span&gt; already present on machine
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Created 10m kubelet, minikube Created container echo-number
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Started 10m kubelet, minikube Started container echo-number
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;できた.&lt;br&gt;
&lt;code&gt;event&lt;/code&gt;の順番を見ると&lt;code&gt;Job&lt;/code&gt;が作成された際の各コンポーネントの動きが推測できておもしろい.&lt;br&gt;
多分以下の流れ.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;kubectl&lt;/code&gt;から指示を受けた&lt;code&gt;kube-apiserver&lt;/code&gt;が&lt;code&gt;Job&lt;/code&gt;の情報を&lt;code&gt;etcd&lt;/code&gt;に書き込み&lt;/li&gt;
&lt;li&gt;&lt;code&gt;kube-controller-manager&lt;/code&gt;に&lt;code&gt;Job&lt;/code&gt;の&lt;code&gt;Controller&lt;/code&gt;が作成される&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Job&lt;/code&gt;の&lt;code&gt;Controller&lt;/code&gt;が&lt;code&gt;kube-apiserver&lt;/code&gt;に指示を出して&lt;code&gt;Pod&lt;/code&gt;の情報を&lt;code&gt;etcd&lt;/code&gt;に書き込み&lt;/li&gt;
&lt;li&gt;&lt;code&gt;kube-scheduler&lt;/code&gt;によって&lt;code&gt;Pod&lt;/code&gt;が&lt;code&gt;Node&lt;/code&gt;に割り当てられる&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Node&lt;/code&gt;の&lt;code&gt;Docker&lt;/code&gt;が&lt;code&gt;Pod&lt;/code&gt;に使う&lt;code&gt;image&lt;/code&gt;を探してコンテナを作成+起動, これを&lt;code&gt;kubelet&lt;/code&gt;が報告&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Pod&lt;/code&gt;が作成されたことを&lt;code&gt;Job&lt;/code&gt;の&lt;code&gt;Controller&lt;/code&gt;が検知&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;Pod&lt;/code&gt;が完了したときにそれを示す&lt;code&gt;event&lt;/code&gt;が作成されないのはなんでだろう&amp;hellip;&lt;br&gt;
たぶん意図があるはずなのでそのうち調べたい.&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Kubernetes&lt;/code&gt;のマニフェストを初めて手書きして実行までやってみた.&lt;br&gt;
やっぱり先にコンポーネントの役割を理解しておいたほうがクラスタ全体の挙動がなんとなくわかって良い気がする.&lt;br&gt;
(間違ってたらかなしい)&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="ほっぺがかわいいそとちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-12-09-pod-args/2019-12-09-sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2019-12-09-pod-args/2019-12-09-sotochan_hu_1e33b72b77ea7961.jpg 800w, https://blog.uzimihsr.com/post/2019-12-09-pod-args/2019-12-09-sotochan_hu_eef40e2cdc7d3e11.jpg 1600w, https://blog.uzimihsr.com/post/2019-12-09-pod-args/2019-12-09-sotochan_hu_d315565edcad84ff.jpg 2400w, https://blog.uzimihsr.com/post/2019-12-09-pod-args/2019-12-09-sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>Kubernetesの主要なコンポーネントについてまとめる</title><link>https://blog.uzimihsr.com/post/2019-11-25-kubernetes-components/</link><pubDate>Mon, 25 Nov 2019 21:20:53 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2019-11-25-kubernetes-components/</guid><description>&lt;h2 id="もうちょっとくわしくなりたい"&gt;もうちょっとくわしくなりたい
&lt;/h2&gt;&lt;p&gt;これまでKubernetesクラスタについてちょっとずつ勉強してMasterガーnodeガーって自分なりに解釈してきたけど,&lt;br&gt;
そのMasterとNodeがどんなコンポーネントで構成されているか気になったのでまとめた.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="読んだもの"&gt;読んだもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://book.impress.co.jp/books/1118101055" target="_blank" rel="noopener"
 &gt;Kubernetes完全ガイド&lt;/a&gt; 19章 Kubernetesのアーキテクチャを知る&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://kubernetes.io/docs/concepts/overview/components/" target="_blank" rel="noopener"
 &gt;Kubernetes Components&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="コンポーネントの構成"&gt;コンポーネントの構成
&lt;/h2&gt;&lt;p&gt;Kubernetesクラスタを構成するコンポーネントの構成はこんな感じ.&lt;br&gt;
ほぼすべてのコンポーネントは&lt;code&gt;Master&lt;/code&gt;の&lt;code&gt;kube-apiserver&lt;/code&gt;とつながっている.&lt;/p&gt;
&lt;p&gt;&lt;img alt="構成図" class="gallery-image" data-flex-basis="375px" data-flex-grow="156" height="1197" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-11-25-kubernetes-components/2019-11-25-architecture.png" srcset="https://blog.uzimihsr.com/post/2019-11-25-kubernetes-components/2019-11-25-architecture_hu_73a66f181056e6c4.png 800w, https://blog.uzimihsr.com/post/2019-11-25-kubernetes-components/2019-11-25-architecture_hu_61d0f271e36880e0.png 1600w, https://blog.uzimihsr.com/post/2019-11-25-kubernetes-components/2019-11-25-architecture.png 1873w" width="1873"&gt;&lt;/p&gt;
&lt;div&gt;Icons made by &lt;a href="https://www.flaticon.com/authors/smashicons" title="Smashicons"&gt;Smashicons&lt;/a&gt; from &lt;a href="https://www.flaticon.com/" title="Flaticon"&gt;www.flaticon.com&lt;/a&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Masterコンポーネント
&lt;ul&gt;
&lt;li&gt;etcd&lt;/li&gt;
&lt;li&gt;kube-apiserver&lt;/li&gt;
&lt;li&gt;kube-scheduler&lt;/li&gt;
&lt;li&gt;kube-controller-manager&lt;/li&gt;
&lt;li&gt;cloud-controller-manager&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Nodeコンポーネント
&lt;ul&gt;
&lt;li&gt;kubelet&lt;/li&gt;
&lt;li&gt;kube-proxy&lt;/li&gt;
&lt;li&gt;コンテナランタイム(Docker)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;アドオン
&lt;ul&gt;
&lt;li&gt;DNS&lt;/li&gt;
&lt;li&gt;Web UI(ダッシュボード)&lt;/li&gt;
&lt;li&gt;コンテナリソース監視&lt;/li&gt;
&lt;li&gt;クラスターレベルログ&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="masterコンポーネント"&gt;Masterコンポーネント
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;クラスタの制御(スケジューリングなど)を行う&lt;/li&gt;
&lt;li&gt;クラスタイベントの検出/応答を行う&lt;/li&gt;
&lt;li&gt;クラスタ内のどのマシンでも実行可能だが, 基本的に同じマシンで実行する
&lt;ul&gt;
&lt;li&gt;シンプルさを保つため全てを1つにまとめる&lt;/li&gt;
&lt;li&gt;このマシンではユーザーのコンテナは実行しない&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="etcd"&gt;etcd
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;分散型KVS(Key-Value Store)
&lt;ul&gt;
&lt;li&gt;冗長化のためにetcdクラスタを組んで運用する&lt;/li&gt;
&lt;li&gt;分散合意アルゴリズム(Raft)を用いるため奇数台で運用する&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;クラスタの全ての情報を保存する場所&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="kube-apiserver"&gt;kube-apiserver
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;Kubernetes APIを提供するコンポーネント
&lt;ul&gt;
&lt;li&gt;kubectlではこれにリクエストを送ることでリソースの操作を行う&lt;/li&gt;
&lt;li&gt;kube-scheduler, kube-controller-manager, kubelet等はこれにリクエストを送ることで処理をしている&lt;/li&gt;
&lt;li&gt;受け取ったリクエストの情報はetcdに保存される&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ロードバランサの下に複数台並べて運用する&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="kube-scheduler"&gt;kube-scheduler
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;etcdに新たに登録されたリソース(Pod)をNodeに割り当てるコンポーネント
&lt;ul&gt;
&lt;li&gt;kube-apiserverにリクエストを送ってNodeが未定のPod情報を取得&lt;/li&gt;
&lt;li&gt;各Nodeのステータス等を考慮して割り当てをおこなう&lt;/li&gt;
&lt;li&gt;割り当てが決定したらkube-apiserverにリクエストを送ってPodをスケジューリングする&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;冗長化のため, 複数台で運用する&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="kube-controller-manager"&gt;kube-controller-manager
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;各種Controllerを実行するコンポーネント
&lt;ul&gt;
&lt;li&gt;各種リソースの状態を監視して必要な操作を決定&lt;/li&gt;
&lt;li&gt;操作が決定したらkube-apiserverにリクエストを送る&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;冗長化のため, 複数台で運用する&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="cloud-controller-manager"&gt;cloud-controller-manager
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;クラウドサービス固有の制御を担当するコンポーネント
&lt;ul&gt;
&lt;li&gt;クラウドプロバイダーと対話を行う&lt;/li&gt;
&lt;li&gt;クラウド固有の必要な操作を行うためのControllerを扱う
&lt;ul&gt;
&lt;li&gt;kube-controller-manegerとControllerがかぶらないようにする&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;クラウドサービスを利用しない場合は特に気にする必要なし&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="nodeコンポーネント"&gt;Nodeコンポーネント
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Nodeで稼働中のPodの管理を行う&lt;/li&gt;
&lt;li&gt;Kubernetesの実行環境を提供する&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="kubelet"&gt;kubelet
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;実際にコンテナの管理を行うコンポーネント
&lt;ul&gt;
&lt;li&gt;Podの動作を保証する&lt;/li&gt;
&lt;li&gt;Kubernetesが作成したコンテナのみを管理する&lt;/li&gt;
&lt;li&gt;kube-apiserverにリクエストを送って自身のNodeにスケジュールされたPodを確認, 起動する&lt;/li&gt;
&lt;li&gt;コンテナランタイムと連携する&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;各Node上で動作する&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="kube-proxy"&gt;kube-proxy
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;外部からのトラフィックを正常に転送するためのコンポーネント
&lt;ul&gt;
&lt;li&gt;Service宛のトラフィックをPodに転送する&lt;/li&gt;
&lt;li&gt;各Nodeで動作&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="コンテナランタイムdocker"&gt;コンテナランタイム(Docker)
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;コンテナの実行を担当するソフトウェア
&lt;ul&gt;
&lt;li&gt;ユーザーのコンテナはここで実行&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Docker以外のランタイムも利用可能
&lt;ul&gt;
&lt;li&gt;containerd, cri-o, rktletなど&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="アドオン"&gt;アドオン
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;クラスタの機能を実装する
&lt;ul&gt;
&lt;li&gt;Deployment, DaemonSetなどのリソースを使用&lt;/li&gt;
&lt;li&gt;kube-systemというnamespaceに置かれている&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;以下は代表的なアドオン&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="dnscoredns"&gt;DNS(CoreDNS)
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;ほぼ必須のアドオン&lt;/li&gt;
&lt;li&gt;クラスタ内のDNSを管理
&lt;ul&gt;
&lt;li&gt;PodとServiceの名前解決を行う&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="web-uiダッシュボード"&gt;Web UI(ダッシュボード)
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;グラフィカルな操作が可能なUI
&lt;ul&gt;
&lt;li&gt;リソース情報やログの閲覧が可能&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="コンテナリソース監視"&gt;コンテナリソース監視
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;コンテナのメトリクスをDBに保存&lt;/li&gt;
&lt;li&gt;メトリクスを可視化するためのUIを提供&lt;/li&gt;
&lt;li&gt;Prometheusなどが利用可能&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="クラスターレベルログ"&gt;クラスターレベルログ
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;コンテナのログを様々な方法で取得する
&lt;ul&gt;
&lt;li&gt;各Nodeでログを取得してバックエンドに送るためのロギングエージェントPodを実行する&lt;/li&gt;
&lt;li&gt;アプリコンテナのログを取得して標準出力するSidecarコンテナを各Podに追加する&lt;/li&gt;
&lt;li&gt;各コンテナのログを直接バックエンドに出力する&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;各種コンポーネントの役割についてなんとなくわかった気になった.&lt;br&gt;
Masterではkube-apiserverとetcdが, Nodeではkubeletが一番重要なんだと思う.&lt;br&gt;
アドオンに関してはDNSが重要なのはわかったけど他はあんまりわかんなかったので必要に応じて勉強したい.&lt;br&gt;
次は&lt;a class="link" href="https://book.impress.co.jp/books/1118101055" target="_blank" rel="noopener"
 &gt;Kubernetes完全ガイド&lt;/a&gt;の内容とかを少しずつまとめていきたい.&lt;/p&gt;</description></item><item><title>Google Kubernetes Engineはじめてみた</title><link>https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/</link><pubDate>Wed, 20 Nov 2019 22:39:39 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/</guid><description>&lt;h2 id="googleサイコー"&gt;Googleサイコー
&lt;/h2&gt;&lt;p&gt;Kubernetesを完全に理解したくて買った&lt;a class="link" href="https://book.impress.co.jp/books/1118101055" target="_blank" rel="noopener"
 &gt;Kubernetes完全ガイド&lt;/a&gt;をざっと読んだらGKE使ってるっぽかったので, 元々興味もあったし事前準備としてGKEを試してみた.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="やったことのまとめ"&gt;やったことのまとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://cloud.google.com/kubernetes-engine/" target="_blank" rel="noopener"
 &gt;Google Kubernetes Engine(GKE)&lt;/a&gt;の無料トライアルを始めた&lt;/li&gt;
&lt;li&gt;GKEで&lt;code&gt;Kubernetes&lt;/code&gt;クラスタを構築してアプリをデプロイ, 公開した後クラスタを削除した&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="gkeってなに"&gt;GKEってなに?
&lt;/h2&gt;&lt;p&gt;GCPが提供してる超便利なマネージド&lt;code&gt;Kubernetes&lt;/code&gt;サービス.&lt;br&gt;
すっげえ簡単にクラスタの構築, 管理ができるらしい.&lt;/p&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#gcp%e3%81%ae%e5%88%a9%e7%94%a8%e3%82%92%e9%96%8b%e5%a7%8b%e3%81%99%e3%82%8b" &gt;GCPの利用を開始する&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%83%97%e3%83%ad%e3%82%b8%e3%82%a7%e3%82%af%e3%83%88%e3%81%ae%e4%bd%9c%e6%88%90" &gt;プロジェクトの作成&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#google-cloud-sdk%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" &gt;Google Cloud SDKのインストール&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#kubernetes-engine%e3%82%af%e3%83%a9%e3%82%b9%e3%82%bf%e3%81%ae%e4%bd%9c%e6%88%90" &gt;Kubernetes Engineクラスタの作成&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%a2%e3%83%97%e3%83%aa%e3%81%ae%e3%83%87%e3%83%97%e3%83%ad%e3%82%a4" &gt;アプリのデプロイ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#kubernetes-engine%e3%82%af%e3%83%a9%e3%82%b9%e3%82%bf%e3%81%ae%e5%89%8a%e9%99%a4" &gt;Kubernetes Engineクラスタの削除&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="動作環境"&gt;動作環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;masOS Mojave 10.14&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="gcpの利用を開始する"&gt;GCPの利用を開始する
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://cloud.google.com/kubernetes-engine/" target="_blank" rel="noopener"
 &gt;https://cloud.google.com/kubernetes-engine/&lt;/a&gt; にアクセス.&lt;br&gt;
&lt;code&gt;無料トライアル&lt;/code&gt;を押す.&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="439px" data-flex-grow="182" height="1574" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc01.png" srcset="https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc01_hu_fcaf72bca5ea4090.png 800w, https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc01_hu_f975849294c382cf.png 1600w, https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc01_hu_84c3eeffbbb060d4.png 2400w, https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc01.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;利用規約の承諾とか住所とか支払い方法を入力して&lt;code&gt;無料トライアルを開始&lt;/code&gt;(スクショには映ってないけど&lt;code&gt;お支払い方法&lt;/code&gt;の下にある)を押す.&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="439px" data-flex-grow="182" height="1574" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc02.png" srcset="https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc02_hu_51ec44e95c5a3efc.png 800w, https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc02_hu_16c115dd36e9f719.png 1600w, https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc02_hu_84348e06663b3d0.png 2400w, https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc02.png 2880w" width="2880"&gt;&lt;br&gt;
&lt;img class="gallery-image" data-flex-basis="438px" data-flex-grow="182" height="1578" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc03.png" srcset="https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc03_hu_bb91dd0c2b595cc3.png 800w, https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc03_hu_d4729b86bb1229ab.png 1600w, https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc03_hu_2aa793d3000aee94.png 2400w, https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc03.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;GCPコンソールのGKEの画面に遷移して, Kubernetes Engine API(たぶんGKEのAPI)の有効化が始まる.&lt;br&gt;
ちょっと待つと準備が完了して, デフォルトで作成されたプロジェクト(&lt;strong&gt;My First Project&lt;/strong&gt;)で&lt;code&gt;Kubernetes&lt;/code&gt;クラスタが作れるようになる.&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="437px" data-flex-grow="182" height="1579" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc04.png" srcset="https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc04_hu_19117f8b8de2cdd4.png 800w, https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc04_hu_29c9825db7baf35.png 1600w, https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc04_hu_98ca031d6510dca.png 2400w, https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc04.png 2880w" width="2880"&gt;&lt;br&gt;
&lt;img class="gallery-image" data-flex-basis="439px" data-flex-grow="182" height="1574" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc05.png" srcset="https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc05_hu_3ebee6a9eefc957e.png 800w, https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc05_hu_3097ad7a7b9cd57f.png 1600w, https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc05_hu_9ce92d09ab74d7b.png 2400w, https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc05.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;このままこのプロジェクトでクラスタ構築して始められそうなんだけど,&lt;br&gt;
初心者なので今回は敢えて&lt;a class="link" href="https://cloud.google.com/kubernetes-engine/docs/quickstart" target="_blank" rel="noopener"
 &gt;クイックスタート&lt;/a&gt;の手順で新たにプロジェクトを作成してCLIからクラスタを構築してみる.&lt;/p&gt;
&lt;h3 id="プロジェクトの作成"&gt;プロジェクトの作成
&lt;/h3&gt;&lt;p&gt;再度&lt;a class="link" href="https://console.cloud.google.com/projectselector2/kubernetes" target="_blank" rel="noopener"
 &gt;GKEの画面&lt;/a&gt;を開く.&lt;br&gt;
ヘッダーから&lt;code&gt;プロジェクトの選択-&amp;gt;新しいプロジェクト&lt;/code&gt;と進む.&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="438px" data-flex-grow="182" height="1575" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc06.png" srcset="https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc06_hu_848f8045d70f750f.png 800w, https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc06_hu_61f6b08f6d4b5ef.png 1600w, https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc06_hu_f2f2e3ca356e371f.png 2400w, https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc06.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;プロジェクト作成画面が開くので, プロジェクト名(&lt;strong&gt;uzimihsr-01&lt;/strong&gt;)だけ入力して&lt;code&gt;作成&lt;/code&gt;を押す.&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="439px" data-flex-grow="182" height="1574" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc07.png" srcset="https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc07_hu_3a22609ce0829ada.png 800w, https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc07_hu_f20bd55b0d8c5edf.png 1600w, https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc07_hu_7080d0a2d39e335.png 2400w, https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc07.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;またまたGKEの画面に遷移して先程と同様にKubernetes Engine APIの有効化が始まり, 少し待つと有効になる.&lt;br&gt;
無料トライアルの開始時とやってることは一緒.&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="438px" data-flex-grow="182" height="1575" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc08.png" srcset="https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc08_hu_2f0c714fb6ebe117.png 800w, https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc08_hu_49cf77b62be6d4b.png 1600w, https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc08_hu_198594a2951578b6.png 2400w, https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc08.png 2880w" width="2880"&gt;&lt;br&gt;
&lt;img class="gallery-image" data-flex-basis="439px" data-flex-grow="182" height="1574" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc09.png" srcset="https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc09_hu_3a296fb521341699.png 800w, https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc09_hu_f93074c3bb24d8b0.png 1600w, https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc09_hu_595637cebe4e0c88.png 2400w, https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc09.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;h3 id="google-cloud-sdkのインストール"&gt;Google Cloud SDKのインストール
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://cloud.google.com/sdk/docs/quickstart-macos" target="_blank" rel="noopener"
 &gt;macOS 用のクイックスタート&lt;/a&gt;に従ってGoogle Cloud SDKとgcloudをインストールする.&lt;/p&gt;
&lt;p&gt;まずはシステムに&lt;code&gt;Python 2.7&lt;/code&gt;がインストールされていることを確認.&lt;br&gt;
自分は普段システム(&lt;strong&gt;/usr/bin/python&lt;/strong&gt;)じゃなくて&lt;code&gt;Homebrew&lt;/code&gt;で入れた&lt;code&gt;Python 2.7&lt;/code&gt;を使っているけど,&lt;br&gt;
とにかくバージョン2.7の&lt;code&gt;Python&lt;/code&gt;にパスが通ってればいいみたい.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# pythonのバージョン確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ which python
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/usr/local/bin/python
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ python -V
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Python 2.7.16
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;macOS 64bit用の&lt;a class="link" href="https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-245.0.0-darwin-x86_64.tar.gz" target="_blank" rel="noopener"
 &gt;google-cloud-sdk-245.0.0-darwin-x86_64.tar.gz&lt;/a&gt;をダウンロード.&lt;br&gt;
ホームディレクトリに移動して展開しておく.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ホームディレクトリにgoogle-cloud-sdkが配置されていることを確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;pwd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/Users/&amp;lt;ユーザ名&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;google-cloud-sdk
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;インストールスクリプト&lt;code&gt;install.sh&lt;/code&gt;を実行して&lt;code&gt;gcloud&lt;/code&gt;コマンドをインストールする.&lt;br&gt;
途中でデータ収集に協力するか, とかCLIの&lt;code&gt;PATH&lt;/code&gt;を通すかとか聞かれるので前者はNo, 後者はYesと答える.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# インストールスクリプトの実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ./google-cloud-sdk/install.sh
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Welcome to the Google Cloud SDK!
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;To &lt;span class="nb"&gt;help&lt;/span&gt; improve the quality of this product, we collect anonymized usage data
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;and anonymized stacktraces when crashes are encountered&lt;span class="p"&gt;;&lt;/span&gt; additional information
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;is available at &amp;lt;https://cloud.google.com/sdk/usage-statistics&amp;gt;. You may choose
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;to opt out of this collection now &lt;span class="o"&gt;(&lt;/span&gt;by choosing &lt;span class="s1"&gt;&amp;#39;N&amp;#39;&lt;/span&gt; at the below prompt&lt;span class="o"&gt;)&lt;/span&gt;, or at
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;any &lt;span class="nb"&gt;time&lt;/span&gt; in the future by running the following command:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; gcloud config &lt;span class="nb"&gt;set&lt;/span&gt; disable_usage_reporting &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Do you want to &lt;span class="nb"&gt;help&lt;/span&gt; improve the Google Cloud SDK &lt;span class="o"&gt;(&lt;/span&gt;Y/n&lt;span class="o"&gt;)&lt;/span&gt;? n
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Your current Cloud SDK version is: 245.0.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;The latest available version is: 272.0.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ Components │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├──────────────────┬──────────────────────────────────────────────────────┬──────────────────────────┬──────────┤
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ Status │ Name │ ID │ Size │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├──────────────────┼──────────────────────────────────────────────────────┼──────────────────────────┼──────────┤
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ Update Available │ BigQuery Command Line Tool │ bq │ &amp;lt; &lt;span class="m"&gt;1&lt;/span&gt; MiB │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ Update Available │ Cloud SDK Core Libraries │ core │ 12.5 MiB │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ Update Available │ Cloud Storage Command Line Tool │ gsutil │ 3.6 MiB │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ Not Installed │ App Engine Go Extensions │ app-engine-go │ 4.8 MiB │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ Not Installed │ Appctl │ appctl │ 18.6 MiB │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ Not Installed │ Cloud Bigtable Command Line Tool │ cbt │ 7.3 MiB │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ Not Installed │ Cloud Bigtable Emulator │ bigtable │ 6.6 MiB │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ Not Installed │ Cloud Datalab Command Line Tool │ datalab │ &amp;lt; &lt;span class="m"&gt;1&lt;/span&gt; MiB │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ Not Installed │ Cloud Datastore Emulator │ cloud-datastore-emulator │ 18.4 MiB │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ Not Installed │ Cloud Firestore Emulator │ cloud-firestore-emulator │ 40.0 MiB │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ Not Installed │ Cloud Pub/Sub Emulator │ pubsub-emulator │ 34.9 MiB │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ Not Installed │ Cloud SQL Proxy │ cloud_sql_proxy │ 3.7 MiB │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ Not Installed │ Emulator Reverse Proxy │ emulator-reverse-proxy │ 14.5 MiB │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ Not Installed │ Google Cloud Build Local Builder │ cloud-build-local │ 5.9 MiB │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ Not Installed │ Google Container Registry s Docker credential helper │ docker-credential-gcr │ 1.8 MiB │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ Not Installed │ Skaffold │ skaffold │ 44.0 MiB │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ Not Installed │ gcloud Alpha Commands │ alpha │ &amp;lt; &lt;span class="m"&gt;1&lt;/span&gt; MiB │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ Not Installed │ gcloud Beta Commands │ beta │ &amp;lt; &lt;span class="m"&gt;1&lt;/span&gt; MiB │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ Not Installed │ gcloud app Java Extensions │ app-engine-java │ 62.0 MiB │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ Not Installed │ gcloud app PHP Extensions │ app-engine-php │ 21.9 MiB │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ Not Installed │ gcloud app Python Extensions │ app-engine-python │ 6.0 MiB │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ Not Installed │ gcloud app Python Extensions &lt;span class="o"&gt;(&lt;/span&gt;Extra Libraries&lt;span class="o"&gt;)&lt;/span&gt; │ app-engine-python-extras │ 27.1 MiB │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ Not Installed │ kubectl │ kubectl │ &amp;lt; &lt;span class="m"&gt;1&lt;/span&gt; MiB │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└──────────────────┴──────────────────────────────────────────────────────┴──────────────────────────┴──────────┘
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;To install or remove components at your current SDK version &lt;span class="o"&gt;[&lt;/span&gt;245.0.0&lt;span class="o"&gt;]&lt;/span&gt;, run:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; $ gcloud components install COMPONENT_ID
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; $ gcloud components remove COMPONENT_ID
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;To update your SDK installation to the latest version &lt;span class="o"&gt;[&lt;/span&gt;272.0.0&lt;span class="o"&gt;]&lt;/span&gt;, run:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; $ gcloud components update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;To take a quick anonymous survey, run:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; $ gcloud alpha survey
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Modify profile to update your &lt;span class="nv"&gt;$PATH&lt;/span&gt; and &lt;span class="nb"&gt;enable&lt;/span&gt; shell &lt;span class="nb"&gt;command&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;completion?
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Do you want to &lt;span class="k"&gt;continue&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;Y/n&lt;span class="o"&gt;)&lt;/span&gt;? y
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;The Google Cloud SDK installer will now prompt you to update an rc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;file to bring the Google Cloud CLIs into your environment.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Enter a path to an rc file to update, or leave blank to use
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;/Users/&amp;lt;ユーザ名&amp;gt;/.zshrc&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Backing up &lt;span class="o"&gt;[&lt;/span&gt;/Users/&amp;lt;ユーザ名&amp;gt;/.zshrc&lt;span class="o"&gt;]&lt;/span&gt; to &lt;span class="o"&gt;[&lt;/span&gt;/Users/&amp;lt;ユーザ名&amp;gt;/.zshrc.backup&lt;span class="o"&gt;]&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;/Users/&amp;lt;ユーザ名&amp;gt;/.zshrc&lt;span class="o"&gt;]&lt;/span&gt; has been updated.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;==&lt;/span&gt;&amp;gt; Start a new shell &lt;span class="k"&gt;for&lt;/span&gt; the changes to take effect.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;For more information on how to get started, please visit:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; https://cloud.google.com/sdk/docs/quickstarts
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# シェルを再起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nv"&gt;$SHELL&lt;/span&gt; -l
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# gcloudコマンドが使えるか確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ gcloud --version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Google Cloud SDK 245.0.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bq 2.0.43
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;core 2019.05.03
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gsutil 4.38
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl 2019.05.03
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Updates are available &lt;span class="k"&gt;for&lt;/span&gt; some Cloud SDK components. To install them,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;please run:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; $ gcloud components update
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで&lt;code&gt;gcloud&lt;/code&gt;コマンドが使えるようになった.&lt;/p&gt;
&lt;p&gt;次にSDKの初期化を行う.&lt;br&gt;
ログインするか聞かれるのでYesと答えるとブラウザが開かれる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# SDKの初期化&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ gcloud init
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Welcome! This &lt;span class="nb"&gt;command&lt;/span&gt; will take you through the configuration of gcloud.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Your current configuration has been &lt;span class="nb"&gt;set&lt;/span&gt; to: &lt;span class="o"&gt;[&lt;/span&gt;default&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;You can skip diagnostics next &lt;span class="nb"&gt;time&lt;/span&gt; by using the following flag:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; gcloud init --skip-diagnostics
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Network diagnostic detects and fixes &lt;span class="nb"&gt;local&lt;/span&gt; network connection issues.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Checking network connection...done.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Reachability Check passed.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Network diagnostic passed &lt;span class="o"&gt;(&lt;/span&gt;1/1 checks passed&lt;span class="o"&gt;)&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;You must log in to &lt;span class="k"&gt;continue&lt;/span&gt;. Would you like to log in &lt;span class="o"&gt;(&lt;/span&gt;Y/n&lt;span class="o"&gt;)&lt;/span&gt;? y
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Your browser has been opened to visit:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; https://accounts.google.com/o/oauth2/auth?redirect_uri&lt;span class="o"&gt;=&lt;/span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 勝手にブラウザが開く&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Googleのログイン画面が表示されるので, 内容を読んで権限を許可する.&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="438px" data-flex-grow="182" height="1576" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc10.png" srcset="https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc10_hu_3877d9f1ffaaa045.png 800w, https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc10_hu_a76585e742fe55e5.png 1600w, https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc10_hu_a308c608d7c393cb.png 2400w, https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc10.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;認証に成功すると画面遷移するので, ブラウザを閉じてターミナルに戻る.&lt;br&gt;
&lt;img class="gallery-image" data-flex-basis="439px" data-flex-grow="182" height="1574" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc11.png" srcset="https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc11_hu_ca4a4aa6946e3eae.png 800w, https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc11_hu_e1234ad530b58ae3.png 1600w, https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc11_hu_2fea152e2e168336.png 2400w, https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc11.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;すると先程のダイアログの続きが表示されているので指示に従ってすすめる.&lt;br&gt;
途中でどのプロジェクトを使うか聞かれるので, 先程作成したプロジェクト(&lt;strong&gt;uzimihsr-01&lt;/strong&gt;)の番号を選択する.&lt;br&gt;
&lt;code&gt;Region&lt;/code&gt;と&lt;code&gt;Zone&lt;/code&gt;の設定は後でもできるので今はNoにしておく.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# さっきのダイアログにつづきが表示されている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ gcloud init
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Welcome! This &lt;span class="nb"&gt;command&lt;/span&gt; will take you through the configuration of gcloud.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Your current configuration has been &lt;span class="nb"&gt;set&lt;/span&gt; to: &lt;span class="o"&gt;[&lt;/span&gt;default&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;You can skip diagnostics next &lt;span class="nb"&gt;time&lt;/span&gt; by using the following flag:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; gcloud init --skip-diagnostics
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Network diagnostic detects and fixes &lt;span class="nb"&gt;local&lt;/span&gt; network connection issues.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Checking network connection...done.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Reachability Check passed.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Network diagnostic passed &lt;span class="o"&gt;(&lt;/span&gt;1/1 checks passed&lt;span class="o"&gt;)&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;You must log in to &lt;span class="k"&gt;continue&lt;/span&gt;. Would you like to log in &lt;span class="o"&gt;(&lt;/span&gt;Y/n&lt;span class="o"&gt;)&lt;/span&gt;? y
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Your browser has been opened to visit:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; https://accounts.google.com/o/oauth2/auth?redirect_uri&lt;span class="o"&gt;=&lt;/span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Updates are available &lt;span class="k"&gt;for&lt;/span&gt; some Cloud SDK components. To install them,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;please run:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; $ gcloud components update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;You are logged in as: &lt;span class="o"&gt;[&lt;/span&gt;xxxxxxxx@gmail.com&lt;span class="o"&gt;]&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Pick cloud project to use:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;1&lt;span class="o"&gt;]&lt;/span&gt; nifty-catfish-259613
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;2&lt;span class="o"&gt;]&lt;/span&gt; uzimihsr-01
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;3&lt;span class="o"&gt;]&lt;/span&gt; Create a new project
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Please enter numeric choice or text value &lt;span class="o"&gt;(&lt;/span&gt;must exactly match list
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;item&lt;span class="o"&gt;)&lt;/span&gt;: &lt;span class="m"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Your current project has been &lt;span class="nb"&gt;set&lt;/span&gt; to: &lt;span class="o"&gt;[&lt;/span&gt;uzimihsr-01&lt;span class="o"&gt;]&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Do you want to configure a default Compute Region and Zone? &lt;span class="o"&gt;(&lt;/span&gt;Y/n&lt;span class="o"&gt;)&lt;/span&gt;? n
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Created a default .boto configuration file at &lt;span class="o"&gt;[&lt;/span&gt;/Users/&amp;lt;ユーザー名&amp;gt;/.boto&lt;span class="o"&gt;]&lt;/span&gt;. See this file and
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;https://cloud.google.com/storage/docs/gsutil/commands/config&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; more
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;information about configuring Google Cloud Storage.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Your Google Cloud SDK is configured and ready to use!
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* Commands that require authentication will use xxxxxxxx@gmail.com by default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* Commands will reference project &lt;span class="sb"&gt;`&lt;/span&gt;uzimihsr-01&lt;span class="sb"&gt;`&lt;/span&gt; by default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Run &lt;span class="sb"&gt;`&lt;/span&gt;gcloud &lt;span class="nb"&gt;help&lt;/span&gt; config&lt;span class="sb"&gt;`&lt;/span&gt; to learn how to change individual settings
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;This gcloud configuration is called &lt;span class="o"&gt;[&lt;/span&gt;default&lt;span class="o"&gt;]&lt;/span&gt;. You can create additional configurations &lt;span class="k"&gt;if&lt;/span&gt; you work with multiple accounts and/or projects.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Run &lt;span class="sb"&gt;`&lt;/span&gt;gcloud topic configurations&lt;span class="sb"&gt;`&lt;/span&gt; to learn more.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Some things to try next:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* Run &lt;span class="sb"&gt;`&lt;/span&gt;gcloud --help&lt;span class="sb"&gt;`&lt;/span&gt; to see the Cloud Platform services you can interact with. And run &lt;span class="sb"&gt;`&lt;/span&gt;gcloud &lt;span class="nb"&gt;help&lt;/span&gt; COMMAND&lt;span class="sb"&gt;`&lt;/span&gt; to get &lt;span class="nb"&gt;help&lt;/span&gt; on any gcloud command.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* Run &lt;span class="sb"&gt;`&lt;/span&gt;gcloud topic --help&lt;span class="sb"&gt;`&lt;/span&gt; to learn about advanced features of the SDK like arg files and output formatting
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これでSDKの初期化は完了.&lt;/p&gt;
&lt;p&gt;次に&lt;code&gt;kubectl&lt;/code&gt;をインストールする.&lt;br&gt;
&lt;code&gt;Docker Desktop&lt;/code&gt;とか&lt;code&gt;Minikube&lt;/code&gt;を使ったときに&lt;code&gt;Homebrew&lt;/code&gt;で入れてあるはずだけど, 一応再インストールしてみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# kubectlのインストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ gcloud components install kubectl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Your current Cloud SDK version is: 245.0.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Installing components from version: 245.0.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;┌─────────────────────────────────────────────────────────────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ These components will be installed. │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├─────────────────────┬────────────────────────┬──────────────────────┤
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ Name │ Version │ Size │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├─────────────────────┼────────────────────────┼──────────────────────┤
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ kubectl │ 2019.05.03 │ &amp;lt; &lt;span class="m"&gt;1&lt;/span&gt; MiB │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ kubectl │ 1.11.9 │ 65.3 MiB │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└─────────────────────┴────────────────────────┴──────────────────────┘
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;For the latest full release notes, please visit:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; https://cloud.google.com/sdk/release_notes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Do you want to &lt;span class="k"&gt;continue&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;Y/n&lt;span class="o"&gt;)&lt;/span&gt;? y
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;╔════════════════════════════════════════════════════════════╗
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;╠═ Creating update staging area ═╣
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;╠════════════════════════════════════════════════════════════╣
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;╠═ Installing: kubectl ═╣
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;╠════════════════════════════════════════════════════════════╣
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;╠═ Installing: kubectl ═╣
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;╠════════════════════════════════════════════════════════════╣
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;╠═ Creating backup and activating new installation ═╣
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;╚════════════════════════════════════════════════════════════╝
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Performing post processing steps...done.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Update &lt;span class="k"&gt;done&lt;/span&gt;!
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;WARNING: There are older versions of Google Cloud Platform tools on your system PATH.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Please remove the following to avoid accidentally invoking these old tools:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; /usr/local/Cellar/kubernetes-cli/1.16.2/bin/kubectl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 元々入ってたkubectl(/usr/local/bin/kubectl)は念の為削除する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ which kubectl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/usr/local/bin/kubectl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ rm /usr/local/Cellar/kubernetes-cli/1.16.2/bin/kubectl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;remove /usr/local/Cellar/kubernetes-cli/1.16.2/bin/kubectl? y
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nv"&gt;$SHELL&lt;/span&gt; -l
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ which kubectl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/Users/username/google-cloud-sdk/bin/kubectl
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これでSDKのインストールは完了.&lt;/p&gt;
&lt;h3 id="kubernetes-engineクラスタの作成"&gt;Kubernetes Engineクラスタの作成
&lt;/h3&gt;&lt;p&gt;次に&lt;code&gt;gcloud&lt;/code&gt;で使用するデフォルトのプロジェクト, &lt;code&gt;Zone&lt;/code&gt;の設定をする.&lt;br&gt;
先程&lt;code&gt;gcloud init&lt;/code&gt;したときとほとんど同じことをやっている.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# デフォルトプロジェクトをuzimihsr-01に設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ gcloud config &lt;span class="nb"&gt;set&lt;/span&gt; project uzimihsr-01
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Updated property &lt;span class="o"&gt;[&lt;/span&gt;core/project&lt;span class="o"&gt;]&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# コンピューティングゾーンをus-west1-aに設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ gcloud config &lt;span class="nb"&gt;set&lt;/span&gt; compute/zone us-west1-a
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Updated property &lt;span class="o"&gt;[&lt;/span&gt;compute/zone&lt;span class="o"&gt;]&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;いよいよ&lt;code&gt;Kubernetes&lt;/code&gt;クラスタを作成する.&lt;br&gt;
作成自体はコマンド1行でできる. すごい.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# k8s-uzimihsrという名前でクラスタを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ gcloud container clusters create k8s-uzimihsr
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;WARNING: In June 2019, node auto-upgrade will be enabled by default &lt;span class="k"&gt;for&lt;/span&gt; newly created clusters and node pools. To disable it, use the &lt;span class="sb"&gt;`&lt;/span&gt;--no-enable-autoupgrade&lt;span class="sb"&gt;`&lt;/span&gt; flag.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;WARNING: Starting in 1.12, new clusters will have basic authentication disabled by default. Basic authentication can be enabled &lt;span class="o"&gt;(&lt;/span&gt;or disabled&lt;span class="o"&gt;)&lt;/span&gt; manually using the &lt;span class="sb"&gt;`&lt;/span&gt;--&lt;span class="o"&gt;[&lt;/span&gt;no-&lt;span class="o"&gt;]&lt;/span&gt;enable-basic-auth&lt;span class="sb"&gt;`&lt;/span&gt; flag.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;WARNING: Starting in 1.12, new clusters will not have a client certificate issued. You can manually &lt;span class="nb"&gt;enable&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;or disable&lt;span class="o"&gt;)&lt;/span&gt; the issuance of the client certificate using the &lt;span class="sb"&gt;`&lt;/span&gt;--&lt;span class="o"&gt;[&lt;/span&gt;no-&lt;span class="o"&gt;]&lt;/span&gt;issue-client-certificate&lt;span class="sb"&gt;`&lt;/span&gt; flag.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;WARNING: Currently VPC-native is not the default mode during cluster creation. In the future, this will become the default mode and can be disabled using &lt;span class="sb"&gt;`&lt;/span&gt;--no-enable-ip-alias&lt;span class="sb"&gt;`&lt;/span&gt; flag. Use &lt;span class="sb"&gt;`&lt;/span&gt;--&lt;span class="o"&gt;[&lt;/span&gt;no-&lt;span class="o"&gt;]&lt;/span&gt;enable-ip-alias&lt;span class="sb"&gt;`&lt;/span&gt; flag to suppress this warning.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;WARNING: Starting in 1.12, default node pools in new clusters will have their legacy Compute Engine instance metadata endpoints disabled by default. To create a cluster with legacy instance metadata endpoints disabled in the default node pool, run &lt;span class="sb"&gt;`&lt;/span&gt;clusters create&lt;span class="sb"&gt;`&lt;/span&gt; with the flag &lt;span class="sb"&gt;`&lt;/span&gt;--metadata disable-legacy-endpoints&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;WARNING: Your Pod address range &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;--cluster-ipv4-cidr&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; can accommodate at most &lt;span class="m"&gt;1008&lt;/span&gt; node&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;This will &lt;span class="nb"&gt;enable&lt;/span&gt; the autorepair feature &lt;span class="k"&gt;for&lt;/span&gt; nodes. Please see https://cloud.google.com/kubernetes-engine/docs/node-auto-repair &lt;span class="k"&gt;for&lt;/span&gt; more information on node autorepairs.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Creating cluster k8s-uzimihsr in us-west1-a... Cluster is being health-checked &lt;span class="o"&gt;(&lt;/span&gt;master is healthy&lt;span class="o"&gt;)&lt;/span&gt;...done.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Created &lt;span class="o"&gt;[&lt;/span&gt;https://container.googleapis.com/v1/projects/uzimihsr-01/zones/us-west1-a/clusters/k8s-uzimihsr&lt;span class="o"&gt;]&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;To inspect the contents of your cluster, go to: https://console.cloud.google.com/kubernetes/workload_/gcloud/us-west1-a/k8s-uzimihsr?project&lt;span class="o"&gt;=&lt;/span&gt;uzimihsr-01
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubeconfig entry generated &lt;span class="k"&gt;for&lt;/span&gt; k8s-uzimihsr.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;k8s-uzimihsr us-west1-a 1.13.11-gke.14 104.196.227.231 n1-standard-1 1.13.11-gke.14 &lt;span class="m"&gt;3&lt;/span&gt; RUNNING
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;クラスタができたので, CLIからこのクラスタと接続するための認証情報を取得する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# クラスタ(k8s-uzimihsr)の認証情報を取得する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ gcloud container clusters get-credentials k8s-uzimihsr
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Fetching cluster endpoint and auth data.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubeconfig entry generated &lt;span class="k"&gt;for&lt;/span&gt; k8s-uzimihsr.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これでこのクラスタを使う準備が完了.&lt;/p&gt;
&lt;h3 id="アプリのデプロイ"&gt;アプリのデプロイ
&lt;/h3&gt;&lt;p&gt;作成したクラスタに実際にアプリをデプロイして公開してみる.&lt;br&gt;
今回は簡単なwebサーバアプリの&lt;code&gt;image&lt;/code&gt;を持つ&lt;code&gt;Pod&lt;/code&gt;を&lt;code&gt;Deployment&lt;/code&gt;で作成し, &lt;code&gt;Service&lt;/code&gt;を設定してそれを公開する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# hello-serverという名前のDeploymentを作成する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl run hello-server --image gcr.io/google-samples/hello-app:1.0 --port &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl run --generator&lt;span class="o"&gt;=&lt;/span&gt;deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator&lt;span class="o"&gt;=&lt;/span&gt;run-pod/v1 or kubectl create instead.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps/hello-server created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# hello-serverのServiceを作成する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl expose deployment hello-server --type &lt;span class="s2"&gt;&amp;#34;LoadBalancer&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/hello-server exposed
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 公開されているIP(EXTERNAL-IP)を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get service hello-server
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hello-server LoadBalancer 10.27.253.151 34.82.48.96 8080:30758/TCP 71s
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;実際に公開されているIP( http://34.82.48.96:8080 )を叩くとちゃんとアプリが公開されていることがわかる. うれしい.&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="992px" data-flex-grow="413" height="224" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc12.png" srcset="https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc12_hu_88b7ecf33ec74c29.png 800w, https://blog.uzimihsr.com/post/2019-11-20-google-kubernetes-engine/2019-11-20-sc12.png 926w" width="926"&gt;&lt;/p&gt;
&lt;p&gt;ちなみに今回のアプリに使用している&lt;code&gt;image&lt;/code&gt;は&lt;code&gt;Go&lt;/code&gt;で書かれていて, 以下で公開されている.&lt;br&gt;
&lt;a class="link" href="https://github.com/GoogleCloudPlatform/kubernetes-engine-samples/blob/master/hello-app/main.go" target="_blank" rel="noopener"
 &gt;main.go&lt;/a&gt;&lt;br&gt;
&lt;a class="link" href="https://github.com/GoogleCloudPlatform/kubernetes-engine-samples/blob/master/hello-app/Dockerfile" target="_blank" rel="noopener"
 &gt;Dockerfile&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="kubernetes-engineクラスタの削除"&gt;Kubernetes Engineクラスタの削除
&lt;/h3&gt;&lt;p&gt;このままアプリを公開し続けるとGCPの課金が発生するらしい.&lt;br&gt;
無料トライアル中なので多分関係ないが, 勉強のためにクラスタの削除までやってみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Service(hello-server)を削除&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl delete service hello-server
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service &lt;span class="s2"&gt;&amp;#34;hello-server&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# クラスタの削除&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ちょっと時間がかかる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ gcloud container clusters delete k8s-uzimihsr
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;The following clusters will be deleted.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - &lt;span class="o"&gt;[&lt;/span&gt;k8s-uzimihsr&lt;span class="o"&gt;]&lt;/span&gt; in &lt;span class="o"&gt;[&lt;/span&gt;us-west1-a&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Do you want to &lt;span class="k"&gt;continue&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;Y/n&lt;span class="o"&gt;)&lt;/span&gt;? y
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Deleting cluster k8s-uzimihsr...done.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Deleted &lt;span class="o"&gt;[&lt;/span&gt;https://container.googleapis.com/v1/projects/uzimihsr-01/zones/us-west1-a/clusters/k8s-uzimihsr&lt;span class="o"&gt;]&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これでクラスタが削除できた.&lt;br&gt;
よくわかってないけど&lt;code&gt;Service&lt;/code&gt;だけ消してるのはそこに課金が発生するからみたい.&lt;br&gt;
(アプリを外部公開している時間に対して課金が発生する?)&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;CLIから簡単に外部公開用のクラスタが構築できてすげー便利だと思った.&lt;br&gt;
アプリを開発できる人間が星の数ほどいる現在,&lt;br&gt;
アプリの開発や公開に便利な環境を提供するサービスはドンドン売れるってはっきりわかんだね. Googleすごい.&lt;br&gt;
&amp;ldquo;ゴールドラッシュのときに一番儲かったのは金を掘るための道具を売ってた人たち&amp;quot;的な話を思い出した.&lt;/p&gt;
&lt;p&gt;次は&lt;a class="link" href="https://book.impress.co.jp/books/1118101055" target="_blank" rel="noopener"
 &gt;Kubernetes完全ガイド&lt;/a&gt;を読んだ内容をまとめていきたい.&lt;/p&gt;</description></item><item><title>Kubernetesの基本を学ぶ</title><link>https://blog.uzimihsr.com/post/2019-10-29-kubernetes-basics/</link><pubDate>Thu, 14 Nov 2019 22:57:42 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2019-10-29-kubernetes-basics/</guid><description>&lt;h2 id="基本が大事"&gt;基本が大事
&lt;/h2&gt;&lt;p&gt;Hello Minikubeしたので, チュートリアルの続きを読んでみた.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="読んだもの"&gt;読んだもの
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://kubernetes.io/ja/docs/tutorials/kubernetes-basics/" target="_blank" rel="noopener"
 &gt;Kubernetesの基本を学ぶ&lt;/a&gt;&lt;br&gt;
元記事 : &lt;a class="link" href="https://kubernetes.io/docs/tutorials/kubernetes-basics/" target="_blank" rel="noopener"
 &gt;Learn Kubernetes Basics&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;日本語訳がしっかり用意されているので, 読んだ内容を自分の言葉でまとめる.&lt;/p&gt;
&lt;h2 id="動作環境"&gt;動作環境
&lt;/h2&gt;&lt;p&gt;途中のチュートリアルは以下の環境を使用して行った.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;masOS Mojave 10.14&lt;/li&gt;
&lt;li&gt;Minikube v1.5.0&lt;/li&gt;
&lt;li&gt;VirtualBox 6.0.12&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="もくじ"&gt;もくじ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#kubernetes%e3%81%ae%e5%9f%ba%e6%9c%ac%e3%82%92%e5%ad%a6%e3%81%b6" &gt;Kubernetesの基本を学ぶ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%af%e3%83%a9%e3%82%b9%e3%82%bf%e3%81%ae%e4%bd%9c%e6%88%90" &gt;クラスタの作成&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%a2%e3%83%97%e3%83%aa%e3%82%b1%e3%83%bc%e3%82%b7%e3%83%a7%e3%83%b3%e3%81%ae%e3%83%87%e3%83%97%e3%83%ad%e3%82%a4" &gt;アプリケーションのデプロイ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%a2%e3%83%97%e3%83%aa%e3%82%b1%e3%83%bc%e3%82%b7%e3%83%a7%e3%83%b3%e3%81%ae%e6%8e%a2%e7%b4%a2" &gt;アプリケーションの探索&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%a2%e3%83%97%e3%83%aa%e3%82%b1%e3%83%bc%e3%82%b7%e3%83%a7%e3%83%b3%e3%81%ae%e5%85%ac%e9%96%8b" &gt;アプリケーションの公開&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%a2%e3%83%97%e3%83%aa%e3%82%b1%e3%83%bc%e3%82%b7%e3%83%a7%e3%83%b3%e3%81%ae%e3%82%b9%e3%82%b1%e3%83%bc%e3%83%aa%e3%83%b3%e3%82%b0" &gt;アプリケーションのスケーリング&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%a2%e3%83%97%e3%83%aa%e3%82%b1%e3%83%bc%e3%82%b7%e3%83%a7%e3%83%b3%e3%81%ae%e3%82%a2%e3%83%83%e3%83%97%e3%83%87%e3%83%bc%e3%83%88" &gt;アプリケーションのアップデート&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="kubernetesの基本を学ぶ"&gt;Kubernetesの基本を学ぶ
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;Kubernetes&lt;/code&gt;はどんなことができるの?&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;コンテナアプリを簡単に実行できるようにしてくれる.&lt;/li&gt;
&lt;li&gt;そのために必要なリソース, ツールを提供してくれる.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="クラスタの作成"&gt;クラスタの作成
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;Kubernetes&lt;/code&gt;クラスタとは&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;クラスタを管理する&lt;code&gt;Master&lt;/code&gt;とコンテナアプリを動かす&lt;code&gt;Node&lt;/code&gt;で構成される.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Master&lt;/code&gt;はクラスタ内の全ての操作を行う.
&lt;ul&gt;
&lt;li&gt;コンテナが&lt;code&gt;Node&lt;/code&gt;で実行されるためのスケジューリングを行う.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Node&lt;/code&gt;はVMまたは物理マシンで構成され, クラスタのワーカーとして動作する.
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Node&lt;/code&gt;を管理し, &lt;code&gt;Master&lt;/code&gt;と通信するための&lt;code&gt;Kubelet&lt;/code&gt;を持つ.
&lt;ul&gt;
&lt;li&gt;通信は&lt;code&gt;Kubernetes API&lt;/code&gt;を介して行う.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;コンテナを動かすための&lt;code&gt;Docker&lt;/code&gt;を持つ.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="Kubernetesクラスタ" class="gallery-image" data-flex-basis="388px" data-flex-grow="161" height="1128" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-10-29-kubernetes-basics/2019-11-14-fig01.png" srcset="https://blog.uzimihsr.com/post/2019-10-29-kubernetes-basics/2019-11-14-fig01_hu_66b26ccba7c8aa89.png 800w, https://blog.uzimihsr.com/post/2019-10-29-kubernetes-basics/2019-11-14-fig01_hu_e26ec8f2720bb28c.png 1600w, https://blog.uzimihsr.com/post/2019-10-29-kubernetes-basics/2019-11-14-fig01.png 1825w" width="1825"&gt;&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;チュートリアル&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Minikubeのバージョン確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ minikube version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;minikube version: v1.5.2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;commit: 792dbf92a1de583fcee76f8791cff12e0c9440ad
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Kubernetesクラスタの作成(VirtualBoxを使用)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ minikube start --vm-driver&lt;span class="o"&gt;=&lt;/span&gt;virtualbox
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;😄 minikube v1.5.2 on Darwin 10.14
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🔥 Creating virtualbox VM &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;CPUs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2, &lt;span class="nv"&gt;Memory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2000MB, &lt;span class="nv"&gt;Disk&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;20000MB&lt;span class="o"&gt;)&lt;/span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🐳 Preparing Kubernetes v1.16.2 on Docker &lt;span class="s1"&gt;&amp;#39;18.09.9&amp;#39;&lt;/span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🚜 Pulling images ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🚀 Launching Kubernetes ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;⌛ Waiting &lt;span class="k"&gt;for&lt;/span&gt;: apiserver
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🏄 Done! kubectl is now configured to use &lt;span class="s2"&gt;&amp;#34;minikube&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# kubectlのバージョン確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Client Version: version.Info&lt;span class="o"&gt;{&lt;/span&gt;Major:&lt;span class="s2"&gt;&amp;#34;1&amp;#34;&lt;/span&gt;, Minor:&lt;span class="s2"&gt;&amp;#34;16&amp;#34;&lt;/span&gt;, GitVersion:&lt;span class="s2"&gt;&amp;#34;v1.16.2&amp;#34;&lt;/span&gt;, GitCommit:&lt;span class="s2"&gt;&amp;#34;c97fe5036ef3df2967d086711e6c0c405941e14b&amp;#34;&lt;/span&gt;, GitTreeState:&lt;span class="s2"&gt;&amp;#34;clean&amp;#34;&lt;/span&gt;, BuildDate:&lt;span class="s2"&gt;&amp;#34;2019-10-15T23:41:55Z&amp;#34;&lt;/span&gt;, GoVersion:&lt;span class="s2"&gt;&amp;#34;go1.12.10&amp;#34;&lt;/span&gt;, Compiler:&lt;span class="s2"&gt;&amp;#34;gc&amp;#34;&lt;/span&gt;, Platform:&lt;span class="s2"&gt;&amp;#34;darwin/amd64&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Server Version: version.Info&lt;span class="o"&gt;{&lt;/span&gt;Major:&lt;span class="s2"&gt;&amp;#34;1&amp;#34;&lt;/span&gt;, Minor:&lt;span class="s2"&gt;&amp;#34;16&amp;#34;&lt;/span&gt;, GitVersion:&lt;span class="s2"&gt;&amp;#34;v1.16.2&amp;#34;&lt;/span&gt;, GitCommit:&lt;span class="s2"&gt;&amp;#34;c97fe5036ef3df2967d086711e6c0c405941e14b&amp;#34;&lt;/span&gt;, GitTreeState:&lt;span class="s2"&gt;&amp;#34;clean&amp;#34;&lt;/span&gt;, BuildDate:&lt;span class="s2"&gt;&amp;#34;2019-10-15T19:09:08Z&amp;#34;&lt;/span&gt;, GoVersion:&lt;span class="s2"&gt;&amp;#34;go1.12.10&amp;#34;&lt;/span&gt;, Compiler:&lt;span class="s2"&gt;&amp;#34;gc&amp;#34;&lt;/span&gt;, Platform:&lt;span class="s2"&gt;&amp;#34;linux/amd64&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# クラスタ情報の確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl cluster-info
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Kubernetes master is running at https://192.168.99.108:8443
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;KubeDNS is running at https://192.168.99.108:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;To further debug and diagnose cluster problems, use &lt;span class="s1"&gt;&amp;#39;kubectl cluster-info dump&amp;#39;&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Nodeの一覧を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get nodes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME STATUS ROLES AGE VERSION
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;minikube Ready master 107s v1.16.2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;h2 id="アプリケーションのデプロイ"&gt;アプリケーションのデプロイ
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;Deployment&lt;/code&gt;とは&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;アプリケーションインスタンスの作成, 更新方法を&lt;code&gt;Kubernetes&lt;/code&gt;に指示するもの
&lt;ul&gt;
&lt;li&gt;アプリケーションインスタンスは&lt;code&gt;Node&lt;/code&gt;に作成される&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Master&lt;/code&gt;にある&lt;code&gt;Deployment Controller&lt;/code&gt;が各インスタンスを監視する
&lt;ul&gt;
&lt;li&gt;問題があった場合は&lt;code&gt;セルフヒーリング&lt;/code&gt;を行う(別&lt;code&gt;Node&lt;/code&gt;のインスタンスと置き換える)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="Deployment" class="gallery-image" data-flex-basis="388px" data-flex-grow="161" height="1128" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-10-29-kubernetes-basics/2019-11-14-fig02.png" srcset="https://blog.uzimihsr.com/post/2019-10-29-kubernetes-basics/2019-11-14-fig02_hu_8be3c09a4e60478a.png 800w, https://blog.uzimihsr.com/post/2019-10-29-kubernetes-basics/2019-11-14-fig02_hu_94bc0c86dc6a884f.png 1600w, https://blog.uzimihsr.com/post/2019-10-29-kubernetes-basics/2019-11-14-fig02.png 1825w" width="1825"&gt;&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;チュートリアル&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Deploymentの作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# kubernetes-bootcampという名前のDeploymentを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# --imageで使用するDocker imageを指定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create deployment kubernetes-bootcamp --image&lt;span class="o"&gt;=&lt;/span&gt;gcr.io/google-samples/kubernetes-bootcamp:v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps/kubernetes-bootcamp created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Deploymentの一覧を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get deployments
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY UP-TO-DATE AVAILABLE AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp 1/1 &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 59s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 別のターミナルを開き, ローカルマシンからKubernetes APIに接続するためのproxyを起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl proxy
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Starting to serve on 127.0.0.1:8001
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 使い終わったらCtrl + Cで終了できる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Kubernetes APIにアクセスしてバージョンを確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://127.0.0.1:8001/version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;major&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;1&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;minor&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;16&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;gitVersion&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;v1.16.2&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;gitCommit&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;c97fe5036ef3df2967d086711e6c0c405941e14b&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;gitTreeState&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;clean&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;buildDate&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;2019-10-15T19:09:08Z&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;goVersion&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;go1.12.10&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;compiler&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;gc&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;platform&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;linux/amd64&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 起動しているPodの名前を取得して環境変数POD_NAMEに代入&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;POD_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;kubectl get pods -o go-template --template &lt;span class="s1"&gt;&amp;#39;{{range .items}}{{.metadata.name}}{{&amp;#34;\n&amp;#34;}}{{end}}&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; Name of the Pod: &lt;span class="nv"&gt;$POD_NAME&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name of the Pod: kubernetes-bootcamp-69fbc6f4cf-6kppt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;h2 id="アプリケーションの探索"&gt;アプリケーションの探索
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;Pod&lt;/code&gt;とは&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1つ以上のコンテナとコンテナの共有リソースを持つ, &lt;code&gt;Kubernetes&lt;/code&gt;の最小単位
&lt;ul&gt;
&lt;li&gt;共有ストレージ, IPアドレス, コンテナの動作に関わる情報を持つ&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Pod&lt;/code&gt;内のコンテナはIPアドレスとポートを共有する&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Deployment&lt;/code&gt;によって作成/管理される&lt;/li&gt;
&lt;li&gt;割り当てられた(スケジュールされた)&lt;code&gt;Node&lt;/code&gt;上で動作する&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;Node&lt;/code&gt;とは&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Kubernetes&lt;/code&gt;のワーカー
&lt;ul&gt;
&lt;li&gt;物理マシン, 仮想マシン問わずワーカーとして機能できる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;複数の&lt;code&gt;Pod&lt;/code&gt;を持つことができる&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Master&lt;/code&gt;によって管理される
&lt;ul&gt;
&lt;li&gt;同一クラスタの&lt;code&gt;Node&lt;/code&gt;間での&lt;code&gt;Pod&lt;/code&gt;のスケジューリングが自動で管理される&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Kubelet&lt;/code&gt;が&lt;code&gt;Master&lt;/code&gt;との通信を担当し, &lt;code&gt;Pod&lt;/code&gt;を管理する&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Docker&lt;/code&gt;を使用してレジストリからイメージを取得, コンテナの実行を行う&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="PodとNode" class="gallery-image" data-flex-basis="415px" data-flex-grow="173" height="1000" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-10-29-kubernetes-basics/2019-11-14-fig03.png" srcset="https://blog.uzimihsr.com/post/2019-10-29-kubernetes-basics/2019-11-14-fig03_hu_fe9956fb8834e616.png 800w, https://blog.uzimihsr.com/post/2019-10-29-kubernetes-basics/2019-11-14-fig03_hu_1971e259ccf53160.png 1600w, https://blog.uzimihsr.com/post/2019-10-29-kubernetes-basics/2019-11-14-fig03.png 1731w" width="1731"&gt;&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;チュートリアル&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podの一覧を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-69fbc6f4cf-6kppt 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 58m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podの詳細を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl describe pods
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: kubernetes-bootcamp-69fbc6f4cf-6kppt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Priority: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node: minikube/192.168.99.109
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Start Time: Wed, &lt;span class="m"&gt;06&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:24:56 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;69fbc6f4cf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Status: Running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IP: 172.17.0.6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IPs:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; IP: 172.17.0.6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Controlled By: ReplicaSet/kubernetes-bootcamp-69fbc6f4cf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Containers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubernetes-bootcamp:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Container ID: docker://64bbc713c49fde8d7fa154fc35b53bcf2515cbf12426248da36b11690a11d2f4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image: gcr.io/google-samples/kubernetes-bootcamp:v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image ID: docker-pullable://gcr.io/google-samples/kubernetes-bootcamp@sha256:0d6b8ee63bb57c5f5b6156f446b3bc3b3c143d233037f3a2f00e279c8fcc64af
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Host Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; State: Running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Started: Wed, &lt;span class="m"&gt;06&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:25:15 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready: True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Restart Count: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Environment: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Mounts:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; /var/run/secrets/kubernetes.io/serviceaccount from default-token-jj2nf &lt;span class="o"&gt;(&lt;/span&gt;ro&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Conditions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Initialized True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ContainersReady True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; PodScheduled True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Volumes:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; default-token-jj2nf:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type: Secret &lt;span class="o"&gt;(&lt;/span&gt;a volume populated by a Secret&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; SecretName: default-token-jj2nf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Optional: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;QoS Class: BestEffort
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node-Selectors: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Tolerations: node.kubernetes.io/not-ready:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; node.kubernetes.io/unreachable:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Reason Age From Message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---- ------ ---- ---- -------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Scheduled &amp;lt;unknown&amp;gt; default-scheduler Successfully assigned default/kubernetes-bootcamp-69fbc6f4cf-6kppt to minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Pulling 59m kubelet, minikube Pulling image &lt;span class="s2"&gt;&amp;#34;gcr.io/google-samples/kubernetes-bootcamp:v1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Pulled 58m kubelet, minikube Successfully pulled image &lt;span class="s2"&gt;&amp;#34;gcr.io/google-samples/kubernetes-bootcamp:v1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Created 58m kubelet, minikube Created container kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Started 58m kubelet, minikube Started container kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# proxyは起動済み&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# $ kubectl proxy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Pod名も取得済み&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# $ export POD_NAME=$(kubectl get pods -o go-template --template &amp;#39;{{range .items}}{{.metadata.name}}{{&amp;#34;\n&amp;#34;}}{{end}}&amp;#39;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; Name of the Pod: &lt;span class="nv"&gt;$POD_NAME&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name of the Pod: kubernetes-bootcamp-69fbc6f4cf-6kppt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Kubernetes APIを利用してPodにアクセスする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# が, この通りにやると失敗する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://localhost:8001/api/v1/namespaces/default/pods/&lt;span class="nv"&gt;$POD_NAME&lt;/span&gt;/proxy/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Error trying to reach service: &lt;span class="s1"&gt;&amp;#39;dial tcp 172.17.0.6:80: connect: connection refused&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 上記コマンドでは失敗するので, 次のコマンドを実行する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 詳細は下記`connection refusedになる問題について`を参照&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://localhost:8001/api/v1/namespaces/default/pods/&lt;span class="nv"&gt;$POD_NAME&lt;/span&gt;:8080/proxy/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Hello Kubernetes bootcamp! &lt;span class="p"&gt;|&lt;/span&gt; Running on: kubernetes-bootcamp-69fbc6f4cf-6kppt &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;v&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;チュートリアルでconnection refusedになる問題について&lt;/summary&gt;&lt;div&gt;
&lt;p&gt;使用している&lt;code&gt;image&lt;/code&gt;(&lt;strong&gt;gcr.io/google-samples/kubernetes-bootcamp:v1&lt;/strong&gt;)が公開しているポートが80番でなく8080番であるにもかかわらず,&lt;br&gt;
&lt;code&gt;Kubernetes API&lt;/code&gt;の&lt;a class="link" href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.16/#get-connect-proxy-pod-v1-core" target="_blank" rel="noopener"
 &gt;Get Connect Proxy&lt;/a&gt;で&lt;code&gt;Pod&lt;/code&gt;にアクセスする際にデフォルトのポート(80番)を叩こうとしていることが原因.&lt;br&gt;
接続しようとしている&lt;code&gt;Pod&lt;/code&gt;には80番ポートが割り当てられているコンテナが無いため, 接続が拒否される.&lt;/p&gt;
&lt;p&gt;以下は確認手順.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# 実際にimageをローカルに持ってくる
$ docker pull gcr.io/google-samples/kubernetes-bootcamp:v1
v1: Pulling from google-samples/kubernetes-bootcamp
5c90d4a2d1a8: Pull complete
ab30c63719b1: Pull complete
29d0bc1e8c52: Pull complete
d4fe0dc68927: Pull complete
dfa9e924f957: Pull complete
Digest: sha256:0d6b8ee63bb57c5f5b6156f446b3bc3b3c143d233037f3a2f00e279c8fcc64af
Status: Downloaded newer image for gcr.io/google-samples/kubernetes-bootcamp:v1
gcr.io/google-samples/kubernetes-bootcamp:v1

# Dockerfileの内容を確認
$ docker image history gcr.io/google-samples/kubernetes-bootcamp:v1
IMAGE CREATED CREATED BY SIZE COMMENT
8fafd8af70e9 3 years ago /bin/sh -c #(nop) CMD [&amp;#34;/bin/sh&amp;#34; &amp;#34;-c&amp;#34; &amp;#34;node… 0B
&amp;lt;missing&amp;gt; 3 years ago /bin/sh -c #(nop) COPY file:de8ef36ebbfd5305… 742B
&amp;lt;missing&amp;gt; 3 years ago /bin/sh -c #(nop) EXPOSE 8080/tcp 0B
&amp;lt;missing&amp;gt; 3 years ago /bin/sh -c #(nop) CMD [&amp;#34;node&amp;#34;] 0B
&amp;lt;missing&amp;gt; 3 years ago /bin/sh -c buildDeps=&amp;#34;xz-utils&amp;#34; &amp;amp;&amp;amp; set -… 41.5MB
&amp;lt;missing&amp;gt; 3 years ago /bin/sh -c #(nop) ENV NODE_VERSION=6.3.1 0B
&amp;lt;missing&amp;gt; 3 years ago /bin/sh -c #(nop) ENV NPM_CONFIG_LOGLEVEL=in… 0B
&amp;lt;missing&amp;gt; 3 years ago /bin/sh -c set -ex &amp;amp;&amp;amp; for key in 9554F… 80.8kB
&amp;lt;missing&amp;gt; 3 years ago /bin/sh -c apt-get update &amp;amp;&amp;amp; apt-get install… 44.7MB
&amp;lt;missing&amp;gt; 3 years ago /bin/sh -c #(nop) CMD [&amp;#34;/bin/bash&amp;#34;] 0B
&amp;lt;missing&amp;gt; 3 years ago /bin/sh -c #(nop) ADD file:76679eeb94129df23… 125MB

# 上記の通り, このimageは`EXPOSE 8080`で8080番ポートを公開している. 
# そのため, チュートリアル通りのコマンドではデフォルトの80番ポート(公開されていない)を見ようとするので失敗する. 
$ curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME/proxy/
Error trying to reach service: &amp;#39;dial tcp 172.17.0.6:80: connect: connection refused&amp;#39;

# Pod名の後にポート番号を指定してあげると問題なくアクセスできる. 
$ curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME:8080/proxy/
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-69fbc6f4cf-6kppt | v=1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/details&gt;
&lt;h2 id="アプリケーションの公開"&gt;アプリケーションの公開
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;Service&lt;/code&gt;とは&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Pod&lt;/code&gt;を外部に公開するためのもの&lt;/li&gt;
&lt;li&gt;IPを指定せずに&lt;code&gt;Label&lt;/code&gt;を用いて各&lt;code&gt;Pod&lt;/code&gt;を指定してアクセスできるようにする役割を持つ&lt;/li&gt;
&lt;li&gt;複数&lt;code&gt;Pod&lt;/code&gt;間の負荷分散を行う
&lt;ul&gt;
&lt;li&gt;複数&lt;code&gt;Node&lt;/code&gt;間に存在する&lt;code&gt;Pod&lt;/code&gt;間でも負荷分散が可能&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="Service" class="gallery-image" data-flex-basis="441px" data-flex-grow="184" height="1127" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-10-29-kubernetes-basics/2019-11-14-fig04.png" srcset="https://blog.uzimihsr.com/post/2019-10-29-kubernetes-basics/2019-11-14-fig04_hu_ff4e9fbed0da3fdf.png 800w, https://blog.uzimihsr.com/post/2019-10-29-kubernetes-basics/2019-11-14-fig04_hu_a0657d04c28dd314.png 1600w, https://blog.uzimihsr.com/post/2019-10-29-kubernetes-basics/2019-11-14-fig04.png 2075w" width="2075"&gt;&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;チュートリアル&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podの一覧を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-69fbc6f4cf-6kppt 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 4d22h
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Serviceの一覧を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# kubernetesはMinikube起動時にデフォルトで生成されるService&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get services
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes ClusterIP 10.96.0.1 &amp;lt;none&amp;gt; 443/TCP 4d22h
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 既に存在するDeployment(kubernetes-bootcamp)を公開するNodePort Serviceを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl expose deployment/kubernetes-bootcamp --type&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;NodePort&amp;#34;&lt;/span&gt; --port &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/kubernetes-bootcamp exposed
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 再度Serviceの一覧を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 新たにService(kubernetes-bootcamp)が作成されていることを確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get services
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes ClusterIP 10.96.0.1 &amp;lt;none&amp;gt; 443/TCP 4d22h
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp NodePort 10.106.55.200 &amp;lt;none&amp;gt; 8080:31038/TCP 17s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Service(kubernetes-bootcamp)の詳細を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Nodeの31038番ががPodの8080番に割り当てられている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl describe services/kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Selector: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Type: NodePort
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IP: 10.106.55.200
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Port: &amp;lt;unset&amp;gt; 8080/TCP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;TargetPort: 8080/TCP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NodePort: &amp;lt;unset&amp;gt; 31038/TCP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Endpoints: 172.17.0.6:8080
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Session Affinity: None
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;External Traffic Policy: Cluster
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Serviceによって公開されているNodeのポート番号を環境変数NODE_PORTに代入&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;NODE_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;kubectl get services/kubernetes-bootcamp -o go-template&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;{{(index .spec.ports 0).nodePort}}&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;NODE_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$NODE_PORT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;NODE_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;31038&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 公開されているポート番号へアクセス&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl &lt;span class="k"&gt;$(&lt;/span&gt;minikube ip&lt;span class="k"&gt;)&lt;/span&gt;:&lt;span class="nv"&gt;$NODE_PORT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Hello Kubernetes bootcamp! &lt;span class="p"&gt;|&lt;/span&gt; Running on: kubernetes-bootcamp-69fbc6f4cf-6kppt &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;v&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 起動しているDeploymentの詳細を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# デフォルトでLabel(app=kubernetes-bootcamp)がつけられている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl describe deployment
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;CreationTimestamp: Wed, &lt;span class="m"&gt;06&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:24:56 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: deployment.kubernetes.io/revision: &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Selector: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Replicas: &lt;span class="m"&gt;1&lt;/span&gt; desired &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; updated &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; total &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; available &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; unavailable
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;StrategyType: RollingUpdate
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;MinReadySeconds: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;RollingUpdateStrategy: 25% max unavailable, 25% max surge
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Pod Template:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Labels: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Containers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubernetes-bootcamp:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image: gcr.io/google-samples/kubernetes-bootcamp:v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Host Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Environment: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Mounts: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Volumes: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Conditions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Status Reason
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---- ------ ------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Available True MinimumReplicasAvailable
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Progressing True NewReplicaSetAvailable
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;OldReplicaSets: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NewReplicaSet: kubernetes-bootcamp-69fbc6f4cf &lt;span class="o"&gt;(&lt;/span&gt;1/1 replicas created&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Label(run=kubernetes-bootcamp)を指定してPodを表示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -l &lt;span class="nv"&gt;run&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-69fbc6f4cf-6kppt 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 4d23h
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 同様にServiceもLabelで絞り込んで表示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get services -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp NodePort 10.106.55.200 &amp;lt;none&amp;gt; 8080:31038/TCP 16m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 環境変数POD_NAMEにPod名を代入&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;POD_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;kubectl get pods -o go-template --template &lt;span class="s1"&gt;&amp;#39;{{range .items}}{{.metadata.name}}{{&amp;#34;\n&amp;#34;}}{{end}}&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; Name of the Pod: &lt;span class="nv"&gt;$POD_NAME&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name of the Pod: kubernetes-bootcamp-69fbc6f4cf-6kppt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Pod(kubernetes-bootcamp-69fbc6f4cf-6kppt)にLabel(app=v1)を追加&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 既にkey(app)に対してvalue(kubernetes-bootcamp)がついていて, --overwriteを指定していないので失敗する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl label pod &lt;span class="nv"&gt;$POD_NAME&lt;/span&gt; &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;error: &lt;span class="s1"&gt;&amp;#39;app&amp;#39;&lt;/span&gt; already has a value &lt;span class="o"&gt;(&lt;/span&gt;kubernetes-bootcamp&lt;span class="o"&gt;)&lt;/span&gt;, and --overwrite is &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 手順とは異なるが別のkey:valueを指定してみる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl label pod &lt;span class="nv"&gt;$POD_NAME&lt;/span&gt; &lt;span class="nv"&gt;app_hoge&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/kubernetes-bootcamp-69fbc6f4cf-6kppt labeled
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Pod(kubernetes-bootcamp-69fbc6f4cf-6kppt)の詳細を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Label(app_hoge=v1)が追加されている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl describe pods &lt;span class="nv"&gt;$POD_NAME&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: kubernetes-bootcamp-69fbc6f4cf-6kppt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Priority: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node: minikube/192.168.99.109
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Start Time: Wed, &lt;span class="m"&gt;06&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:24:56 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;app_hoge&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;69fbc6f4cf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Status: Running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IP: 172.17.0.6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IPs:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; IP: 172.17.0.6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Controlled By: ReplicaSet/kubernetes-bootcamp-69fbc6f4cf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Containers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubernetes-bootcamp:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Container ID: docker://64bbc713c49fde8d7fa154fc35b53bcf2515cbf12426248da36b11690a11d2f4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image: gcr.io/google-samples/kubernetes-bootcamp:v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image ID: docker-pullable://gcr.io/google-samples/kubernetes-bootcamp@sha256:0d6b8ee63bb57c5f5b6156f446b3bc3b3c143d233037f3a2f00e279c8fcc64af
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Host Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; State: Running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Started: Wed, &lt;span class="m"&gt;06&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:25:15 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready: True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Restart Count: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Environment: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Mounts:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; /var/run/secrets/kubernetes.io/serviceaccount from default-token-jj2nf &lt;span class="o"&gt;(&lt;/span&gt;ro&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Conditions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Initialized True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ContainersReady True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; PodScheduled True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Volumes:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; default-token-jj2nf:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type: Secret &lt;span class="o"&gt;(&lt;/span&gt;a volume populated by a Secret&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; SecretName: default-token-jj2nf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Optional: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;QoS Class: BestEffort
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node-Selectors: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Tolerations: node.kubernetes.io/not-ready:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; node.kubernetes.io/unreachable:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Label(app_hoge=v1)を持つPodを表示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -l &lt;span class="nv"&gt;app_hoge&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-69fbc6f4cf-6kppt 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 4d23h
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Label(app=kubernetes-bootcamp)を指定してServiceを削除&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl delete service -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service &lt;span class="s2"&gt;&amp;#34;kubernetes-bootcamp&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 再度Serviceの一覧を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# kubernetes-bootcampが削除されている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get services
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes ClusterIP 10.96.0.1 &amp;lt;none&amp;gt; 443/TCP 4d23h
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 再度ポートにアクセスする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Serviceが削除され, 31038番が公開されていないので失敗する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl &lt;span class="k"&gt;$(&lt;/span&gt;minikube ip&lt;span class="k"&gt;)&lt;/span&gt;:&lt;span class="nv"&gt;$NODE_PORT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl: &lt;span class="o"&gt;(&lt;/span&gt;7&lt;span class="o"&gt;)&lt;/span&gt; Failed to connect to 192.168.99.109 port 31038: Connection refused
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podの中からアクセスする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Serviceがなくてもアプリケーションは生きていることが確認できる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -ti &lt;span class="nv"&gt;$POD_NAME&lt;/span&gt; curl localhost:8080
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Hello Kubernetes bootcamp! &lt;span class="p"&gt;|&lt;/span&gt; Running on: kubernetes-bootcamp-69fbc6f4cf-6kppt &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;v&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;h2 id="アプリケーションのスケーリング"&gt;アプリケーションのスケーリング
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Deploymentによるスケーリング&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;スケーリングは&lt;code&gt;Deployment&lt;/code&gt;の&lt;code&gt;Replicas&lt;/code&gt;を変更することで行う&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Replicas&lt;/code&gt;が増えた場合は利用可能な&lt;code&gt;Node&lt;/code&gt;に新しい&lt;code&gt;Pod&lt;/code&gt;が作成される&lt;/li&gt;
&lt;li&gt;新たに生成された&lt;code&gt;Pod&lt;/code&gt;へのトラフィック設定は&lt;code&gt;Service&lt;/code&gt;で管理する&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="スケールアウト" class="gallery-image" data-flex-basis="470px" data-flex-grow="196" height="1153" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-10-29-kubernetes-basics/2019-11-14-fig05.png" srcset="https://blog.uzimihsr.com/post/2019-10-29-kubernetes-basics/2019-11-14-fig05_hu_5142b8d90d3ff725.png 800w, https://blog.uzimihsr.com/post/2019-10-29-kubernetes-basics/2019-11-14-fig05_hu_f16a8753b69fc3d8.png 1600w, https://blog.uzimihsr.com/post/2019-10-29-kubernetes-basics/2019-11-14-fig05.png 2261w" width="2261"&gt;&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;チュートリアル&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Deploymentの一覧を表示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# READYは(起動しているPod数)/(設定されているPod数)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# UP-TO-DATEは指定の状態になっているPod数&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# AVAILABLEはユーザーが利用可能なPod数&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get deployments
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY UP-TO-DATE AVAILABLE AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp 1/1 &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 5d
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Deployment(kubernetes-bootcamp)のReplicasを4に増やす&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl scale deployments/kubernetes-bootcamp --replicas&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps/kubernetes-bootcamp scaled
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 再度Deploymentの一覧を表示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Pod数が指定した値(4)に変わっている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get deployments
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY UP-TO-DATE AVAILABLE AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp 4/4 &lt;span class="m"&gt;4&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt; 5d
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podの一覧を表示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 確かにPodが4つそれぞれ別IPで稼働している&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -o wide
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-69fbc6f4cf-6kppt 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 5d 172.17.0.6 minikube &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-69fbc6f4cf-9htwb 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 11m 172.17.0.9 minikube &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-69fbc6f4cf-cm8pb 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 11m 172.17.0.7 minikube &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-69fbc6f4cf-j5kq2 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 11m 172.17.0.8 minikube &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Deployment(kubernetes-bootcamp)の詳細表示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Replicasが4に変わっている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 変更履歴はEventに記録される&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl describe deployments/kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;CreationTimestamp: Wed, &lt;span class="m"&gt;06&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:24:56 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: deployment.kubernetes.io/revision: &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Selector: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Replicas: &lt;span class="m"&gt;4&lt;/span&gt; desired &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt; updated &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt; total &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt; available &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; unavailable
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;StrategyType: RollingUpdate
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;MinReadySeconds: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;RollingUpdateStrategy: 25% max unavailable, 25% max surge
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Pod Template:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Labels: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Containers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubernetes-bootcamp:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image: gcr.io/google-samples/kubernetes-bootcamp:v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Host Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Environment: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Mounts: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Volumes: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Conditions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Status Reason
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---- ------ ------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Progressing True NewReplicaSetAvailable
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Available True MinimumReplicasAvailable
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;OldReplicaSets: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NewReplicaSet: kubernetes-bootcamp-69fbc6f4cf &lt;span class="o"&gt;(&lt;/span&gt;4/4 replicas created&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Reason Age From Message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---- ------ ---- ---- -------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal ScalingReplicaSet 6m48s deployment-controller Scaled up replica &lt;span class="nb"&gt;set&lt;/span&gt; kubernetes-bootcamp-69fbc6f4cf to &lt;span class="m"&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 手順にはないが前のチュートリアルでServiceを削除してしまっているので再度作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl expose deployment/kubernetes-bootcamp --type&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;NodePort&amp;#34;&lt;/span&gt; --port &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/kubernetes-bootcamp exposed
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Service(kubernetes-bootcamp)の詳細を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Deployment(kubernetes-bootcamp)が管理する4つのPodが接続されている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl describe services/kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Selector: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Type: NodePort
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IP: 10.111.26.43
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Port: &amp;lt;unset&amp;gt; 8080/TCP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;TargetPort: 8080/TCP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NodePort: &amp;lt;unset&amp;gt; 31189/TCP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Endpoints: 172.17.0.6:8080,172.17.0.7:8080,172.17.0.8:8080 + &lt;span class="m"&gt;1&lt;/span&gt; more...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Session Affinity: None
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;External Traffic Policy: Cluster
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 環境変数NODE_PORTに公開されているNodeのポート番号を代入&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;NODE_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;kubectl get services/kubernetes-bootcamp -o go-template&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;{{(index .spec.ports 0).nodePort}}&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;NODE_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$NODE_PORT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;NODE_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;31189&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# アクセスするたびに違うPodからレスポンスが返ってくる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 負荷分散ができている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl &lt;span class="k"&gt;$(&lt;/span&gt;minikube ip&lt;span class="k"&gt;)&lt;/span&gt;:&lt;span class="nv"&gt;$NODE_PORT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Hello Kubernetes bootcamp! &lt;span class="p"&gt;|&lt;/span&gt; Running on: kubernetes-bootcamp-69fbc6f4cf-6kppt &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;v&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl &lt;span class="k"&gt;$(&lt;/span&gt;minikube ip&lt;span class="k"&gt;)&lt;/span&gt;:&lt;span class="nv"&gt;$NODE_PORT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Hello Kubernetes bootcamp! &lt;span class="p"&gt;|&lt;/span&gt; Running on: kubernetes-bootcamp-69fbc6f4cf-cm8pb &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;v&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl &lt;span class="k"&gt;$(&lt;/span&gt;minikube ip&lt;span class="k"&gt;)&lt;/span&gt;:&lt;span class="nv"&gt;$NODE_PORT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Hello Kubernetes bootcamp! &lt;span class="p"&gt;|&lt;/span&gt; Running on: kubernetes-bootcamp-69fbc6f4cf-j5kq2 &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;v&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl &lt;span class="k"&gt;$(&lt;/span&gt;minikube ip&lt;span class="k"&gt;)&lt;/span&gt;:&lt;span class="nv"&gt;$NODE_PORT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Hello Kubernetes bootcamp! &lt;span class="p"&gt;|&lt;/span&gt; Running on: kubernetes-bootcamp-69fbc6f4cf-j5kq2 &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;v&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl &lt;span class="k"&gt;$(&lt;/span&gt;minikube ip&lt;span class="k"&gt;)&lt;/span&gt;:&lt;span class="nv"&gt;$NODE_PORT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Hello Kubernetes bootcamp! &lt;span class="p"&gt;|&lt;/span&gt; Running on: kubernetes-bootcamp-69fbc6f4cf-9htwb &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;v&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Deployment(kubernetes-bootcamp)のReplicasを2に減らす&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl scale deployments/kubernetes-bootcamp --replicas&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps/kubernetes-bootcamp scaled
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Deploymentの一覧を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Pod数が2に減っている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get deployments
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY UP-TO-DATE AVAILABLE AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp 2/2 &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; 5d
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podの一覧を表示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 4つあったPodのうち2つが消えている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -o wide
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-69fbc6f4cf-6kppt 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 5d 172.17.0.6 minikube &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-69fbc6f4cf-9htwb 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 19m 172.17.0.9 minikube &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;h2 id="アプリケーションのアップデート"&gt;アプリケーションのアップデート
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;ローリングアップデートとは&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Pod&lt;/code&gt;を段階的にアップデートすること
&lt;ul&gt;
&lt;li&gt;ダウンタイムが発生しない&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="ローリングアップデート" class="gallery-image" data-flex-basis="357px" data-flex-grow="148" height="1975" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-10-29-kubernetes-basics/2019-11-14-fig06.png" srcset="https://blog.uzimihsr.com/post/2019-10-29-kubernetes-basics/2019-11-14-fig06_hu_c2b80120a4aea09a.png 800w, https://blog.uzimihsr.com/post/2019-10-29-kubernetes-basics/2019-11-14-fig06_hu_a4c62bd3e692cfcd.png 1600w, https://blog.uzimihsr.com/post/2019-10-29-kubernetes-basics/2019-11-14-fig06_hu_f0b55129d8b4a2f0.png 2400w, https://blog.uzimihsr.com/post/2019-10-29-kubernetes-basics/2019-11-14-fig06.png 2940w" width="2940"&gt;&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;チュートリアル&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 手順にはないが後半の手順とPod数を合わせるためスケールアウトする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl scale deployments/kubernetes-bootcamp --replicas&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps/kubernetes-bootcamp scaled
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Deploymentの一覧を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get deployments
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY UP-TO-DATE AVAILABLE AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp 4/4 &lt;span class="m"&gt;4&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt; 5d23h
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podの一覧を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-69fbc6f4cf-6hx6m 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 57s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-69fbc6f4cf-6kppt 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 5d23h
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-69fbc6f4cf-6rvk4 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 57s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-69fbc6f4cf-9htwb 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 23h
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podの詳細を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl describe pods
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: kubernetes-bootcamp-69fbc6f4cf-6hx6m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Priority: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node: minikube/192.168.99.109
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Start Time: Tue, &lt;span class="m"&gt;12&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:05:57 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;69fbc6f4cf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Status: Running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IP: 172.17.0.7
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IPs:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; IP: 172.17.0.7
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Controlled By: ReplicaSet/kubernetes-bootcamp-69fbc6f4cf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Containers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubernetes-bootcamp:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Container ID: docker://4a1577f4cc007bbdc62d54afb048b3c67c622e9d4fa4fcbc7bb4e7a7014a8e70
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image: gcr.io/google-samples/kubernetes-bootcamp:v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image ID: docker-pullable://gcr.io/google-samples/kubernetes-bootcamp@sha256:0d6b8ee63bb57c5f5b6156f446b3bc3b3c143d233037f3a2f00e279c8fcc64af
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Host Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; State: Running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Started: Tue, &lt;span class="m"&gt;12&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:05:58 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready: True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Restart Count: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Environment: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Mounts:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; /var/run/secrets/kubernetes.io/serviceaccount from default-token-jj2nf &lt;span class="o"&gt;(&lt;/span&gt;ro&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Conditions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Initialized True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ContainersReady True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; PodScheduled True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Volumes:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; default-token-jj2nf:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type: Secret &lt;span class="o"&gt;(&lt;/span&gt;a volume populated by a Secret&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; SecretName: default-token-jj2nf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Optional: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;QoS Class: BestEffort
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node-Selectors: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Tolerations: node.kubernetes.io/not-ready:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; node.kubernetes.io/unreachable:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Reason Age From Message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---- ------ ---- ---- -------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Scheduled &amp;lt;unknown&amp;gt; default-scheduler Successfully assigned default/kubernetes-bootcamp-69fbc6f4cf-6hx6m to minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Pulled 91s kubelet, minikube Container image &lt;span class="s2"&gt;&amp;#34;gcr.io/google-samples/kubernetes-bootcamp:v1&amp;#34;&lt;/span&gt; already present on machine
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Created 91s kubelet, minikube Created container kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Started 91s kubelet, minikube Started container kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: kubernetes-bootcamp-69fbc6f4cf-6kppt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Priority: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node: minikube/192.168.99.109
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Start Time: Wed, &lt;span class="m"&gt;06&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:24:56 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;app_hoge&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;69fbc6f4cf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Status: Running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IP: 172.17.0.6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IPs:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; IP: 172.17.0.6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Controlled By: ReplicaSet/kubernetes-bootcamp-69fbc6f4cf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Containers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubernetes-bootcamp:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Container ID: docker://64bbc713c49fde8d7fa154fc35b53bcf2515cbf12426248da36b11690a11d2f4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image: gcr.io/google-samples/kubernetes-bootcamp:v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image ID: docker-pullable://gcr.io/google-samples/kubernetes-bootcamp@sha256:0d6b8ee63bb57c5f5b6156f446b3bc3b3c143d233037f3a2f00e279c8fcc64af
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Host Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; State: Running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Started: Wed, &lt;span class="m"&gt;06&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:25:15 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready: True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Restart Count: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Environment: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Mounts:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; /var/run/secrets/kubernetes.io/serviceaccount from default-token-jj2nf &lt;span class="o"&gt;(&lt;/span&gt;ro&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Conditions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Initialized True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ContainersReady True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; PodScheduled True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Volumes:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; default-token-jj2nf:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type: Secret &lt;span class="o"&gt;(&lt;/span&gt;a volume populated by a Secret&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; SecretName: default-token-jj2nf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Optional: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;QoS Class: BestEffort
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node-Selectors: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Tolerations: node.kubernetes.io/not-ready:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; node.kubernetes.io/unreachable:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: kubernetes-bootcamp-69fbc6f4cf-6rvk4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Priority: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node: minikube/192.168.99.109
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Start Time: Tue, &lt;span class="m"&gt;12&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:05:57 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;69fbc6f4cf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Status: Running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IP: 172.17.0.8
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IPs:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; IP: 172.17.0.8
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Controlled By: ReplicaSet/kubernetes-bootcamp-69fbc6f4cf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Containers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubernetes-bootcamp:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Container ID: docker://124b92bb9f17895f808deee23916dccc6efb95af2fd7e6d8214af7f3ad0bdf97
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image: gcr.io/google-samples/kubernetes-bootcamp:v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image ID: docker-pullable://gcr.io/google-samples/kubernetes-bootcamp@sha256:0d6b8ee63bb57c5f5b6156f446b3bc3b3c143d233037f3a2f00e279c8fcc64af
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Host Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; State: Running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Started: Tue, &lt;span class="m"&gt;12&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:05:58 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready: True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Restart Count: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Environment: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Mounts:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; /var/run/secrets/kubernetes.io/serviceaccount from default-token-jj2nf &lt;span class="o"&gt;(&lt;/span&gt;ro&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Conditions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Initialized True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ContainersReady True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; PodScheduled True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Volumes:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; default-token-jj2nf:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type: Secret &lt;span class="o"&gt;(&lt;/span&gt;a volume populated by a Secret&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; SecretName: default-token-jj2nf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Optional: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;QoS Class: BestEffort
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node-Selectors: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Tolerations: node.kubernetes.io/not-ready:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; node.kubernetes.io/unreachable:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Reason Age From Message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---- ------ ---- ---- -------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Scheduled &amp;lt;unknown&amp;gt; default-scheduler Successfully assigned default/kubernetes-bootcamp-69fbc6f4cf-6rvk4 to minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Pulled 91s kubelet, minikube Container image &lt;span class="s2"&gt;&amp;#34;gcr.io/google-samples/kubernetes-bootcamp:v1&amp;#34;&lt;/span&gt; already present on machine
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Created 91s kubelet, minikube Created container kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Started 91s kubelet, minikube Started container kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: kubernetes-bootcamp-69fbc6f4cf-9htwb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Priority: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node: minikube/192.168.99.109
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Start Time: Mon, &lt;span class="m"&gt;11&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:35:24 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;69fbc6f4cf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Status: Running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IP: 172.17.0.9
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IPs:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; IP: 172.17.0.9
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Controlled By: ReplicaSet/kubernetes-bootcamp-69fbc6f4cf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Containers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubernetes-bootcamp:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Container ID: docker://ce75a00dbebf8ede509c4bf2776029666518022ee1b164aaced4c7edc90def8d
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image: gcr.io/google-samples/kubernetes-bootcamp:v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image ID: docker-pullable://gcr.io/google-samples/kubernetes-bootcamp@sha256:0d6b8ee63bb57c5f5b6156f446b3bc3b3c143d233037f3a2f00e279c8fcc64af
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Host Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; State: Running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Started: Mon, &lt;span class="m"&gt;11&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:35:25 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready: True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Restart Count: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Environment: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Mounts:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; /var/run/secrets/kubernetes.io/serviceaccount from default-token-jj2nf &lt;span class="o"&gt;(&lt;/span&gt;ro&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Conditions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Initialized True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ContainersReady True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; PodScheduled True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Volumes:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; default-token-jj2nf:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type: Secret &lt;span class="o"&gt;(&lt;/span&gt;a volume populated by a Secret&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; SecretName: default-token-jj2nf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Optional: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;QoS Class: BestEffort
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node-Selectors: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Tolerations: node.kubernetes.io/not-ready:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; node.kubernetes.io/unreachable:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Reason Age From Message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---- ------ ---- ---- -------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Scheduled &amp;lt;unknown&amp;gt; default-scheduler Successfully assigned default/kubernetes-bootcamp-69fbc6f4cf-9htwb to minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Pulled 23h kubelet, minikube Container image &lt;span class="s2"&gt;&amp;#34;gcr.io/google-samples/kubernetes-bootcamp:v1&amp;#34;&lt;/span&gt; already present on machine
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Created 23h kubelet, minikube Created container kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Started 23h kubelet, minikube Started container kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Deployment(kubernetes-bootcamp)で使用しているimage(kubernetes-bootcamp)のバージョンを変更&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;set&lt;/span&gt; image deployments/kubernetes-bootcamp kubernetes-bootcamp&lt;span class="o"&gt;=&lt;/span&gt;jocatalin/kubernetes-bootcamp:v2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps/kubernetes-bootcamp image updated
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 何度かPodの一覧を確認すると順番に古いPodが削除/新しいPodが生成されていることがわかる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-69fbc6f4cf-6hx6m 1/1 Terminating &lt;span class="m"&gt;0&lt;/span&gt; 2m53s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-69fbc6f4cf-6kppt 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 5d23h
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-69fbc6f4cf-6rvk4 1/1 Terminating &lt;span class="m"&gt;0&lt;/span&gt; 2m53s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-69fbc6f4cf-9htwb 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 23h
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-b4d9f565-ftfn6 0/1 ContainerCreating &lt;span class="m"&gt;0&lt;/span&gt; 6s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-b4d9f565-vd6fb 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 6s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-b4d9f565-wwxnf 0/1 ContainerCreating &lt;span class="m"&gt;0&lt;/span&gt; 1s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-69fbc6f4cf-6hx6m 1/1 Terminating &lt;span class="m"&gt;0&lt;/span&gt; 2m56s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-69fbc6f4cf-6kppt 1/1 Terminating &lt;span class="m"&gt;0&lt;/span&gt; 5d23h
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-69fbc6f4cf-6rvk4 1/1 Terminating &lt;span class="m"&gt;0&lt;/span&gt; 2m56s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-69fbc6f4cf-9htwb 1/1 Terminating &lt;span class="m"&gt;0&lt;/span&gt; 23h
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-b4d9f565-ftfn6 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 9s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-b4d9f565-qxjhr 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 2s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-b4d9f565-vd6fb 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 9s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-b4d9f565-wwxnf 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 4s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-b4d9f565-ftfn6 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 48s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-b4d9f565-qxjhr 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 41s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-b4d9f565-vd6fb 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 48s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-b4d9f565-wwxnf 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 43s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Service(kubernetes-bootcamp)の詳細を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl describe services/kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Selector: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Type: NodePort
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IP: 10.111.26.43
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Port: &amp;lt;unset&amp;gt; 8080/TCP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;TargetPort: 8080/TCP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NodePort: &amp;lt;unset&amp;gt; 31189/TCP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Endpoints: 172.17.0.10:8080,172.17.0.11:8080,172.17.0.12:8080 + &lt;span class="m"&gt;1&lt;/span&gt; more...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Session Affinity: None
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;External Traffic Policy: Cluster
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 環境変数NODE_PORTにService(kubernetes-bootcamp)で公開されているポート番号を代入&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;NODE_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;kubectl get services/kubernetes-bootcamp -o go-template&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;{{(index .spec.ports 0).nodePort}}&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;NODE_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$NODE_PORT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;NODE_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;31189&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 公開されているポートにアクセス&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl &lt;span class="k"&gt;$(&lt;/span&gt;minikube ip&lt;span class="k"&gt;)&lt;/span&gt;:&lt;span class="nv"&gt;$NODE_PORT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Hello Kubernetes bootcamp! &lt;span class="p"&gt;|&lt;/span&gt; Running on: kubernetes-bootcamp-b4d9f565-mds8p &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;v&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ローリングアップデートが成功したか確認する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl rollout status deployments/kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment &lt;span class="s2"&gt;&amp;#34;kubernetes-bootcamp&amp;#34;&lt;/span&gt; successfully rolled out
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podの詳細を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Imageがすべてv2に変わっている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl describe pods
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: kubernetes-bootcamp-b4d9f565-4wkhr
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Priority: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node: minikube/192.168.99.109
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Start Time: Tue, &lt;span class="m"&gt;12&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:13:59 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;b4d9f565
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Status: Running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IP: 172.17.0.11
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IPs:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; IP: 172.17.0.11
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Controlled By: ReplicaSet/kubernetes-bootcamp-b4d9f565
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Containers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubernetes-bootcamp:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Container ID: docker://c8bebac0609ee166972beae7437c71733955bfde4107708d28fe3606d68e44d6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image: jocatalin/kubernetes-bootcamp:v2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image ID: docker-pullable://jocatalin/kubernetes-bootcamp@sha256:fb1a3ced00cecfc1f83f18ab5cd14199e30adc1b49aa4244f5d65ad3f5feb2a5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Host Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; State: Running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Started: Tue, &lt;span class="m"&gt;12&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:14:00 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready: True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Restart Count: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Environment: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Mounts:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; /var/run/secrets/kubernetes.io/serviceaccount from default-token-jj2nf &lt;span class="o"&gt;(&lt;/span&gt;ro&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Conditions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Initialized True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ContainersReady True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; PodScheduled True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Volumes:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; default-token-jj2nf:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type: Secret &lt;span class="o"&gt;(&lt;/span&gt;a volume populated by a Secret&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; SecretName: default-token-jj2nf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Optional: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;QoS Class: BestEffort
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node-Selectors: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Tolerations: node.kubernetes.io/not-ready:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; node.kubernetes.io/unreachable:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Reason Age From Message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---- ------ ---- ---- -------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Scheduled &amp;lt;unknown&amp;gt; default-scheduler Successfully assigned default/kubernetes-bootcamp-b4d9f565-4wkhr to minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Pulled 7m23s kubelet, minikube Container image &lt;span class="s2"&gt;&amp;#34;jocatalin/kubernetes-bootcamp:v2&amp;#34;&lt;/span&gt; already present on machine
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Created 7m23s kubelet, minikube Created container kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Started 7m22s kubelet, minikube Started container kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: kubernetes-bootcamp-b4d9f565-fnkvz
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Priority: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node: minikube/192.168.99.109
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Start Time: Tue, &lt;span class="m"&gt;12&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:13:59 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;b4d9f565
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Status: Running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IP: 172.17.0.10
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IPs:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; IP: 172.17.0.10
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Controlled By: ReplicaSet/kubernetes-bootcamp-b4d9f565
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Containers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubernetes-bootcamp:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Container ID: docker://896cc268b334f8241463d9c66af5c7b1accc909c86ea304e95886709b28dedf0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image: jocatalin/kubernetes-bootcamp:v2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image ID: docker-pullable://jocatalin/kubernetes-bootcamp@sha256:fb1a3ced00cecfc1f83f18ab5cd14199e30adc1b49aa4244f5d65ad3f5feb2a5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Host Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; State: Running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Started: Tue, &lt;span class="m"&gt;12&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:14:00 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready: True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Restart Count: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Environment: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Mounts:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; /var/run/secrets/kubernetes.io/serviceaccount from default-token-jj2nf &lt;span class="o"&gt;(&lt;/span&gt;ro&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Conditions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Initialized True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ContainersReady True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; PodScheduled True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Volumes:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; default-token-jj2nf:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type: Secret &lt;span class="o"&gt;(&lt;/span&gt;a volume populated by a Secret&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; SecretName: default-token-jj2nf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Optional: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;QoS Class: BestEffort
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node-Selectors: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Tolerations: node.kubernetes.io/not-ready:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; node.kubernetes.io/unreachable:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Reason Age From Message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---- ------ ---- ---- -------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Scheduled &amp;lt;unknown&amp;gt; default-scheduler Successfully assigned default/kubernetes-bootcamp-b4d9f565-fnkvz to minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Pulled 7m23s kubelet, minikube Container image &lt;span class="s2"&gt;&amp;#34;jocatalin/kubernetes-bootcamp:v2&amp;#34;&lt;/span&gt; already present on machine
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Created 7m23s kubelet, minikube Created container kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Started 7m22s kubelet, minikube Started container kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: kubernetes-bootcamp-b4d9f565-mds8p
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Priority: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node: minikube/192.168.99.109
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Start Time: Tue, &lt;span class="m"&gt;12&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:14:00 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;b4d9f565
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Status: Running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IP: 172.17.0.12
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IPs:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; IP: 172.17.0.12
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Controlled By: ReplicaSet/kubernetes-bootcamp-b4d9f565
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Containers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubernetes-bootcamp:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Container ID: docker://67e064117055eb3050d2fcc7aaeca90fbfa206ce17943c4746103d783e18b4cf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image: jocatalin/kubernetes-bootcamp:v2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image ID: docker-pullable://jocatalin/kubernetes-bootcamp@sha256:fb1a3ced00cecfc1f83f18ab5cd14199e30adc1b49aa4244f5d65ad3f5feb2a5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Host Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; State: Running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Started: Tue, &lt;span class="m"&gt;12&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:14:01 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready: True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Restart Count: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Environment: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Mounts:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; /var/run/secrets/kubernetes.io/serviceaccount from default-token-jj2nf &lt;span class="o"&gt;(&lt;/span&gt;ro&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Conditions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Initialized True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ContainersReady True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; PodScheduled True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Volumes:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; default-token-jj2nf:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type: Secret &lt;span class="o"&gt;(&lt;/span&gt;a volume populated by a Secret&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; SecretName: default-token-jj2nf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Optional: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;QoS Class: BestEffort
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node-Selectors: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Tolerations: node.kubernetes.io/not-ready:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; node.kubernetes.io/unreachable:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Reason Age From Message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---- ------ ---- ---- -------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Scheduled &amp;lt;unknown&amp;gt; default-scheduler Successfully assigned default/kubernetes-bootcamp-b4d9f565-mds8p to minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Pulled 7m21s kubelet, minikube Container image &lt;span class="s2"&gt;&amp;#34;jocatalin/kubernetes-bootcamp:v2&amp;#34;&lt;/span&gt; already present on machine
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Created 7m21s kubelet, minikube Created container kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Started 7m21s kubelet, minikube Started container kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: kubernetes-bootcamp-b4d9f565-z7t47
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Priority: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node: minikube/192.168.99.109
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Start Time: Tue, &lt;span class="m"&gt;12&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:14:01 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;b4d9f565
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Status: Running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IP: 172.17.0.13
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IPs:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; IP: 172.17.0.13
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Controlled By: ReplicaSet/kubernetes-bootcamp-b4d9f565
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Containers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubernetes-bootcamp:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Container ID: docker://e41971ea038199381f5a2ac385e984b1dfc6c7564101b88d104df9d008cb45cb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image: jocatalin/kubernetes-bootcamp:v2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image ID: docker-pullable://jocatalin/kubernetes-bootcamp@sha256:fb1a3ced00cecfc1f83f18ab5cd14199e30adc1b49aa4244f5d65ad3f5feb2a5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Host Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; State: Running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Started: Tue, &lt;span class="m"&gt;12&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:14:02 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready: True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Restart Count: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Environment: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Mounts:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; /var/run/secrets/kubernetes.io/serviceaccount from default-token-jj2nf &lt;span class="o"&gt;(&lt;/span&gt;ro&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Conditions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Initialized True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ContainersReady True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; PodScheduled True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Volumes:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; default-token-jj2nf:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type: Secret &lt;span class="o"&gt;(&lt;/span&gt;a volume populated by a Secret&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; SecretName: default-token-jj2nf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Optional: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;QoS Class: BestEffort
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node-Selectors: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Tolerations: node.kubernetes.io/not-ready:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; node.kubernetes.io/unreachable:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Reason Age From Message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---- ------ ---- ---- -------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Scheduled &amp;lt;unknown&amp;gt; default-scheduler Successfully assigned default/kubernetes-bootcamp-b4d9f565-z7t47 to minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Pulled 7m20s kubelet, minikube Container image &lt;span class="s2"&gt;&amp;#34;jocatalin/kubernetes-bootcamp:v2&amp;#34;&lt;/span&gt; already present on machine
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Created 7m20s kubelet, minikube Created container kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Started 7m20s kubelet, minikube Started container kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 今度はv10を指定してアップデートしてみる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl &lt;span class="nb"&gt;set&lt;/span&gt; image deployments/kubernetes-bootcamp kubernetes-bootcamp&lt;span class="o"&gt;=&lt;/span&gt;gcr.io/google-samples/kubernetes-bootcamp:v10
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps/kubernetes-bootcamp image updated
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Deploymentの一覧を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Pod数がおかしいことになっている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get deployments
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY UP-TO-DATE AVAILABLE AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp 3/4 &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; 5d23h
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podの一覧を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Statusがおかしいものがある&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-6b4c55d8fc-2rb26 0/1 ImagePullBackOff &lt;span class="m"&gt;0&lt;/span&gt; 81s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-6b4c55d8fc-z9gn7 0/1 ImagePullBackOff &lt;span class="m"&gt;0&lt;/span&gt; 81s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-b4d9f565-4wkhr 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 11m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-b4d9f565-fnkvz 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 11m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-b4d9f565-mds8p 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 11m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podの詳細を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Eventsを見るとv10が見つからずエラーとなっている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl describe pods
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: kubernetes-bootcamp-6b4c55d8fc-2rb26
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Priority: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node: minikube/192.168.99.109
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Start Time: Tue, &lt;span class="m"&gt;12&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:23:59 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;6b4c55d8fc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Status: Pending
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IP: 172.17.0.7
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IPs:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; IP: 172.17.0.7
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Controlled By: ReplicaSet/kubernetes-bootcamp-6b4c55d8fc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Containers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubernetes-bootcamp:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Container ID:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image: gcr.io/google-samples/kubernetes-bootcamp:v10
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image ID:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Host Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; State: Waiting
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Reason: ImagePullBackOff
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready: False
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Restart Count: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Environment: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Mounts:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; /var/run/secrets/kubernetes.io/serviceaccount from default-token-jj2nf &lt;span class="o"&gt;(&lt;/span&gt;ro&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Conditions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Initialized True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready False
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ContainersReady False
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; PodScheduled True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Volumes:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; default-token-jj2nf:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type: Secret &lt;span class="o"&gt;(&lt;/span&gt;a volume populated by a Secret&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; SecretName: default-token-jj2nf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Optional: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;QoS Class: BestEffort
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node-Selectors: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Tolerations: node.kubernetes.io/not-ready:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; node.kubernetes.io/unreachable:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Reason Age From Message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---- ------ ---- ---- -------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Scheduled &amp;lt;unknown&amp;gt; default-scheduler Successfully assigned default/kubernetes-bootcamp-6b4c55d8fc-2rb26 to minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Pulling 41s &lt;span class="o"&gt;(&lt;/span&gt;x4 over 2m18s&lt;span class="o"&gt;)&lt;/span&gt; kubelet, minikube Pulling image &lt;span class="s2"&gt;&amp;#34;gcr.io/google-samples/kubernetes-bootcamp:v10&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Warning Failed 40s &lt;span class="o"&gt;(&lt;/span&gt;x4 over 2m16s&lt;span class="o"&gt;)&lt;/span&gt; kubelet, minikube Failed to pull image &lt;span class="s2"&gt;&amp;#34;gcr.io/google-samples/kubernetes-bootcamp:v10&amp;#34;&lt;/span&gt;: rpc error: &lt;span class="nv"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; Unknown &lt;span class="nv"&gt;desc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; Error response from daemon: manifest &lt;span class="k"&gt;for&lt;/span&gt; gcr.io/google-samples/kubernetes-bootcamp:v10 not found
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Warning Failed 40s &lt;span class="o"&gt;(&lt;/span&gt;x4 over 2m16s&lt;span class="o"&gt;)&lt;/span&gt; kubelet, minikube Error: ErrImagePull
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Warning Failed 29s &lt;span class="o"&gt;(&lt;/span&gt;x6 over 2m16s&lt;span class="o"&gt;)&lt;/span&gt; kubelet, minikube Error: ImagePullBackOff
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal BackOff 17s &lt;span class="o"&gt;(&lt;/span&gt;x7 over 2m16s&lt;span class="o"&gt;)&lt;/span&gt; kubelet, minikube Back-off pulling image &lt;span class="s2"&gt;&amp;#34;gcr.io/google-samples/kubernetes-bootcamp:v10&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: kubernetes-bootcamp-6b4c55d8fc-z9gn7
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Priority: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node: minikube/192.168.99.109
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Start Time: Tue, &lt;span class="m"&gt;12&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:23:59 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;6b4c55d8fc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Status: Pending
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IP: 172.17.0.6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IPs:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; IP: 172.17.0.6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Controlled By: ReplicaSet/kubernetes-bootcamp-6b4c55d8fc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Containers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubernetes-bootcamp:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Container ID:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image: gcr.io/google-samples/kubernetes-bootcamp:v10
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image ID:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Host Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; State: Waiting
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Reason: ImagePullBackOff
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready: False
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Restart Count: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Environment: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Mounts:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; /var/run/secrets/kubernetes.io/serviceaccount from default-token-jj2nf &lt;span class="o"&gt;(&lt;/span&gt;ro&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Conditions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Initialized True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready False
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ContainersReady False
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; PodScheduled True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Volumes:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; default-token-jj2nf:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type: Secret &lt;span class="o"&gt;(&lt;/span&gt;a volume populated by a Secret&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; SecretName: default-token-jj2nf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Optional: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;QoS Class: BestEffort
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node-Selectors: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Tolerations: node.kubernetes.io/not-ready:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; node.kubernetes.io/unreachable:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Reason Age From Message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---- ------ ---- ---- -------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Scheduled &amp;lt;unknown&amp;gt; default-scheduler Successfully assigned default/kubernetes-bootcamp-6b4c55d8fc-z9gn7 to minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal BackOff 61s &lt;span class="o"&gt;(&lt;/span&gt;x6 over 2m17s&lt;span class="o"&gt;)&lt;/span&gt; kubelet, minikube Back-off pulling image &lt;span class="s2"&gt;&amp;#34;gcr.io/google-samples/kubernetes-bootcamp:v10&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Pulling 46s &lt;span class="o"&gt;(&lt;/span&gt;x4 over 2m18s&lt;span class="o"&gt;)&lt;/span&gt; kubelet, minikube Pulling image &lt;span class="s2"&gt;&amp;#34;gcr.io/google-samples/kubernetes-bootcamp:v10&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Warning Failed 45s &lt;span class="o"&gt;(&lt;/span&gt;x4 over 2m17s&lt;span class="o"&gt;)&lt;/span&gt; kubelet, minikube Failed to pull image &lt;span class="s2"&gt;&amp;#34;gcr.io/google-samples/kubernetes-bootcamp:v10&amp;#34;&lt;/span&gt;: rpc error: &lt;span class="nv"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; Unknown &lt;span class="nv"&gt;desc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; Error response from daemon: manifest &lt;span class="k"&gt;for&lt;/span&gt; gcr.io/google-samples/kubernetes-bootcamp:v10 not found
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Warning Failed 45s &lt;span class="o"&gt;(&lt;/span&gt;x4 over 2m17s&lt;span class="o"&gt;)&lt;/span&gt; kubelet, minikube Error: ErrImagePull
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Warning Failed 31s &lt;span class="o"&gt;(&lt;/span&gt;x7 over 2m17s&lt;span class="o"&gt;)&lt;/span&gt; kubelet, minikube Error: ImagePullBackOff
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: kubernetes-bootcamp-b4d9f565-4wkhr
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Priority: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node: minikube/192.168.99.109
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Start Time: Tue, &lt;span class="m"&gt;12&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:13:59 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;b4d9f565
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Status: Running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IP: 172.17.0.11
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IPs:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; IP: 172.17.0.11
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Controlled By: ReplicaSet/kubernetes-bootcamp-b4d9f565
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Containers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubernetes-bootcamp:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Container ID: docker://c8bebac0609ee166972beae7437c71733955bfde4107708d28fe3606d68e44d6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image: jocatalin/kubernetes-bootcamp:v2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image ID: docker-pullable://jocatalin/kubernetes-bootcamp@sha256:fb1a3ced00cecfc1f83f18ab5cd14199e30adc1b49aa4244f5d65ad3f5feb2a5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Host Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; State: Running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Started: Tue, &lt;span class="m"&gt;12&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:14:00 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready: True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Restart Count: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Environment: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Mounts:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; /var/run/secrets/kubernetes.io/serviceaccount from default-token-jj2nf &lt;span class="o"&gt;(&lt;/span&gt;ro&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Conditions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Initialized True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ContainersReady True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; PodScheduled True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Volumes:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; default-token-jj2nf:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type: Secret &lt;span class="o"&gt;(&lt;/span&gt;a volume populated by a Secret&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; SecretName: default-token-jj2nf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Optional: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;QoS Class: BestEffort
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node-Selectors: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Tolerations: node.kubernetes.io/not-ready:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; node.kubernetes.io/unreachable:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Reason Age From Message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---- ------ ---- ---- -------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Scheduled &amp;lt;unknown&amp;gt; default-scheduler Successfully assigned default/kubernetes-bootcamp-b4d9f565-4wkhr to minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Pulled 12m kubelet, minikube Container image &lt;span class="s2"&gt;&amp;#34;jocatalin/kubernetes-bootcamp:v2&amp;#34;&lt;/span&gt; already present on machine
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Created 12m kubelet, minikube Created container kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Started 12m kubelet, minikube Started container kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: kubernetes-bootcamp-b4d9f565-fnkvz
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Priority: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node: minikube/192.168.99.109
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Start Time: Tue, &lt;span class="m"&gt;12&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:13:59 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;b4d9f565
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Status: Running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IP: 172.17.0.10
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IPs:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; IP: 172.17.0.10
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Controlled By: ReplicaSet/kubernetes-bootcamp-b4d9f565
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Containers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubernetes-bootcamp:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Container ID: docker://896cc268b334f8241463d9c66af5c7b1accc909c86ea304e95886709b28dedf0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image: jocatalin/kubernetes-bootcamp:v2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image ID: docker-pullable://jocatalin/kubernetes-bootcamp@sha256:fb1a3ced00cecfc1f83f18ab5cd14199e30adc1b49aa4244f5d65ad3f5feb2a5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Host Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; State: Running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Started: Tue, &lt;span class="m"&gt;12&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:14:00 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready: True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Restart Count: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Environment: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Mounts:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; /var/run/secrets/kubernetes.io/serviceaccount from default-token-jj2nf &lt;span class="o"&gt;(&lt;/span&gt;ro&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Conditions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Initialized True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ContainersReady True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; PodScheduled True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Volumes:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; default-token-jj2nf:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type: Secret &lt;span class="o"&gt;(&lt;/span&gt;a volume populated by a Secret&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; SecretName: default-token-jj2nf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Optional: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;QoS Class: BestEffort
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node-Selectors: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Tolerations: node.kubernetes.io/not-ready:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; node.kubernetes.io/unreachable:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Reason Age From Message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---- ------ ---- ---- -------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Scheduled &amp;lt;unknown&amp;gt; default-scheduler Successfully assigned default/kubernetes-bootcamp-b4d9f565-fnkvz to minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Pulled 12m kubelet, minikube Container image &lt;span class="s2"&gt;&amp;#34;jocatalin/kubernetes-bootcamp:v2&amp;#34;&lt;/span&gt; already present on machine
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Created 12m kubelet, minikube Created container kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Started 12m kubelet, minikube Started container kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: kubernetes-bootcamp-b4d9f565-mds8p
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Priority: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node: minikube/192.168.99.109
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Start Time: Tue, &lt;span class="m"&gt;12&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:14:00 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;b4d9f565
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Status: Running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IP: 172.17.0.12
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IPs:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; IP: 172.17.0.12
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Controlled By: ReplicaSet/kubernetes-bootcamp-b4d9f565
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Containers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubernetes-bootcamp:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Container ID: docker://67e064117055eb3050d2fcc7aaeca90fbfa206ce17943c4746103d783e18b4cf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image: jocatalin/kubernetes-bootcamp:v2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image ID: docker-pullable://jocatalin/kubernetes-bootcamp@sha256:fb1a3ced00cecfc1f83f18ab5cd14199e30adc1b49aa4244f5d65ad3f5feb2a5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Host Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; State: Running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Started: Tue, &lt;span class="m"&gt;12&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:14:01 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready: True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Restart Count: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Environment: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Mounts:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; /var/run/secrets/kubernetes.io/serviceaccount from default-token-jj2nf &lt;span class="o"&gt;(&lt;/span&gt;ro&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Conditions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Initialized True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ContainersReady True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; PodScheduled True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Volumes:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; default-token-jj2nf:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type: Secret &lt;span class="o"&gt;(&lt;/span&gt;a volume populated by a Secret&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; SecretName: default-token-jj2nf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Optional: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;QoS Class: BestEffort
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node-Selectors: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Tolerations: node.kubernetes.io/not-ready:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; node.kubernetes.io/unreachable:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Reason Age From Message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---- ------ ---- ---- -------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Scheduled &amp;lt;unknown&amp;gt; default-scheduler Successfully assigned default/kubernetes-bootcamp-b4d9f565-mds8p to minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Pulled 12m kubelet, minikube Container image &lt;span class="s2"&gt;&amp;#34;jocatalin/kubernetes-bootcamp:v2&amp;#34;&lt;/span&gt; already present on machine
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Created 12m kubelet, minikube Created container kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Started 12m kubelet, minikube Started container kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 直前のローリングアップデートを巻き戻す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl rollout undo deployments/kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps/kubernetes-bootcamp rolled back
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podの一覧を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Statusが正常に戻っている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-b4d9f565-4wkhr 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 13m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-b4d9f565-b9t5c 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 4s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-b4d9f565-fnkvz 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 13m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes-bootcamp-b4d9f565-mds8p 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 13m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podの詳細を確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl describe pods
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: kubernetes-bootcamp-b4d9f565-4wkhr
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Priority: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node: minikube/192.168.99.109
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Start Time: Tue, &lt;span class="m"&gt;12&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:13:59 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;b4d9f565
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Status: Running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IP: 172.17.0.11
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IPs:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; IP: 172.17.0.11
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Controlled By: ReplicaSet/kubernetes-bootcamp-b4d9f565
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Containers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubernetes-bootcamp:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Container ID: docker://c8bebac0609ee166972beae7437c71733955bfde4107708d28fe3606d68e44d6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image: jocatalin/kubernetes-bootcamp:v2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image ID: docker-pullable://jocatalin/kubernetes-bootcamp@sha256:fb1a3ced00cecfc1f83f18ab5cd14199e30adc1b49aa4244f5d65ad3f5feb2a5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Host Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; State: Running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Started: Tue, &lt;span class="m"&gt;12&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:14:00 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready: True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Restart Count: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Environment: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Mounts:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; /var/run/secrets/kubernetes.io/serviceaccount from default-token-jj2nf &lt;span class="o"&gt;(&lt;/span&gt;ro&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Conditions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Initialized True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ContainersReady True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; PodScheduled True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Volumes:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; default-token-jj2nf:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type: Secret &lt;span class="o"&gt;(&lt;/span&gt;a volume populated by a Secret&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; SecretName: default-token-jj2nf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Optional: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;QoS Class: BestEffort
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node-Selectors: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Tolerations: node.kubernetes.io/not-ready:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; node.kubernetes.io/unreachable:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Reason Age From Message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---- ------ ---- ---- -------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Scheduled &amp;lt;unknown&amp;gt; default-scheduler Successfully assigned default/kubernetes-bootcamp-b4d9f565-4wkhr to minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Pulled 16m kubelet, minikube Container image &lt;span class="s2"&gt;&amp;#34;jocatalin/kubernetes-bootcamp:v2&amp;#34;&lt;/span&gt; already present on machine
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Created 16m kubelet, minikube Created container kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Started 16m kubelet, minikube Started container kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: kubernetes-bootcamp-b4d9f565-b9t5c
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Priority: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node: minikube/192.168.99.109
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Start Time: Tue, &lt;span class="m"&gt;12&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:27:35 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;b4d9f565
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Status: Running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IP: 172.17.0.8
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IPs:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; IP: 172.17.0.8
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Controlled By: ReplicaSet/kubernetes-bootcamp-b4d9f565
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Containers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubernetes-bootcamp:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Container ID: docker://644cf4f577f0a12f4e43d2c8ab98ab587cb231f5f9dbd41a48885c4255e146cb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image: jocatalin/kubernetes-bootcamp:v2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image ID: docker-pullable://jocatalin/kubernetes-bootcamp@sha256:fb1a3ced00cecfc1f83f18ab5cd14199e30adc1b49aa4244f5d65ad3f5feb2a5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Host Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; State: Running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Started: Tue, &lt;span class="m"&gt;12&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:27:36 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready: True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Restart Count: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Environment: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Mounts:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; /var/run/secrets/kubernetes.io/serviceaccount from default-token-jj2nf &lt;span class="o"&gt;(&lt;/span&gt;ro&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Conditions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Initialized True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ContainersReady True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; PodScheduled True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Volumes:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; default-token-jj2nf:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type: Secret &lt;span class="o"&gt;(&lt;/span&gt;a volume populated by a Secret&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; SecretName: default-token-jj2nf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Optional: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;QoS Class: BestEffort
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node-Selectors: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Tolerations: node.kubernetes.io/not-ready:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; node.kubernetes.io/unreachable:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Reason Age From Message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---- ------ ---- ---- -------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Scheduled &amp;lt;unknown&amp;gt; default-scheduler Successfully assigned default/kubernetes-bootcamp-b4d9f565-b9t5c to minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Pulled 2m46s kubelet, minikube Container image &lt;span class="s2"&gt;&amp;#34;jocatalin/kubernetes-bootcamp:v2&amp;#34;&lt;/span&gt; already present on machine
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Created 2m46s kubelet, minikube Created container kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Started 2m46s kubelet, minikube Started container kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: kubernetes-bootcamp-b4d9f565-fnkvz
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Priority: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node: minikube/192.168.99.109
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Start Time: Tue, &lt;span class="m"&gt;12&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:13:59 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;b4d9f565
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Status: Running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IP: 172.17.0.10
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IPs:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; IP: 172.17.0.10
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Controlled By: ReplicaSet/kubernetes-bootcamp-b4d9f565
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Containers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubernetes-bootcamp:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Container ID: docker://896cc268b334f8241463d9c66af5c7b1accc909c86ea304e95886709b28dedf0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image: jocatalin/kubernetes-bootcamp:v2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image ID: docker-pullable://jocatalin/kubernetes-bootcamp@sha256:fb1a3ced00cecfc1f83f18ab5cd14199e30adc1b49aa4244f5d65ad3f5feb2a5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Host Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; State: Running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Started: Tue, &lt;span class="m"&gt;12&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:14:00 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready: True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Restart Count: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Environment: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Mounts:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; /var/run/secrets/kubernetes.io/serviceaccount from default-token-jj2nf &lt;span class="o"&gt;(&lt;/span&gt;ro&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Conditions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Initialized True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ContainersReady True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; PodScheduled True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Volumes:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; default-token-jj2nf:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type: Secret &lt;span class="o"&gt;(&lt;/span&gt;a volume populated by a Secret&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; SecretName: default-token-jj2nf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Optional: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;QoS Class: BestEffort
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node-Selectors: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Tolerations: node.kubernetes.io/not-ready:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; node.kubernetes.io/unreachable:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Reason Age From Message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---- ------ ---- ---- -------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Scheduled &amp;lt;unknown&amp;gt; default-scheduler Successfully assigned default/kubernetes-bootcamp-b4d9f565-fnkvz to minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Pulled 16m kubelet, minikube Container image &lt;span class="s2"&gt;&amp;#34;jocatalin/kubernetes-bootcamp:v2&amp;#34;&lt;/span&gt; already present on machine
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Created 16m kubelet, minikube Created container kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Started 16m kubelet, minikube Started container kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: kubernetes-bootcamp-b4d9f565-mds8p
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Namespace: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Priority: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node: minikube/192.168.99.109
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Start Time: Tue, &lt;span class="m"&gt;12&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:14:00 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Labels: &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; pod-template-hash&lt;span class="o"&gt;=&lt;/span&gt;b4d9f565
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Annotations: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Status: Running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IP: 172.17.0.12
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IPs:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; IP: 172.17.0.12
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Controlled By: ReplicaSet/kubernetes-bootcamp-b4d9f565
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Containers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubernetes-bootcamp:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Container ID: docker://67e064117055eb3050d2fcc7aaeca90fbfa206ce17943c4746103d783e18b4cf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image: jocatalin/kubernetes-bootcamp:v2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image ID: docker-pullable://jocatalin/kubernetes-bootcamp@sha256:fb1a3ced00cecfc1f83f18ab5cd14199e30adc1b49aa4244f5d65ad3f5feb2a5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Host Port: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; State: Running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Started: Tue, &lt;span class="m"&gt;12&lt;/span&gt; Nov &lt;span class="m"&gt;2019&lt;/span&gt; 23:14:01 +0900
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready: True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Restart Count: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Environment: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Mounts:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; /var/run/secrets/kubernetes.io/serviceaccount from default-token-jj2nf &lt;span class="o"&gt;(&lt;/span&gt;ro&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Conditions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Initialized True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Ready True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ContainersReady True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; PodScheduled True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Volumes:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; default-token-jj2nf:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type: Secret &lt;span class="o"&gt;(&lt;/span&gt;a volume populated by a Secret&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; SecretName: default-token-jj2nf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Optional: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;QoS Class: BestEffort
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node-Selectors: &amp;lt;none&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Tolerations: node.kubernetes.io/not-ready:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; node.kubernetes.io/unreachable:NoExecute &lt;span class="k"&gt;for&lt;/span&gt; 300s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Events:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Type Reason Age From Message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---- ------ ---- ---- -------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Scheduled &amp;lt;unknown&amp;gt; default-scheduler Successfully assigned default/kubernetes-bootcamp-b4d9f565-mds8p to minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Pulled 16m kubelet, minikube Container image &lt;span class="s2"&gt;&amp;#34;jocatalin/kubernetes-bootcamp:v2&amp;#34;&lt;/span&gt; already present on machine
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Created 16m kubelet, minikube Created container kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Normal Started 16m kubelet, minikube Started container kubernetes-bootcamp
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;おわり.&lt;br&gt;
自分で絵を書くのがめんどくさかったけどなんとなく理解できた. 気がする.&lt;/p&gt;</description></item><item><title>Hello Minikubeする</title><link>https://blog.uzimihsr.com/post/2019-10-28-hello-minikube/</link><pubDate>Mon, 28 Oct 2019 21:56:44 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2019-10-28-hello-minikube/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2019-10-28-hello-minikube/2019-10-28-sotochan.jpg" alt="Featured image of post Hello Minikubeする" /&gt;&lt;h2 id="こんにちはminikube"&gt;こんにちはMinikube
&lt;/h2&gt;&lt;p&gt;Minikubeをインストールしたので, 公式のチュートリアルをやってみた.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="動作環境"&gt;動作環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;masOS Mojave 10.14&lt;/li&gt;
&lt;li&gt;Minikube v1.5.0&lt;/li&gt;
&lt;li&gt;VirtualBox 6.0.12&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;p&gt;公式の&lt;a class="link" href="https://kubernetes.io/docs/tutorials/hello-minikube/" target="_blank" rel="noopener"
 &gt;Hello Minikube&lt;/a&gt;の内容.&lt;br&gt;
&lt;a class="link" href="https://kubernetes.io/ja/docs/tutorials/hello-minikube/" target="_blank" rel="noopener"
 &gt;日本語版&lt;/a&gt;もあるので今回はいちいち訳さずに気楽にやってみる.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#minikube%e3%82%af%e3%83%a9%e3%82%b9%e3%82%bf%e3%81%ae%e4%bd%9c%e6%88%90" &gt;Minikubeクラスタの作成&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#deployment%e3%81%ae%e4%bd%9c%e6%88%90" &gt;Deploymentの作成&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#service%e3%81%ae%e4%bd%9c%e6%88%90" &gt;Serviceの作成&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%a2%e3%83%89%e3%82%aa%e3%83%b3%e3%81%ae%e6%9c%89%e5%8a%b9%e5%8c%96" &gt;アドオンの有効化&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%a2%e3%83%83%e3%83%97" &gt;クリーンアップ&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="minikubeクラスタの作成"&gt;Minikubeクラスタの作成
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://kubernetes.io/docs/tutorials/hello-minikube/#create-a-minikube-cluster" target="_blank" rel="noopener"
 &gt;https://kubernetes.io/docs/tutorials/hello-minikube/#create-a-minikube-cluster&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Minikube&lt;/code&gt;を起動して, dashboardとやらを開いてみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Minikubeを起動する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ minikube start --vm-driver&lt;span class="o"&gt;=&lt;/span&gt;virtualbox
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;😄 minikube v1.5.0 on Darwin 10.14
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🔥 Creating virtualbox VM &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;CPUs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2, &lt;span class="nv"&gt;Memory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2000MB, &lt;span class="nv"&gt;Disk&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;20000MB&lt;span class="o"&gt;)&lt;/span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🐳 Preparing Kubernetes v1.16.2 on Docker 18.09.9 ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🚜 Pulling images ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🚀 Launching Kubernetes ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;⌛ Waiting &lt;span class="k"&gt;for&lt;/span&gt;: apiserver proxy etcd scheduler controller dns
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🏄 Done! kubectl is now configured to use &lt;span class="s2"&gt;&amp;#34;minikube&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;⚠️ /usr/local/bin/kubectl is version 1.14.6, and is incompatible with Kubernetes 1.16.2. You will need to update /usr/local/bin/kubectl or use &lt;span class="s1"&gt;&amp;#39;minikube kubectl&amp;#39;&lt;/span&gt; to connect with this cluster
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# dashboardを起動する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ minikube dashboard
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🔌 Enabling dashboard ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🤔 Verifying dashboard health ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🚀 Launching proxy ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🤔 Verifying proxy health ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🎉 Opening http://127.0.0.1:53295/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/ in your default browser...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;勝手にブラウザが動いてdashboardの画面が開く.&lt;/p&gt;
&lt;p&gt;&lt;img alt="dashboard画面" class="gallery-image" data-flex-basis="403px" data-flex-grow="168" height="1713" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-10-28-hello-minikube/2019-10-28-sc01.png" srcset="https://blog.uzimihsr.com/post/2019-10-28-hello-minikube/2019-10-28-sc01_hu_b4ba4cc3fc3edbea.png 800w, https://blog.uzimihsr.com/post/2019-10-28-hello-minikube/2019-10-28-sc01_hu_1d23f4fc7d166a99.png 1600w, https://blog.uzimihsr.com/post/2019-10-28-hello-minikube/2019-10-28-sc01_hu_6f6f6bf4fd6d07e7.png 2400w, https://blog.uzimihsr.com/post/2019-10-28-hello-minikube/2019-10-28-sc01.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;なんかいろいろ見られそうで便利そう(小並感)&lt;/p&gt;
&lt;p&gt;バックグラウンド起動にできないのめんどい&amp;hellip;&lt;br&gt;
とりあえず以下はターミナルの別タブでやっていく.&lt;/p&gt;
&lt;h2 id="deploymentの作成"&gt;Deploymentの作成
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://kubernetes.io/docs/tutorials/hello-minikube/#create-a-deployment" target="_blank" rel="noopener"
 &gt;https://kubernetes.io/docs/tutorials/hello-minikube/#create-a-deployment&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Deployment&lt;/code&gt;を作る.&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2019-10-13-docker-03/" target="_blank" rel="noopener"
 &gt;Docker Quickstart&lt;/a&gt;でちょっと触ったけど&lt;code&gt;Deployment&lt;/code&gt;ってなんだったっけ&amp;hellip;?(すっとぼけ)&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;KubernetesのPod は、コンテナの管理やネットワーキングの目的でまとめられた、1つ以上のコンテナのグループです。このチュートリアルのPodがもつコンテナは1つのみです。Kubernetesの Deployment はPodの状態を確認し、Podのコンテナが停止した場合には再起動します。DeploymentはPodの作成やスケールを管理するために推奨される方法(手段)です。&lt;br&gt;
(&lt;a class="link" href="https://kubernetes.io/ja/docs/tutorials/hello-minikube/#deployment%E3%81%AE%E4%BD%9C%E6%88%90" target="_blank" rel="noopener"
 &gt;https://kubernetes.io/ja/docs/tutorials/hello-minikube/#deployment%E3%81%AE%E4%BD%9C%E6%88%90&lt;/a&gt; より引用)&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;なるほど. なんかコンテナがいくつか集まったのが&lt;code&gt;Pod&lt;/code&gt;で, 複数台の&lt;code&gt;Pod&lt;/code&gt;をいい感じに管理するのが&lt;code&gt;Deployment&lt;/code&gt;だったはず.&lt;/p&gt;
&lt;p&gt;今回は以下のファイルで作成された&lt;code&gt;Docker image&lt;/code&gt;を使って&lt;code&gt;Deployment&lt;/code&gt;を作成する.&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;server.js&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;http&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;handleRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Received request for URL: &amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Hello World!&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;www&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handleRequest&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;www&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="link" href="https://github.com/kubernetes/website/blob/master/content/en/examples/minikube/server.js" target="_blank" rel="noopener"
 &gt;https://github.com/kubernetes/website/blob/master/content/en/examples/minikube/server.js&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;Dockerfile&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-docker" data-lang="docker"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;node:6.14.2&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;8080&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; server.js .&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CMD&lt;/span&gt; node server.js&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="link" href="https://github.com/kubernetes/website/blob/master/content/en/examples/minikube/Dockerfile" target="_blank" rel="noopener"
 &gt;https://github.com/kubernetes/website/blob/master/content/en/examples/minikube/Dockerfile&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/details&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Deployment(hello-node)を作成する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create deployment hello-node --image&lt;span class="o"&gt;=&lt;/span&gt;gcr.io/hello-minikube-zero-install/hello-node
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps/hello-node created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Deploymentの一覧を表示する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get deployments
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY UP-TO-DATE AVAILABLE AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hello-node 1/1 &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 40s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podの一覧を表示する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hello-node-7676b5fb8d-x7l5t 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 88s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# cluster eventを表示する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get events
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;LAST SEEN TYPE REASON OBJECT MESSAGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;unknown&amp;gt; Normal Scheduled pod/hello-node-7676b5fb8d-x7l5t Successfully assigned default/hello-node-7676b5fb8d-x7l5t to minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3m17s Normal Pulling pod/hello-node-7676b5fb8d-x7l5t Pulling image &lt;span class="s2"&gt;&amp;#34;gcr.io/hello-minikube-zero-install/hello-node&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2m38s Normal Pulled pod/hello-node-7676b5fb8d-x7l5t Successfully pulled image &lt;span class="s2"&gt;&amp;#34;gcr.io/hello-minikube-zero-install/hello-node&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2m38s Normal Created pod/hello-node-7676b5fb8d-x7l5t Created container hello-node
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2m38s Normal Started pod/hello-node-7676b5fb8d-x7l5t Started container hello-node
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3m17s Normal SuccessfulCreate replicaset/hello-node-7676b5fb8d Created pod: hello-node-7676b5fb8d-x7l5t
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3m17s Normal ScalingReplicaSet deployment/hello-node Scaled up replica &lt;span class="nb"&gt;set&lt;/span&gt; hello-node-7676b5fb8d to &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# kubectlの設定を表示する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl config view
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apiVersion: v1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;clusters:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- cluster:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; certificate-authority-data: DATA+OMITTED
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; server: https://kubernetes.docker.internal:6443
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: docker-desktop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- cluster:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; certificate-authority: /Users/uzimihsr/.minikube/ca.crt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; server: https://192.168.99.104:8443
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;contexts:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- context:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cluster: docker-desktop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; user: docker-desktop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: docker-desktop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- context:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cluster: docker-desktop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; user: docker-desktop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: docker-for-desktop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- context:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cluster: minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; user: minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name: minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;current-context: minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kind: Config
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;preferences: &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;users:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- name: docker-desktop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; user:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; client-certificate-data: REDACTED
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; client-key-data: REDACTED
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- name: minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; user:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; client-certificate: /Users/uzimihsr/.minikube/client.crt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; client-key: /Users/uzimihsr/.minikube/client.key
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;kubectl get events&lt;/code&gt;は初めて打った. 内部で行われている操作がわかって便利そう.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;kubectl&lt;/code&gt;の設定はDocker for Desktopのぶんの設定も表示しているっぽい.&lt;/p&gt;
&lt;p&gt;以上で&lt;code&gt;Deployment&lt;/code&gt;の作成ができた.&lt;/p&gt;
&lt;h2 id="serviceの作成"&gt;Serviceの作成
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://kubernetes.io/docs/tutorials/hello-minikube/#create-a-service" target="_blank" rel="noopener"
 &gt;https://kubernetes.io/docs/tutorials/hello-minikube/#create-a-service&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Service&lt;/code&gt;を作る.&lt;/p&gt;
&lt;p&gt;ってか&lt;code&gt;Service&lt;/code&gt;ってなんだっけ?(すっとぼけ)(2回目)&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;通常、PodはKubernetesクラスタ内部のIPアドレスからのみアクセスすることができます。hello-nodeコンテナをKubernetesの仮想ネットワークの外部からアクセスするためには、KubernetesのServiceとしてポッドを公開する必要があります。&lt;br&gt;
(&lt;a class="link" href="https://kubernetes.io/ja/docs/tutorials/hello-minikube/#service%E3%81%AE%E4%BD%9C%E6%88%90" target="_blank" rel="noopener"
 &gt;https://kubernetes.io/ja/docs/tutorials/hello-minikube/#service%E3%81%AE%E4%BD%9C%E6%88%90&lt;/a&gt; より引用)&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;ほーん.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Pod&lt;/code&gt;のネットワークまわりの設定をするのが&lt;code&gt;Service&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podをインターネット(外部)からアクセス可能にするためのServiceを作成する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl expose deployment hello-node --type&lt;span class="o"&gt;=&lt;/span&gt;LoadBalancer --port&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/hello-node exposed
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Serviceの一覧を表示する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get services
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hello-node LoadBalancer 10.105.200.193 &amp;lt;pending&amp;gt; 8080:32547/TCP 71s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes ClusterIP 10.96.0.1 &amp;lt;none&amp;gt; 443/TCP 101m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Service(hello-node)にアクセスする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ minikube service hello-node
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt;-----------&lt;span class="p"&gt;|&lt;/span&gt;------------&lt;span class="p"&gt;|&lt;/span&gt;-------------&lt;span class="p"&gt;|&lt;/span&gt;-----------------------------&lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; NAMESPACE &lt;span class="p"&gt;|&lt;/span&gt; NAME &lt;span class="p"&gt;|&lt;/span&gt; TARGET PORT &lt;span class="p"&gt;|&lt;/span&gt; URL &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt;-----------&lt;span class="p"&gt;|&lt;/span&gt;------------&lt;span class="p"&gt;|&lt;/span&gt;-------------&lt;span class="p"&gt;|&lt;/span&gt;-----------------------------&lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; default &lt;span class="p"&gt;|&lt;/span&gt; hello-node &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; http://192.168.99.104:32547 &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt;-----------&lt;span class="p"&gt;|&lt;/span&gt;------------&lt;span class="p"&gt;|&lt;/span&gt;-------------&lt;span class="p"&gt;|&lt;/span&gt;-----------------------------&lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🎉 Opening kubernetes service default/hello-node in default browser...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;勝手にブラウザが開き, &lt;strong&gt;server.js&lt;/strong&gt; で定義されたHello World!の画面が表示される.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Hello World!" class="gallery-image" data-flex-basis="1063px" data-flex-grow="443" height="230" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-10-28-hello-minikube/2019-10-28-sc02.png" srcset="https://blog.uzimihsr.com/post/2019-10-28-hello-minikube/2019-10-28-sc02_hu_a7e6873eaac26cb6.png 800w, https://blog.uzimihsr.com/post/2019-10-28-hello-minikube/2019-10-28-sc02.png 1019w" width="1019"&gt;&lt;/p&gt;
&lt;p&gt;以上で&lt;code&gt;Service&lt;/code&gt;の作成と&lt;code&gt;Pod&lt;/code&gt;内のコンテナへのアクセスができた.&lt;/p&gt;
&lt;p&gt;ちなみに最初に開いたdashboardを見ると作成したリソースの情報が見られるようになっている. 便利.&lt;/p&gt;
&lt;p&gt;&lt;img alt="dashboard" class="gallery-image" data-flex-basis="421px" data-flex-grow="175" height="1638" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-10-28-hello-minikube/2019-10-28-sc03.png" srcset="https://blog.uzimihsr.com/post/2019-10-28-hello-minikube/2019-10-28-sc03_hu_155e2702ba384a28.png 800w, https://blog.uzimihsr.com/post/2019-10-28-hello-minikube/2019-10-28-sc03_hu_7be246d32441615c.png 1600w, https://blog.uzimihsr.com/post/2019-10-28-hello-minikube/2019-10-28-sc03_hu_2e55ba1efb0cac0e.png 2400w, https://blog.uzimihsr.com/post/2019-10-28-hello-minikube/2019-10-28-sc03.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;h2 id="アドオンの有効化"&gt;アドオンの有効化
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://kubernetes.io/docs/tutorials/hello-minikube/#enable-addons" target="_blank" rel="noopener"
 &gt;https://kubernetes.io/docs/tutorials/hello-minikube/#enable-addons&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Minikube&lt;/code&gt;に元々入ってるアドオンが使えるらしいので触ってみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 利用可能なアドオンの一覧を表示する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ minikube addons list
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- addon-manager: enabled
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- dashboard: enabled
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- default-storageclass: enabled
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- efk: disabled
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- freshpod: disabled
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- gvisor: disabled
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- heapster: disabled
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- helm-tiller: disabled
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- ingress: disabled
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- ingress-dns: disabled
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- logviewer: disabled
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- metrics-server: disabled
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- nvidia-driver-installer: disabled
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- nvidia-gpu-device-plugin: disabled
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- registry: disabled
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- registry-creds: disabled
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- storage-provisioner: enabled
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- storage-provisioner-gluster: disabled
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 試しにheapster(監視ツール)を使ってみる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# が, その前にkube-system(namespace)のPodとServiceの一覧を表示する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pod,svc -n kube-system
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/coredns-5644d7b6d9-d2vxs 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 115m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/coredns-5644d7b6d9-rhr9r 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 115m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/etcd-minikube 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 114m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/kube-addon-manager-minikube 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 116m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/kube-apiserver-minikube 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 114m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/kube-controller-manager-minikube 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 114m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/kube-proxy-f45zs 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 115m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/kube-scheduler-minikube 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 114m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/storage-provisioner 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 115m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/kube-dns ClusterIP 10.96.0.10 &amp;lt;none&amp;gt; 53/UDP,53/TCP,9153/TCP 116m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# heapsterを有効化する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ minikube addons &lt;span class="nb"&gt;enable&lt;/span&gt; heapster
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;✅ heapster was successfully enabled
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 比較のためにPodとServiceを再度確認する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pod,svc -n kube-system
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/coredns-5644d7b6d9-d2vxs 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 118m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/coredns-5644d7b6d9-rhr9r 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 118m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/etcd-minikube 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 117m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/heapster-h2d7l 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 57s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/influxdb-grafana-m6c78 2/2 Running &lt;span class="m"&gt;0&lt;/span&gt; 57s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/kube-addon-manager-minikube 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 118m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/kube-apiserver-minikube 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 116m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/kube-controller-manager-minikube 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 117m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/kube-proxy-f45zs 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 118m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/kube-scheduler-minikube 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 117m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/storage-provisioner 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 118m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/heapster ClusterIP 10.111.191.189 &amp;lt;none&amp;gt; 80/TCP 57s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/kube-dns ClusterIP 10.96.0.10 &amp;lt;none&amp;gt; 53/UDP,53/TCP,9153/TCP 118m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/monitoring-grafana NodePort 10.102.71.198 &amp;lt;none&amp;gt; 80:30002/TCP 58s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/monitoring-influxdb ClusterIP 10.107.121.196 &amp;lt;none&amp;gt; 8083/TCP,8086/TCP 57s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# heapsterを無効化する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ minikube addons disable heapster
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;✅ &lt;span class="s2"&gt;&amp;#34;heapster&amp;#34;&lt;/span&gt; was successfully disabled
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;アドオンの有効化/無効化ができた.&lt;/p&gt;
&lt;p&gt;なお&lt;a class="link" href="https://github.com/kubernetes-retired/heapster" target="_blank" rel="noopener"
 &gt;Heapster&lt;/a&gt;はDeprecatedされている模様&amp;hellip;&lt;/p&gt;
&lt;h2 id="クリーンアップ"&gt;クリーンアップ
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://kubernetes.io/docs/tutorials/hello-minikube/#clean-up" target="_blank" rel="noopener"
 &gt;https://kubernetes.io/docs/tutorials/hello-minikube/#clean-up&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;おかたづけする.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# リソースの一覧を確認する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get all
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/hello-node-7676b5fb8d-x7l5t 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 40m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/hello-node LoadBalancer 10.105.200.193 &amp;lt;pending&amp;gt; 8080:32547/TCP 22m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/kubernetes ClusterIP 10.96.0.1 &amp;lt;none&amp;gt; 443/TCP 122m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY UP-TO-DATE AVAILABLE AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps/hello-node 1/1 &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 40m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME DESIRED CURRENT READY AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;replicaset.apps/hello-node-7676b5fb8d &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 40m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Service(hello-node)を削除する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl delete service hello-node
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service &lt;span class="s2"&gt;&amp;#34;hello-node&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Deployment(hello-node)を削除する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl delete deployment hello-node
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps &lt;span class="s2"&gt;&amp;#34;hello-node&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# リソースを再確認する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get all
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/kubernetes ClusterIP 10.96.0.1 &amp;lt;none&amp;gt; 443/TCP 125m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# MinikubeのVMを停止する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ minikube stop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;✋ Stopping &lt;span class="s2"&gt;&amp;#34;minikube&amp;#34;&lt;/span&gt; in virtualbox ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🛑 &lt;span class="s2"&gt;&amp;#34;minikube&amp;#34;&lt;/span&gt; stopped.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# MinikubeのVMを削除する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ minikube delete
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🔥 Deleting &lt;span class="s2"&gt;&amp;#34;minikube&amp;#34;&lt;/span&gt; in virtualbox ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;💔 The &lt;span class="s2"&gt;&amp;#34;minikube&amp;#34;&lt;/span&gt; cluster has been deleted.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🔥 Successfully deleted profile &lt;span class="s2"&gt;&amp;#34;minikube&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以上, Hello Minikubeした.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="お部屋から顔だけ出すそとちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-10-28-hello-minikube/2019-10-28-sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2019-10-28-hello-minikube/2019-10-28-sotochan_hu_14d956abd9b117bc.jpg 800w, https://blog.uzimihsr.com/post/2019-10-28-hello-minikube/2019-10-28-sotochan_hu_a4778f5436990d0b.jpg 1600w, https://blog.uzimihsr.com/post/2019-10-28-hello-minikube/2019-10-28-sotochan_hu_fcf3bfc9dc7879cf.jpg 2400w, https://blog.uzimihsr.com/post/2019-10-28-hello-minikube/2019-10-28-sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>Minikubeをインストールした</title><link>https://blog.uzimihsr.com/post/2019-10-27-minikube/</link><pubDate>Sun, 27 Oct 2019 20:48:28 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2019-10-27-minikube/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2019-10-27-minikube/2019-10-27-sotochan.jpg" alt="Featured image of post Minikubeをインストールした" /&gt;&lt;h2 id="kubernetesやるぞ"&gt;Kubernetesやるぞ
&lt;/h2&gt;&lt;p&gt;今までKubernetesの勉強用にDocker for Desktopを使ってたけど,&lt;br&gt;
なんか公式のチュートリアルがMinikubeを使ってるのでやっぱり入れてみた.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="動作環境"&gt;動作環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;masOS Mojave 10.14&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Minikubeのインストール&lt;/li&gt;
&lt;li&gt;Kubernetesのセットアップ&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="minikubeのインストール"&gt;Minikubeのインストール
&lt;/h2&gt;&lt;p&gt;Kubernetes公式の手順(&lt;a class="link" href="https://kubernetes.io/docs/tasks/tools/install-minikube/" target="_blank" rel="noopener"
 &gt;Install Minikube&lt;/a&gt;)をやっていく.&lt;/p&gt;
&lt;p&gt;まずはじめに仮想化が有効になっているかチェックする.&lt;br&gt;
&lt;code&gt;VMX&lt;/code&gt;の文字に色がついてたらOKらしい.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sysctl -a &lt;span class="p"&gt;|&lt;/span&gt; grep -E --color &lt;span class="s1"&gt;&amp;#39;machdep.cpu.features|VMX&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;machdep.cpu.features: FPU VME DE PSE TSC MSR PAE MCE CX8 APIC SEP MTRR PGE MCA CMOV PAT PSE36 CLFSH DS ACPI MMX FXSR SSE SSE2 SS HTT TM PBE SSE3 PCLMULQDQ DTES64 MON DSCPL VMX SMX EST TM2 SSSE3 FMA CX16 TPR PDCM SSE4.1 SSE4.2 x2APIC MOVBE POPCNT AES PCID XSAVE OSXSAVE SEGLIM64 TSCTMR AVX1.0 RDRAND F16C
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;kubectl&lt;/code&gt;は&lt;code&gt;Docker for Desktop&lt;/code&gt;をインストールしたときに一緒に入れてるので大丈夫なはず.&lt;br&gt;
一応公式の手順は&lt;a class="link" href="https://kubernetes.io/docs/tasks/tools/install-kubectl/#install-kubectl-on-macos" target="_blank" rel="noopener"
 &gt;ここ&lt;/a&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Client Version: version.Info&lt;span class="o"&gt;{&lt;/span&gt;Major:&lt;span class="s2"&gt;&amp;#34;1&amp;#34;&lt;/span&gt;, Minor:&lt;span class="s2"&gt;&amp;#34;14&amp;#34;&lt;/span&gt;, GitVersion:&lt;span class="s2"&gt;&amp;#34;v1.14.6&amp;#34;&lt;/span&gt;, GitCommit:&lt;span class="s2"&gt;&amp;#34;96fac5cd13a5dc064f7d9f4f23030a6aeface6cc&amp;#34;&lt;/span&gt;, GitTreeState:&lt;span class="s2"&gt;&amp;#34;clean&amp;#34;&lt;/span&gt;, BuildDate:&lt;span class="s2"&gt;&amp;#34;2019-08-19T11:13:49Z&amp;#34;&lt;/span&gt;, GoVersion:&lt;span class="s2"&gt;&amp;#34;go1.12.9&amp;#34;&lt;/span&gt;, Compiler:&lt;span class="s2"&gt;&amp;#34;gc&amp;#34;&lt;/span&gt;, Platform:&lt;span class="s2"&gt;&amp;#34;darwin/amd64&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Server Version: version.Info&lt;span class="o"&gt;{&lt;/span&gt;Major:&lt;span class="s2"&gt;&amp;#34;1&amp;#34;&lt;/span&gt;, Minor:&lt;span class="s2"&gt;&amp;#34;14&amp;#34;&lt;/span&gt;, GitVersion:&lt;span class="s2"&gt;&amp;#34;v1.14.6&amp;#34;&lt;/span&gt;, GitCommit:&lt;span class="s2"&gt;&amp;#34;96fac5cd13a5dc064f7d9f4f23030a6aeface6cc&amp;#34;&lt;/span&gt;, GitTreeState:&lt;span class="s2"&gt;&amp;#34;clean&amp;#34;&lt;/span&gt;, BuildDate:&lt;span class="s2"&gt;&amp;#34;2019-08-19T11:05:16Z&amp;#34;&lt;/span&gt;, GoVersion:&lt;span class="s2"&gt;&amp;#34;go1.12.9&amp;#34;&lt;/span&gt;, Compiler:&lt;span class="s2"&gt;&amp;#34;gc&amp;#34;&lt;/span&gt;, Platform:&lt;span class="s2"&gt;&amp;#34;linux/amd64&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;また, VMのハイパーバイザーは&lt;a class="link" href="https://uzimihsr.github.io/post/2019-10-07-docker-get-started-04/" target="_blank" rel="noopener"
 &gt;Dockerの旧Get Started&lt;/a&gt;で&lt;code&gt;VirtualBox&lt;/code&gt;をインストール済み.&lt;br&gt;
一応&lt;a class="link" href="https://www.virtualbox.org/wiki/Downloads" target="_blank" rel="noopener"
 &gt;ここ&lt;/a&gt;からダウンロードできる.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Homebrew&lt;/code&gt;を使って&lt;code&gt;Minikube&lt;/code&gt;をインストールする.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ brew cask install minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;==&lt;/span&gt;&amp;gt; Tapping homebrew/cask
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Cloning into &lt;span class="s1"&gt;&amp;#39;/usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask&amp;#39;&lt;/span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;remote: Enumerating objects: 3601, &lt;span class="k"&gt;done&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;remote: Counting objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;3601/3601&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;remote: Compressing objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;3593/3593&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;remote: Total &lt;span class="m"&gt;3601&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;delta 25&lt;span class="o"&gt;)&lt;/span&gt;, reused &lt;span class="m"&gt;576&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;delta 6&lt;span class="o"&gt;)&lt;/span&gt;, pack-reused &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Receiving objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;3601/3601&lt;span class="o"&gt;)&lt;/span&gt;, 1.20 MiB &lt;span class="p"&gt;|&lt;/span&gt; 1.44 MiB/s, &lt;span class="k"&gt;done&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Resolving deltas: 100% &lt;span class="o"&gt;(&lt;/span&gt;25/25&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Tapped &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="nb"&gt;command&lt;/span&gt; and &lt;span class="m"&gt;3489&lt;/span&gt; casks &lt;span class="o"&gt;(&lt;/span&gt;3,606 files, 3.9MB&lt;span class="o"&gt;)&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;==&lt;/span&gt;&amp;gt; Satisfying dependencies
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;All Formula dependencies satisfied.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;==&lt;/span&gt;&amp;gt; Downloading https://storage.googleapis.com/minikube/releases/v1.5.0/minikube-darwin-amd64
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;######################################################################## 100.0%&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;==&lt;/span&gt;&amp;gt; Verifying SHA-256 checksum &lt;span class="k"&gt;for&lt;/span&gt; Cask &lt;span class="s1"&gt;&amp;#39;minikube&amp;#39;&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;==&lt;/span&gt;&amp;gt; Installing Cask &lt;span class="nv"&gt;minikube&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;==&lt;/span&gt;&amp;gt; Creating Caskroom at /usr/local/Caskroom
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;==&lt;/span&gt;&amp;gt; We&lt;span class="s1"&gt;&amp;#39;ll set permissions properly so we won&amp;#39;&lt;/span&gt;t need sudo in the future.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Password:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;==&lt;/span&gt;&amp;gt; Linking Binary &lt;span class="s1"&gt;&amp;#39;minikube-darwin-amd64&amp;#39;&lt;/span&gt; to &lt;span class="s1"&gt;&amp;#39;/usr/local/bin/minikube&amp;#39;&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🍺 minikube was successfully installed!
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ minikube version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;minikube version: v1.5.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;commit: d1151d93385a70c5a03775e166e94067791fe2d9
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;早速&lt;code&gt;Minikube&lt;/code&gt;を起動する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ minikube start
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;😄 minikube v1.5.0 on Darwin 10.14
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;✨ Automatically selected the &lt;span class="s1"&gt;&amp;#39;hyperkit&amp;#39;&lt;/span&gt; driver &lt;span class="o"&gt;(&lt;/span&gt;alternates: &lt;span class="o"&gt;[&lt;/span&gt;virtualbox&lt;span class="o"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;💾 Downloading driver docker-machine-driver-hyperkit:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;gt; docker-machine-driver-hyperkit.sha256: &lt;span class="m"&gt;65&lt;/span&gt; B / &lt;span class="m"&gt;65&lt;/span&gt; B &lt;span class="o"&gt;[&lt;/span&gt;---&lt;span class="o"&gt;]&lt;/span&gt; 100.00% ? p/s 0s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;gt; docker-machine-driver-hyperkit: 10.79 MiB / 10.79 MiB 100.00% 3.25 MiB p
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🔑 The &lt;span class="s1"&gt;&amp;#39;hyperkit&amp;#39;&lt;/span&gt; driver requires elevated permissions. The following commands will be executed:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; $ sudo chown root:wheel /Users/uzimihsr/.minikube/bin/docker-machine-driver-hyperkit
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; $ sudo chmod u+s /Users/uzimihsr/.minikube/bin/docker-machine-driver-hyperkit
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Password:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;💿 Downloading VM boot image ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;gt; minikube-v1.5.0.iso.sha256: &lt;span class="m"&gt;65&lt;/span&gt; B / &lt;span class="m"&gt;65&lt;/span&gt; B &lt;span class="o"&gt;[&lt;/span&gt;--------------&lt;span class="o"&gt;]&lt;/span&gt; 100.00% ? p/s 0s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;gt; minikube-v1.5.0.iso: 143.77 MiB / 143.77 MiB &lt;span class="o"&gt;[&lt;/span&gt;-&lt;span class="o"&gt;]&lt;/span&gt; 100.00% 58.33 MiB p/s 2s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🔥 Creating hyperkit VM &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;CPUs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2, &lt;span class="nv"&gt;Memory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2000MB, &lt;span class="nv"&gt;Disk&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;20000MB&lt;span class="o"&gt;)&lt;/span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🐳 Preparing Kubernetes v1.16.2 on Docker 18.09.9 ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;💾 Downloading kubeadm v1.16.2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;💾 Downloading kubelet v1.16.2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🚜 Pulling images ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🚀 Launching Kubernetes ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;⌛ Waiting &lt;span class="k"&gt;for&lt;/span&gt;: apiserver proxy etcd scheduler controller dns
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🏄 Done! kubectl is now configured to use &lt;span class="s2"&gt;&amp;#34;minikube&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;⚠️ /usr/local/bin/kubectl is version 1.14.6, and is incompatible with Kubernetes 1.16.2. You will need to update /usr/local/bin/kubectl or use &lt;span class="s1"&gt;&amp;#39;minikube kubectl&amp;#39;&lt;/span&gt; to connect with this cluster
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ちゃんと起動したけどなんか勝手に&lt;code&gt;Hyperkit&lt;/code&gt;が使われちゃってるので一旦止める.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ minikube delete
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🔥 Deleting &lt;span class="s2"&gt;&amp;#34;minikube&amp;#34;&lt;/span&gt; in hyperkit ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;💔 The &lt;span class="s2"&gt;&amp;#34;minikube&amp;#34;&lt;/span&gt; cluster has been deleted.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🔥 Successfully deleted profile &lt;span class="s2"&gt;&amp;#34;minikube&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;使用するハイパーバイザは&lt;code&gt;--vm-driver&lt;/code&gt;フラグを指定すればいいらしい.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ minikube start --vm-driver&lt;span class="o"&gt;=&lt;/span&gt;virtualbox
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;😄 minikube v1.5.0 on Darwin 10.14
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🔥 Creating virtualbox VM &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;CPUs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2, &lt;span class="nv"&gt;Memory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2000MB, &lt;span class="nv"&gt;Disk&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;20000MB&lt;span class="o"&gt;)&lt;/span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🐳 Preparing Kubernetes v1.16.2 on Docker 18.09.9 ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🚜 Pulling images ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🚀 Launching Kubernetes ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;⌛ Waiting &lt;span class="k"&gt;for&lt;/span&gt;: apiserver proxy etcd scheduler controller dns
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🏄 Done! kubectl is now configured to use &lt;span class="s2"&gt;&amp;#34;minikube&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;⚠️ /usr/local/bin/kubectl is version 1.14.6, and is incompatible with Kubernetes 1.16.2. You will need to update /usr/local/bin/kubectl or use &lt;span class="s1"&gt;&amp;#39;minikube kubectl&amp;#39;&lt;/span&gt; to connect with this cluster
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;今度はちゃんと&lt;code&gt;VirtualBox&lt;/code&gt;を使ってくれた.&lt;br&gt;
よく見たら&lt;code&gt;kubectl&lt;/code&gt;のバージョンが古くて警告されてる. バージョンを上げない場合は&lt;code&gt;minikube kubectl&lt;/code&gt;を使う必要があるみたい.&lt;/p&gt;
&lt;p&gt;なんかログを見た感じmacBook上にVMを作成してそれをノードとして&lt;code&gt;Kubernetes&lt;/code&gt;クラスタにしてるっぽい?&lt;br&gt;
&lt;code&gt;docker-machine&lt;/code&gt;を使って&lt;code&gt;Swarm&lt;/code&gt;クラスタを&lt;a class="link" href="https://uzimihsr.github.io/post/2019-10-07-docker-get-started-04/" target="_blank" rel="noopener"
 &gt;作ったとき&lt;/a&gt;と似たことをやっている?&lt;br&gt;
後で余裕があったらちゃんと調べておく(たぶんやらない).&lt;/p&gt;
&lt;p&gt;とりあえず&lt;code&gt;Minikube&lt;/code&gt;のインストールは完了.&lt;/p&gt;
&lt;h2 id="kubernetesのセットアップ"&gt;Kubernetesのセットアップ
&lt;/h2&gt;&lt;p&gt;Kubernetes公式の手順(&lt;a class="link" href="https://kubernetes.io/docs/setup/learning-environment/minikube/#quickstart" target="_blank" rel="noopener"
 &gt;Installing Kubernetes with Minikube&lt;/a&gt;)のQuickstartをやっていく.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;minikube start&lt;/code&gt;は既に実行済みなので割愛.&lt;/p&gt;
&lt;p&gt;早速&lt;code&gt;kubectl&lt;/code&gt;でサンプル用&lt;code&gt;Deployment&lt;/code&gt;を作成してみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ minikube kubectl create deployment hello-minikube --image&lt;span class="o"&gt;=&lt;/span&gt;k8s.gcr.io/echoserver:1.10
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Error: unknown flag: --image
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Usage:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; minikube kubectl &lt;span class="o"&gt;[&lt;/span&gt;flags&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;options&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Use &lt;span class="s2"&gt;&amp;#34;minikube kubectl options&amp;#34;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; a list of global command-line options &lt;span class="o"&gt;(&lt;/span&gt;applies to all commands&lt;span class="o"&gt;)&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl create deployment hello-minikube --image&lt;span class="o"&gt;=&lt;/span&gt;k8s.gcr.io/echoserver:1.10
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps/hello-minikube created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get deployments
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY UP-TO-DATE AVAILABLE AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hello-minikube 1/1 &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 46s
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;さっきの警告どおり&lt;code&gt;minikube kubectl&lt;/code&gt;使うと&lt;code&gt;--image&lt;/code&gt;が使えないぞ的なエラーになった. なぜ&amp;hellip;?&lt;br&gt;
まあ普通に&lt;code&gt;kubectl&lt;/code&gt;が使えるのであまり気にしない.&lt;/p&gt;
&lt;p&gt;この &lt;strong&gt;hello-minikube&lt;/strong&gt; &lt;code&gt;Deployment&lt;/code&gt;の8080番ポートを公開するための&lt;code&gt;Service&lt;/code&gt;を作成する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl expose deployment hello-minikube --type&lt;span class="o"&gt;=&lt;/span&gt;NodePort --port&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/hello-minikube exposed
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;hello-minikube&lt;/strong&gt; の&lt;code&gt;Pod&lt;/code&gt;を確認する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hello-minikube-797f975945-ftf9z 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 6m38s
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Service&lt;/code&gt;のURLを取得する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ minikube service hello-minikube --url
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;http://192.168.99.103:31394
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;取得したURLをブラウザで開く.&lt;br&gt;
クラスタの詳細情報が表示される.&lt;/p&gt;
&lt;p&gt;&lt;img alt="クラスタ詳細" class="gallery-image" data-flex-basis="535px" data-flex-grow="223" height="1184" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-10-27-minikube/2019-10-27-sc01.png" srcset="https://blog.uzimihsr.com/post/2019-10-27-minikube/2019-10-27-sc01_hu_18886d94d2877ef9.png 800w, https://blog.uzimihsr.com/post/2019-10-27-minikube/2019-10-27-sc01_hu_c1d9fddc15609701.png 1600w, https://blog.uzimihsr.com/post/2019-10-27-minikube/2019-10-27-sc01_hu_6a446fe26f2c9de.png 2400w, https://blog.uzimihsr.com/post/2019-10-27-minikube/2019-10-27-sc01.png 2642w" width="2642"&gt;&lt;/p&gt;
&lt;p&gt;動作確認ができたので, &lt;code&gt;Service&lt;/code&gt;と&lt;code&gt;Deployment&lt;/code&gt;を削除する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get all
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/hello-minikube-797f975945-ftf9z 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 17m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/hello-minikube NodePort 10.109.38.18 &amp;lt;none&amp;gt; 8080:31394/TCP 13m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/kubernetes ClusterIP 10.96.0.1 &amp;lt;none&amp;gt; 443/TCP 29m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY UP-TO-DATE AVAILABLE AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps/hello-minikube 1/1 &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 17m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME DESIRED CURRENT READY AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;replicaset.apps/hello-minikube-797f975945 &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 17m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl delete service hello-minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service &lt;span class="s2"&gt;&amp;#34;hello-minikube&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl delete deployment hello-minikube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps &lt;span class="s2"&gt;&amp;#34;hello-minikube&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Minikube&lt;/code&gt;クラスタを停止, 削除する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ minikube stop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;✋ Stopping &lt;span class="s2"&gt;&amp;#34;minikube&amp;#34;&lt;/span&gt; in virtualbox ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🛑 &lt;span class="s2"&gt;&amp;#34;minikube&amp;#34;&lt;/span&gt; stopped.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ minikube delete
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🔥 Deleting &lt;span class="s2"&gt;&amp;#34;minikube&amp;#34;&lt;/span&gt; in virtualbox ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;💔 The &lt;span class="s2"&gt;&amp;#34;minikube&amp;#34;&lt;/span&gt; cluster has been deleted.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;🔥 Successfully deleted profile &lt;span class="s2"&gt;&amp;#34;minikube&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;とりあえず&lt;code&gt;Minikube&lt;/code&gt;で&lt;code&gt;Kubernetes&lt;/code&gt;クラスタを構築してアプリをデプロイできた.&lt;/p&gt;
&lt;p&gt;次は&lt;a class="link" href="https://kubernetes.io/docs/tutorials/hello-minikube/" target="_blank" rel="noopener"
 &gt;Hello Minikube&lt;/a&gt;あたりからチュートリアルを進めていく.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="ダンボールに入るそとちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-10-27-minikube/2019-10-27-sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2019-10-27-minikube/2019-10-27-sotochan_hu_b4899a2e78e5532e.jpg 800w, https://blog.uzimihsr.com/post/2019-10-27-minikube/2019-10-27-sotochan_hu_8c16515b6020552c.jpg 1600w, https://blog.uzimihsr.com/post/2019-10-27-minikube/2019-10-27-sotochan_hu_76bf562a7f77211b.jpg 2400w, https://blog.uzimihsr.com/post/2019-10-27-minikube/2019-10-27-sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>Docker Quickstartを超意訳する Part 5</title><link>https://blog.uzimihsr.com/post/2019-10-15-docker-05/</link><pubDate>Tue, 15 Oct 2019 22:40:21 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2019-10-15-docker-05/</guid><description>&lt;h2 id="docker-hubでイメージをシェアする"&gt;Docker Hubでイメージをシェアする
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2019-10-14-docker-04/" target="_blank" rel="noopener"
 &gt;Part 4&lt;/a&gt;ではSwarmにアプリをデプロイした.&lt;br&gt;
最後のPart 5ではイメージのシェアを行う.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="get-started-part-5-sharing-images-on-docker-hub"&gt;Get Started, Part 5: Sharing Images on Docker Hub
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/part5/" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/get-started/part5/&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="もくじ"&gt;もくじ
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;Prerequisites&lt;/li&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Setting Up Your Docker Hub Account&lt;/li&gt;
&lt;li&gt;Creating and Pushing to a Docker Hub Repository&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="prerequisites"&gt;Prerequisites
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/part5/#prerequisites" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/get-started/part5/#prerequisites&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2019-10-12-docker-02/" target="_blank" rel="noopener"
 &gt;Part 2&lt;/a&gt;でのアプリのコンテナ化ができていること.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="introduction"&gt;Introduction
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/part5/#introduction" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/get-started/part5/#introduction&lt;/a&gt;&lt;br&gt;
ここまでのパートでは&lt;code&gt;Docker Desktop&lt;/code&gt;を利用してアプリのコンテナ化(&lt;a class="link" href="https://uzimihsr.github.io/post/2019-10-12-docker-02/" target="_blank" rel="noopener"
 &gt;Part 2&lt;/a&gt;), &lt;code&gt;Kubernetes&lt;/code&gt;でのデプロイ(&lt;a class="link" href="https://uzimihsr.github.io/post/2019-10-13-docker-03/" target="_blank" rel="noopener"
 &gt;Part 3&lt;/a&gt;), &lt;code&gt;Swarm&lt;/code&gt;でのデプロイ(&lt;a class="link" href="https://uzimihsr.github.io/post/2019-10-14-docker-04/" target="_blank" rel="noopener"
 &gt;Part 4&lt;/a&gt;)を行ってきた.&lt;br&gt;
このパートではコンテナアプリ開発の最後のステップである&lt;code&gt;image&lt;/code&gt;のシェアを行う.&lt;br&gt;
&lt;code&gt;Docker Hub&lt;/code&gt;のようなレジストリを利用することで, &lt;code&gt;image&lt;/code&gt;のダウンロードと実行がどこでも簡単にできるようになる.&lt;/p&gt;
&lt;h3 id="setting-up-your-docker-hub-account"&gt;Setting Up Your Docker Hub Account
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/part5/#setting-up-your-docker-hub-account" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/get-started/part5/#setting-up-your-docker-hub-account&lt;/a&gt;&lt;br&gt;
まだ&lt;code&gt;Docker ID&lt;/code&gt;を持っていない場合は以下の手順に従うことで&lt;code&gt;Docker Hub&lt;/code&gt;を利用した&lt;code&gt;image&lt;/code&gt;のシェアが可能になる.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1&lt;/strong&gt;: ブラウザで&lt;code&gt;Docker Hub&lt;/code&gt;の新規登録ページ &lt;a class="link" href="https://hub.docker.com/signup" target="_blank" rel="noopener"
 &gt;https://hub.docker.com/signup&lt;/a&gt; を開く.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2&lt;/strong&gt;: フォームを埋めて送信し, &lt;code&gt;Docker ID&lt;/code&gt;を取得する.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3&lt;/strong&gt;: ツールバーの&lt;code&gt;Docker&lt;/code&gt;アイコンを押し, プルダウンメニューから&lt;code&gt;Sign In / Create Docker ID&lt;/code&gt;をクリックする.&lt;br&gt;
&lt;img alt="プルダウン" class="gallery-image" data-flex-basis="159px" data-flex-grow="66" height="730" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-10-15-docker-05/2019-10-15-sc01.png" width="484"&gt;&lt;/p&gt;
&lt;p&gt;取得した&lt;code&gt;Docker ID&lt;/code&gt;とパスワードを入力してログインする.&lt;br&gt;
&lt;img alt="ログイン" class="gallery-image" data-flex-basis="371px" data-flex-grow="154" height="782" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-10-15-docker-05/2019-10-15-sc02.png" srcset="https://blog.uzimihsr.com/post/2019-10-15-docker-05/2019-10-15-sc02_hu_bc41415fbcc3d989.png 800w, https://blog.uzimihsr.com/post/2019-10-15-docker-05/2019-10-15-sc02.png 1212w" width="1212"&gt;&lt;/p&gt;
&lt;p&gt;ログインに成功するとプルダウンメニューに&lt;code&gt;username: Sign out&lt;/code&gt;が表示される.&lt;br&gt;
&lt;img alt="プルダウン" class="gallery-image" data-flex-basis="158px" data-flex-grow="65" height="737" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-10-15-docker-05/2019-10-15-sc03.png" width="486"&gt;&lt;/p&gt;
&lt;p&gt;また, この手順の代わりに&lt;code&gt;docker login&lt;/code&gt;でも同じことができる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Dockerレジストリにログイン&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker login
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Login with your Docker ID to push and pull images from Docker Hub. If you don&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;t have a Docker ID, head over to https://hub.docker.com to create one.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Username: uzimihsr
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Password:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Login Succeeded
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;[追加]ログアウトは&lt;code&gt;docker logout&lt;/code&gt;でできる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Dockerレジストリからログアウト&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker &lt;span class="nb"&gt;logout&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Removing login credentials &lt;span class="k"&gt;for&lt;/span&gt; https://index.docker.io/v1/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="creating-and-pushing-to-a-docker-hub-repository"&gt;Creating and Pushing to a Docker Hub Repository
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/part5/#creating-and-pushing-to-a-docker-hub-repository" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/get-started/part5/#creating-and-pushing-to-a-docker-hub-repository&lt;/a&gt;&lt;br&gt;
&lt;code&gt;Docker Hub&lt;/code&gt;のアカウントを&lt;code&gt;Docker Desktop&lt;/code&gt;に紐付けることができたので, さっそくリポジトリを作成して掲示板アプリをシェアする.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1&lt;/strong&gt;: ツールバーの&lt;code&gt;Docker&lt;/code&gt;アイコンを押し, &lt;code&gt;Repositories -&amp;gt; Create...&lt;/code&gt;と進む.&lt;br&gt;
&lt;img alt="プルダウン" class="gallery-image" data-flex-basis="258px" data-flex-grow="107" height="730" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-10-15-docker-05/2019-10-15-sc04.png" width="787"&gt;&lt;/p&gt;
&lt;p&gt;デフォルトブラウザでリポジトリ作成画面が開かれる.&lt;br&gt;
&lt;img alt="リポジトリ作成画面" class="gallery-image" data-flex-basis="402px" data-flex-grow="167" height="1719" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-10-15-docker-05/2019-10-15-sc05.png" srcset="https://blog.uzimihsr.com/post/2019-10-15-docker-05/2019-10-15-sc05_hu_7c9289d80702975a.png 800w, https://blog.uzimihsr.com/post/2019-10-15-docker-05/2019-10-15-sc05_hu_484d01437b00629e.png 1600w, https://blog.uzimihsr.com/post/2019-10-15-docker-05/2019-10-15-sc05_hu_d9ecd03f613aaaec.png 2400w, https://blog.uzimihsr.com/post/2019-10-15-docker-05/2019-10-15-sc05.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2&lt;/strong&gt;: &lt;code&gt;Name&lt;/code&gt;(リポジトリ名)に&lt;strong&gt;bulletinboard&lt;/strong&gt;と入力し, 他の内容は初期状態のまま下部の&lt;code&gt;Create&lt;/code&gt;を押す.&lt;br&gt;
&lt;img alt="リポジトリ作成画面" class="gallery-image" data-flex-basis="425px" data-flex-grow="177" height="1624" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-10-15-docker-05/2019-10-15-sc06.png" srcset="https://blog.uzimihsr.com/post/2019-10-15-docker-05/2019-10-15-sc06_hu_4aab38f7bdb895e4.png 800w, https://blog.uzimihsr.com/post/2019-10-15-docker-05/2019-10-15-sc06_hu_5f8b511621715adc.png 1600w, https://blog.uzimihsr.com/post/2019-10-15-docker-05/2019-10-15-sc06_hu_c57c5d1baa6c7744.png 2400w, https://blog.uzimihsr.com/post/2019-10-15-docker-05/2019-10-15-sc06.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;リポジトリが作成され, &lt;strong&gt;bulletinboard&lt;/strong&gt;リポジトリの画面に遷移する.&lt;br&gt;
&lt;img alt="リポジトリ作成画面" class="gallery-image" data-flex-basis="471px" data-flex-grow="196" height="1466" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-10-15-docker-05/2019-10-15-sc07.png" srcset="https://blog.uzimihsr.com/post/2019-10-15-docker-05/2019-10-15-sc07_hu_13fa7706570c02ef.png 800w, https://blog.uzimihsr.com/post/2019-10-15-docker-05/2019-10-15-sc07_hu_3138248ab5b7e975.png 1600w, https://blog.uzimihsr.com/post/2019-10-15-docker-05/2019-10-15-sc07_hu_116b413897d53c47.png 2400w, https://blog.uzimihsr.com/post/2019-10-15-docker-05/2019-10-15-sc07.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3&lt;/strong&gt;: &lt;code&gt;image&lt;/code&gt;を&lt;code&gt;Docker Hub&lt;/code&gt;でシェアするためには, アップロードする前に&lt;code&gt;Docker Hub&lt;/code&gt;上で管理するための名前をつける必要がある.&lt;br&gt;
&lt;code&gt;Docker Hub&lt;/code&gt;上で&lt;code&gt;image&lt;/code&gt;を識別する名前は基本的に&lt;code&gt;&amp;lt;Docker Hub ID&amp;gt;/&amp;lt;Repository Name&amp;gt;:&amp;lt;tag&amp;gt;&lt;/code&gt;の形式を取る.&lt;br&gt;
今回の掲示板アプリの&lt;code&gt;image&lt;/code&gt;であれば次のように名前をつける.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# imageを確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;REPOSITORY TAG IMAGE ID CREATED SIZE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bulletinboard 1.0 06f7fe6f1ca0 &lt;span class="m"&gt;2&lt;/span&gt; days ago 681MB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ローカルにあるimage(bulletinboard:1.0)にDocker Hub用のタグ(uzimihsr/bulletinboard:1.0)を付け直す&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image tag bulletinboard:1.0 uzimihsr/bulletinboard:1.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# imageを再確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;REPOSITORY TAG IMAGE ID CREATED SIZE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bulletinboard 1.0 06f7fe6f1ca0 &lt;span class="m"&gt;2&lt;/span&gt; days ago 681MB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr/bulletinboard 1.0 06f7fe6f1ca0 &lt;span class="m"&gt;2&lt;/span&gt; days ago 681MB
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;4&lt;/strong&gt;: タグを付け直した&lt;code&gt;image&lt;/code&gt;を&lt;code&gt;Docker Hub&lt;/code&gt;にアップロード(push)する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# image(uzimihsr/bulletinboard:1.0)をpush&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image push uzimihsr/bulletinboard:1.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;The push refers to repository &lt;span class="o"&gt;[&lt;/span&gt;docker.io/uzimihsr/bulletinboard&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;0b4750593321: Pushed
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3896ce266caf: Pushed
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;439a7da7954e: Pushed
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;f7d0b1f86348: Pushed
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dd883cbb0cf7: Mounted from library/node
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;a3a3f69aebe8: Mounted from library/node
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;0da372da714b: Mounted from library/node
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bf3841becf9d: Mounted from library/node
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;63866df00998: Mounted from library/node
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2f9128310b77: Mounted from library/node
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;d9a5f9b8d5c2: Mounted from library/node
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;c01c63c6823d: Mounted from library/node
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1.0: digest: sha256:339f47f51b574edbd94c981e8a58b0e019ba7451a8e83f44cca1cc32d3748d8b size: &lt;span class="m"&gt;2841&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;先程の&lt;strong&gt;bulletinboard&lt;/strong&gt;リポジトリの画面をリロードするか, &lt;a class="link" href="https://hub.docker.com/r/uzimihsr/bulletinboard/tags" target="_blank" rel="noopener"
 &gt;https://hub.docker.com/r/uzimihsr/bulletinboard/tags&lt;/a&gt; を開くと確かに&lt;code&gt;image&lt;/code&gt;がpushされていることを確認できる. また, デフォルトではリポジトリがpublicになっていることに注意.&lt;br&gt;
&lt;img alt="リポジトリ画面" class="gallery-image" data-flex-basis="575px" data-flex-grow="239" height="1202" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-10-15-docker-05/2019-10-15-sc08.png" srcset="https://blog.uzimihsr.com/post/2019-10-15-docker-05/2019-10-15-sc08_hu_f4576dff8873a35c.png 800w, https://blog.uzimihsr.com/post/2019-10-15-docker-05/2019-10-15-sc08_hu_5f6cf1037a682363.png 1600w, https://blog.uzimihsr.com/post/2019-10-15-docker-05/2019-10-15-sc08_hu_408f42a33044aeeb.png 2400w, https://blog.uzimihsr.com/post/2019-10-15-docker-05/2019-10-15-sc08.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;[追加]レジストリの&lt;code&gt;image&lt;/code&gt;を利用する例は&lt;a class="link" href="https://uzimihsr.github.io/post/2019-10-05-docker-get-started-02/" target="_blank" rel="noopener"
 &gt;旧記事&lt;/a&gt;にあるので, 今回は省略する.&lt;/p&gt;
&lt;h3 id="conclusion"&gt;Conclusion
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/part5/#conclusion" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/get-started/part5/#conclusion&lt;/a&gt;&lt;br&gt;
以上の手順により&lt;code&gt;Docker Hub&lt;/code&gt;上に&lt;code&gt;image&lt;/code&gt;をpushできたため, どこからでもこの&lt;code&gt;image&lt;/code&gt;を使えるようになった.&lt;br&gt;
この&lt;code&gt;image&lt;/code&gt;(&lt;strong&gt;bulletinboard:1.0&lt;/strong&gt;)をローカルに持っていないクラスタから今回作成したリポジトリの&lt;code&gt;image&lt;/code&gt;を指定すると, &lt;code&gt;Docker&lt;/code&gt;はこれを自動でダウンロードして使用してくれる.&lt;br&gt;
このように&lt;code&gt;image&lt;/code&gt;はどこでも利用することができ, さらにアプリに必要な依存関係は&lt;code&gt;image&lt;/code&gt;の中で完結するため,&lt;br&gt;
マシンに&lt;code&gt;Docker&lt;/code&gt;とオーケストレーター(&lt;code&gt;kubernetes&lt;/code&gt;または&lt;code&gt;Swarm&lt;/code&gt;)さえインストールすればどんなコンテナアプリでも動かすことができる.&lt;/p&gt;
&lt;p&gt;また, 今回は&lt;code&gt;image&lt;/code&gt;を&lt;code&gt;Docker Hub&lt;/code&gt;にpushしただけだが, &lt;code&gt;image&lt;/code&gt;の作成に使用した&lt;code&gt;Dockerfile&lt;/code&gt;やオーケストレーターでのコンテナの起動に使用する&lt;code&gt;Kubernetes&lt;/code&gt;YAMLファイル, &lt;code&gt;Stack&lt;/code&gt;ファイルについてはどうすれば良いのか?&lt;br&gt;
それらのファイルはバージョン管理システム(Gitなど)でソースコードと一緒に管理し, そのリポジトリが簡単に参照できるよう&lt;code&gt;Docker Hub&lt;/code&gt;リポジトリの説明欄にリンクを貼り, &lt;code&gt;image&lt;/code&gt;のビルド手順を残し, アプリ利用方法がわかるようにしておくのがベストプラクティスである.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="感想"&gt;感想
&lt;/h2&gt;&lt;p&gt;ここまで5つのパートを読んでみて, なんとなくで済ませていた&lt;code&gt;Docker&lt;/code&gt;コンテナの扱いについてちょっとは理解が深まった気がする.&lt;br&gt;
特にレジストリを使って&lt;code&gt;image&lt;/code&gt;が共有できるのは素晴らしいと思った.&lt;br&gt;
&lt;code&gt;Kubernetes&lt;/code&gt;についても(ほんとに一部のリソースだけだが)触れられて良かった.&lt;br&gt;
&lt;code&gt;Swarm&lt;/code&gt;についてはなんか公式でも&lt;code&gt;Kubernetes&lt;/code&gt;に切り替えている感がドキュメントからも伝わってきたけど,&lt;br&gt;
旧Get Startedでも触ったように実際のマシンでも簡単にクラスタ構築ができるのは便利だとは思う&amp;hellip;&lt;br&gt;
でも最近は&lt;code&gt;Kubernetes&lt;/code&gt;も環境構築が簡単になってきているみたいなので, やっぱりお察し.&lt;br&gt;
というわけで次は&lt;code&gt;Kubernetes&lt;/code&gt;の公式ドキュメントで入門に良さそうなものがあったらまた読んでみたい.&lt;/p&gt;</description></item><item><title>Docker Quickstartを超意訳する Part 4</title><link>https://blog.uzimihsr.com/post/2019-10-14-docker-04/</link><pubDate>Mon, 14 Oct 2019 13:56:32 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2019-10-14-docker-04/</guid><description>&lt;h2 id="swarmでのデプロイ"&gt;Swarmでのデプロイ
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2019-10-13-docker-03/" target="_blank" rel="noopener"
 &gt;Part 3&lt;/a&gt;ではKubernetesにアプリをデプロイした.&lt;br&gt;
Part 4では同じアプリをSwarmにデプロイしてみる.&lt;br&gt;
正直Kubernetesのほうが便利だし内容もほとんど被っているので飛ばして良かったかもしれない&amp;hellip;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="get-started-part-4-deploying-to-swarm"&gt;Get Started, Part 4: Deploying to Swarm
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/part4/" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/get-started/part4/&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="もくじ"&gt;もくじ
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;Prerequisites&lt;/li&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Describing Apps Using Stack Files&lt;/li&gt;
&lt;li&gt;Deploying and Checking Your Application&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="prerequisites"&gt;Prerequisites
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/part4/#prerequisites" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/get-started/part4/#prerequisites&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2019-10-12-docker-02/" target="_blank" rel="noopener"
 &gt;Part 2&lt;/a&gt;でのアプリのコンテナ化ができていること.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Docker Desktop&lt;/code&gt;上で&lt;code&gt;Swarm&lt;/code&gt;が動作していること
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;docker system info&lt;/code&gt;で確認できる. &lt;code&gt;Swarm: active&lt;/code&gt;となっていればOK.&lt;/li&gt;
&lt;li&gt;動作していない場合は&lt;code&gt;docker swarm init&lt;/code&gt;で起動する.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Dockerのシステム情報を表示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 長いのでSwarmを含む行を抜き出し&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker system info &lt;span class="p"&gt;|&lt;/span&gt; grep Swarm
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Swarm: active
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="introduction"&gt;Introduction
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/part4/#introduction" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/get-started/part4/#introduction&lt;/a&gt;&lt;br&gt;
これまでのパートではアプリを単一のコンテナで起動する方法と&lt;code&gt;Kubernetes&lt;/code&gt;上にデプロイする方法を学んできたが, このパートでは&lt;code&gt;Docker Swarm&lt;/code&gt;でアプリを管理してみる.&lt;br&gt;
&lt;code&gt;Swarm&lt;/code&gt;は&lt;code&gt;Kubernetes&lt;/code&gt;と同様にコンテナアプリのスケーリング, ネットワーク, セキュリティ, メンテナンスのための, コンテナ自体に最初から入っている機能よりも強力な様々なツールを提供する.&lt;/p&gt;
&lt;p&gt;Part 2で作成したコンテナアプリが&lt;code&gt;Swarm&lt;/code&gt;上で動作することを検証するために, 今回は本番環境の&lt;code&gt;Swarm&lt;/code&gt;クラスタではなく&lt;code&gt;Docker Desktop&lt;/code&gt;でセットアップした開発マシンの&lt;code&gt;Swarm&lt;/code&gt;を使用する.&lt;br&gt;
&lt;code&gt;Docker Desktop&lt;/code&gt;で構築した&lt;code&gt;Swarm&lt;/code&gt;環境は本番環境のクラスタで動作するものと同じ機能を持ち, 開発マシンから容易にアクセスできるという利点がある.&lt;br&gt;
[追加]&lt;code&gt;Swarm&lt;/code&gt;(Docker社製)と&lt;code&gt;Kubernetes&lt;/code&gt;(Google社製)はどちらもコンテナを管理(オーケストレーション)するシステムであり, 正直&lt;code&gt;Kubernetes&lt;/code&gt;のほうが強力だと思う&amp;hellip;
自分で1からセットアップする場合の触りやすさではまだ&lt;code&gt;Swarm&lt;/code&gt;に分がある?&lt;/p&gt;
&lt;h3 id="describing-apps-using-stack-files"&gt;Describing Apps Using Stack Files
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/part4/#describing-apps-using-stack-files" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/get-started/part4/#describing-apps-using-stack-files&lt;/a&gt;&lt;br&gt;
&lt;code&gt;Swarm&lt;/code&gt;ではPart 2のようにコンテナを1つずつ作成することはせず, &lt;code&gt;Swarm&lt;/code&gt;が自動で管理するネットワーク機能を付与されたスケーラブルな複数のコンテナで構成される&lt;code&gt;service&lt;/code&gt;という単位で運用される.&lt;br&gt;
また, 全ての&lt;code&gt;Swarm&lt;/code&gt;オブジェクトは&lt;code&gt;Stack&lt;/code&gt;ファイルと呼ばれるマニフェストファイルで定義される.&lt;br&gt;
このファイルには&lt;code&gt;Swarm&lt;/code&gt;アプリを構成するコンポーネントと設定の情報が記述されていて, &lt;code&gt;Swarm&lt;/code&gt;環境でのアプリの作成/削除に使用される.&lt;br&gt;
[追記]ここらへんの原文はほとんどPart 3と変わらない&amp;hellip; &lt;del&gt;&lt;code&gt;Kubernetes&lt;/code&gt;と機能が被っていることがよくわかる.&lt;/del&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1&lt;/strong&gt;: 掲示板アプリを動かすための簡単な&lt;code&gt;Stack&lt;/code&gt;ファイルをつくってみる.&lt;br&gt;
任意の場所に&lt;code&gt;bb-stack.yaml&lt;/code&gt;というファイルを以下の内容で作成する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;3.7&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;bb-app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;bulletinboard:1.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;8000:8080&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この&lt;code&gt;Swarm&lt;/code&gt;YAMLファイルでは1つのオブジェクトを定義している:&lt;br&gt;
&lt;code&gt;service&lt;/code&gt;は中身が同じでスケーリングが可能な複数のコンテナを定義する.&lt;br&gt;
今回はコンテナ数が1つで(デフォルト値), そのコンテナはPart 2で作成した&lt;code&gt;image&lt;/code&gt;(&lt;strong&gt;bulletinboard:1.0&lt;/strong&gt;)を元に起動することが記述されており,
さらにホスト(開発マシン)の8000番ポートとコンテナの8080番ポートを通信させるよう設定している.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;Kubernetes&lt;/code&gt;の&lt;code&gt;Service&lt;/code&gt;と&lt;code&gt;Swarm&lt;/code&gt;の&lt;code&gt;service&lt;/code&gt;は違うことに注意!&lt;/strong&gt;&lt;br&gt;
serviceという同じ名前ではあるが, 2つのオーケストレーターではこれらはまったく違うものとして扱われる.&lt;br&gt;
&lt;code&gt;Swarm&lt;/code&gt;ではコンテナの起動/管理設定とネットワーク設定を同じ1つの&lt;code&gt;service&lt;/code&gt;で定義するが,&lt;br&gt;
&lt;code&gt;Kubernetes&lt;/code&gt;ではこれらは&lt;code&gt;Deployment&lt;/code&gt;と&lt;code&gt;Service&lt;/code&gt;という2つのコンポーネントで定義する.&lt;br&gt;
[追加]混同を避けるため, この意訳では&lt;code&gt;Swarm&lt;/code&gt;のものは&lt;code&gt;service&lt;/code&gt;(小文字)と表記する.&lt;/p&gt;
&lt;h3 id="deploying-and-checking-your-application"&gt;Deploying and Checking Your Application
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/part4/#deploying-and-checking-your-application" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/get-started/part4/#deploying-and-checking-your-application&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;1&lt;/strong&gt;: アプリを&lt;code&gt;Swarm&lt;/code&gt;にデプロイする.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# bb-stack.yamlで定義されたStackにdemoという名前をつけてデプロイ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker stack deploy -c bb-stack.yaml demo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Creating network demo_default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Creating service demo_bb-app
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;また, このとき&lt;code&gt;service&lt;/code&gt;以外に&lt;code&gt;Stack&lt;/code&gt;内で使用するデフォルトの&lt;code&gt;network&lt;/code&gt;が作成される.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2&lt;/strong&gt;: &lt;code&gt;service&lt;/code&gt;の一覧を表示して動作を確認する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# serviceの一覧を表示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker service ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ID NAME MODE REPLICAS IMAGE PORTS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;po8srxqtzf13 demo_bb-app replicated 1/1 bulletinboard:1.0 *:8000-&amp;gt;8080/tcp
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;bb-stack.yaml&lt;/code&gt;の&lt;code&gt;service&lt;/code&gt;で定義したコンテナが1台起動しており, 開発マシンの8000番ポートがコンテナの8080番ポートに転送されていることがわかる.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3&lt;/strong&gt;: 開発マシンのブラウザで http://localhost:8000/ を開く.&lt;br&gt;
&lt;img class="gallery-image" data-flex-basis="523px" data-flex-grow="218" height="1321" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-10-14-docker-04/2019-10-14-sc01.png" srcset="https://blog.uzimihsr.com/post/2019-10-14-docker-04/2019-10-14-sc01_hu_886e83223d820e4.png 800w, https://blog.uzimihsr.com/post/2019-10-14-docker-04/2019-10-14-sc01_hu_fc4a29722574e1b3.png 1600w, https://blog.uzimihsr.com/post/2019-10-14-docker-04/2019-10-14-sc01_hu_da2c0313168ca261.png 2400w, https://blog.uzimihsr.com/post/2019-10-14-docker-04/2019-10-14-sc01.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;Part 2でコンテナを単体で動かしたときと同じ画面が表示される.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4&lt;/strong&gt;: 動作確認ができたら, アプリを削除する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Stack(demo)を削除&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker stack rm demo
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="conclusion"&gt;Conclusion
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/part4/#conclusion" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/get-started/part4/#conclusion&lt;/a&gt;&lt;br&gt;
このパートでは, &lt;code&gt;Docker Desktop&lt;/code&gt;を用いて開発マシン上の&lt;code&gt;Swarm&lt;/code&gt;に掲示板アプリをデプロイした.&lt;br&gt;
この程度ではまだ&lt;code&gt;Swarm&lt;/code&gt;を使いこなしているとは言えないが, 最初のステップは既にクリアしている.&lt;br&gt;
環境はすでに開発マシンに構築できているので, 同じ手順で&lt;code&gt;Swarm&lt;/code&gt;の機能をさらに活用すればアプリに他のコンポーネントを追加することもできる.&lt;/p&gt;
&lt;p&gt;また, このパートではアプリのデプロイに加えて&lt;code&gt;Stack&lt;/code&gt;ファイルでのアプリ定義も行った.&lt;br&gt;
アプリを動作させるために必要なすべての情報がシンプルなファイルに記述されているため, バージョンコントロール(Gitなど)で管理したり, 他の開発者と簡単に共有することができる.&lt;br&gt;
また, &lt;code&gt;Stack&lt;/code&gt;ファイルがあればアプリを異なるクラスタに配置することも簡単に行うことができる(例: テスト環境と本番環境を分ける場合など).&lt;br&gt;
[追加]まとめの文章もPart 3とほとんど一緒. 仕事でもほとんど使わないし正直飛ばしたほうがよかったかも&amp;hellip;&lt;/p&gt;</description></item><item><title>Docker Quickstartを超意訳する Part 3</title><link>https://blog.uzimihsr.com/post/2019-10-13-docker-03/</link><pubDate>Sun, 13 Oct 2019 22:48:55 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2019-10-13-docker-03/</guid><description>&lt;h2 id="kubernetesでのデプロイ"&gt;Kubernetesでのデプロイ
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2019-10-12-docker-02/" target="_blank" rel="noopener"
 &gt;Part 2&lt;/a&gt;ではアプリのコンテナ化を行った.&lt;br&gt;
Part 3ではKubernetesにアプリをデプロイしてみる.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="get-started-part-3-deploying-to-kubernetes"&gt;Get Started, Part 3: Deploying to Kubernetes
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/part3/" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/get-started/part3/&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="もくじ"&gt;もくじ
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;Prerequisites&lt;/li&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Describing Apps Using Kubernetes YAML&lt;/li&gt;
&lt;li&gt;Deploying and Checking Your Application&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="prerequisites"&gt;Prerequisites
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/part3/#prerequisites" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/get-started/part3/#prerequisites&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2019-10-12-docker-02/" target="_blank" rel="noopener"
 &gt;Part 2&lt;/a&gt;でのアプリのコンテナ化ができていること.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Docker Desktop&lt;/code&gt;上で&lt;code&gt;Kubernetes&lt;/code&gt;が動作していること
&lt;ul&gt;
&lt;li&gt;動作していない場合は&lt;a class="link" href="https://uzimihsr.github.io/post/2019-10-11-docker-01/#enable-kubernetes" target="_blank" rel="noopener"
 &gt;Part 1&lt;/a&gt;の手順に従う.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="introduction"&gt;Introduction
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/part3/#introduction" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/get-started/part3/#introduction&lt;/a&gt;&lt;br&gt;
前のパートではアプリのコンポーネントを単独のコンテナとして動作させていたが, ここからはそれらをコンテナオーケストレーター(&lt;code&gt;Kubernetes&lt;/code&gt;)で管理する.&lt;br&gt;
&lt;code&gt;Kubernetes&lt;/code&gt;はコンテナアプリのスケーリング, ネットワーク, セキュリティ, メンテナンスのための, コンテナ自体に最初から入っている機能よりも強力な様々なツールを提供する.&lt;/p&gt;
&lt;p&gt;前のパートで作成したコンテナアプリが&lt;code&gt;Kubernetes&lt;/code&gt;上で動作することを検証するために, 今回は本番環境の&lt;code&gt;Kubernetes&lt;/code&gt;クラスタではなく&lt;code&gt;Docker Desktop&lt;/code&gt;でセットアップした開発マシンの&lt;code&gt;Kubernetes&lt;/code&gt;を使用する.&lt;br&gt;
&lt;code&gt;Docker Desktop&lt;/code&gt;で構築した&lt;code&gt;Kubernetes&lt;/code&gt;環境は本番環境のクラスタで動作するものと同じ機能を持ち, 開発マシンから容易にアクセスできるという利点がある.&lt;/p&gt;
&lt;h3 id="describing-apps-using-kubernetes-yaml"&gt;Describing Apps Using Kubernetes YAML
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/part3/#describing-apps-using-kubernetes-yaml" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/get-started/part3/#describing-apps-using-kubernetes-yaml&lt;/a&gt;&lt;br&gt;
&lt;code&gt;Kubernetes&lt;/code&gt;では全てのコンテナはリソースを共有する複数のコンテナによって構成される&lt;code&gt;Pod&lt;/code&gt;という単位で運用される.&lt;br&gt;
また, 実際のアプリで開発者が&lt;code&gt;Pod&lt;/code&gt;を1つずつ運用することは稀で, &lt;code&gt;Kubernetes&lt;/code&gt;が自動でスケーリングなどの管理を行う複数の&lt;code&gt;Pod&lt;/code&gt;で構成される&lt;code&gt;Deployment&lt;/code&gt;という単位で運用されることが多い.&lt;br&gt;
全ての&lt;code&gt;Kubernetes&lt;/code&gt;オブジェクトは&lt;code&gt;Kubernetes&lt;/code&gt;YAMLファイルと呼ばれるマニフェストファイルで定義される.&lt;br&gt;
このファイルには&lt;code&gt;Kubernetes&lt;/code&gt;アプリを構成するコンポーネントと設定の情報が記述されていて, &lt;code&gt;Kubernetes&lt;/code&gt;環境でのアプリの作成/削除に使用される.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1&lt;/strong&gt;: Part 1では簡単な内容の&lt;code&gt;Kubernetes&lt;/code&gt;YAMLファイルを作成したが, 今回は掲示板アプリを動かすためにもう少し詳細なものをつくってみる.&lt;br&gt;
任意の場所に&lt;code&gt;bb.yaml&lt;/code&gt;というファイルを以下の内容で作成する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;apps/v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Deployment&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;bb-demo&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;default&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;replicas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;matchLabels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;bb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;web&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;bb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;web&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;bb-site&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;bulletinboard:1.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Service&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;bb-entrypoint&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;default&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;NodePort&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;bb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;web&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8080&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targetPort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8080&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;nodePort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;30001&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この&lt;code&gt;Kuberetes&lt;/code&gt;YAMLファイルには&lt;code&gt;---&lt;/code&gt;で区切られた2つのオブジェクトが記述されている:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Deployment&lt;/code&gt;は中身が同じでスケーリングが可能な複数の&lt;code&gt;Pod&lt;/code&gt;を定義する. &lt;br&gt;このファイルでは&lt;code&gt;replica&lt;/code&gt;(同じ&lt;code&gt;Pod&lt;/code&gt;の数)が1つであり,&lt;br&gt;その&lt;code&gt;Pod&lt;/code&gt;がPart 2で作成した&lt;code&gt;image&lt;/code&gt;(&lt;strong&gt;bulletinboard:1.0&lt;/strong&gt;)から起動するコンテナを1つ持つことが定義されている.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Service&lt;/code&gt;は&lt;code&gt;Pod&lt;/code&gt;に関する通信設定を定義する. &lt;br&gt;このファイルではホスト(ここでは開発マシン)の30001番ポートを&lt;code&gt;Pod&lt;/code&gt;の8080番ポートと通信させる&lt;code&gt;NodePort Service&lt;/code&gt;を定義し, 掲示板アプリに接続できるようにしている.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;はじめはこの&lt;code&gt;Kubernetes&lt;/code&gt;YAMLファイルが長く, 複雑なものに見えるかもしれないが, 実際はどれも同じパターンで記述されている:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;apiVersion&lt;/code&gt;でこのオブジェクトをパースする&lt;code&gt;Kubernetes&lt;/code&gt;APIのバージョンを指定&lt;/li&gt;
&lt;li&gt;&lt;code&gt;kind&lt;/code&gt;でこのオブジェクトの種類を定義&lt;/li&gt;
&lt;li&gt;&lt;code&gt;metadata&lt;/code&gt;でオブジェクトの名前などの情報(メタデータ)を定義&lt;/li&gt;
&lt;li&gt;&lt;code&gt;spec&lt;/code&gt;でオブジェクトのパラメータと設定を記述&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="deploying-and-checking-your-application"&gt;Deploying and Checking Your Application
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/part3/#deploying-and-checking-your-application" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/get-started/part3/#deploying-and-checking-your-application&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;1&lt;/strong&gt;: &lt;code&gt;bb.yaml&lt;/code&gt;があるディレクトリに移動して, &lt;code&gt;Kubernetes&lt;/code&gt;にアプリをデプロイする.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# bb.yamlがあることを確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bb.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# bb.yamlに記述された内容のリソースを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f bb.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps/bb-demo created
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service/bb-entrypoint created
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;2&lt;/strong&gt;: 起動している&lt;code&gt;Deployment&lt;/code&gt;の一覧を表示して動作を確認する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Deploymentsの一覧を表示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get deployments
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY UP-TO-DATE AVAILABLE AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bb-demo 1/1 &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; 93s
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;bb.yaml&lt;/code&gt;で定義した&lt;code&gt;Deployment&lt;/code&gt;(&lt;strong&gt;bb-demo&lt;/strong&gt;)で1つの&lt;code&gt;Pod&lt;/code&gt;が正常に動作していることがわかる.&lt;/p&gt;
&lt;p&gt;同様に&lt;code&gt;Service&lt;/code&gt;についても動作確認を行う.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Serviceの一覧を表示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get services
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bb-entrypoint NodePort 10.102.111.61 &amp;lt;none&amp;gt; 8080:30001/TCP 6m11s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubernetes ClusterIP 10.96.0.1 &amp;lt;none&amp;gt; 443/TCP 34d
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Kubernetes&lt;/code&gt;のデフォルトで使用される&lt;code&gt;Service&lt;/code&gt;の他に, &lt;code&gt;bb.yaml&lt;/code&gt;で定義した&lt;code&gt;Service&lt;/code&gt;(&lt;strong&gt;bb-entrypoint&lt;/strong&gt;)が動作し, 30001/TCPへのリクエストを受ける設定になっていることがわかる.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3&lt;/strong&gt;: 開発マシンのブラウザで http://localhost:30001/ を開く.&lt;br&gt;
&lt;img alt="掲示板アプリの画面" class="gallery-image" data-flex-basis="525px" data-flex-grow="219" height="1315" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-10-13-docker-03/2019-10-13-sc01.png" srcset="https://blog.uzimihsr.com/post/2019-10-13-docker-03/2019-10-13-sc01_hu_e9ca606a7969db67.png 800w, https://blog.uzimihsr.com/post/2019-10-13-docker-03/2019-10-13-sc01_hu_814657986c5b52f9.png 1600w, https://blog.uzimihsr.com/post/2019-10-13-docker-03/2019-10-13-sc01_hu_adee83d92df74a08.png 2400w, https://blog.uzimihsr.com/post/2019-10-13-docker-03/2019-10-13-sc01.png 2880w" width="2880"&gt;&lt;br&gt;
Part 2でコンテナを単体で実行したときと同じ画面が確認できる.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4&lt;/strong&gt;: 動作確認が完了したら, アプリを削除する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# bb.yamlに記述された内容のリソースを削除&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl delete -f bb.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deployment.apps &lt;span class="s2"&gt;&amp;#34;bb-demo&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service &lt;span class="s2"&gt;&amp;#34;bb-entrypoint&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="conclusion"&gt;Conclusion
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/part3/#conclusion" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/get-started/part3/#conclusion&lt;/a&gt;&lt;br&gt;
このパートでは, &lt;code&gt;Docker Desktop&lt;/code&gt;を用いて開発マシン上の&lt;code&gt;Kubernetes&lt;/code&gt;に掲示板アプリをデプロイした.&lt;br&gt;
この程度ではまだ&lt;code&gt;Kubernetes&lt;/code&gt;を使いこなしているとは言えないが, 最初のステップは既にクリアしている.&lt;br&gt;
環境はすでに開発マシンに構築できているので, 同じ手順で&lt;code&gt;Kubernetes&lt;/code&gt;の機能をさらに活用すればアプリに他のコンポーネントを追加することもできる.&lt;/p&gt;
&lt;p&gt;また, このパートではアプリのデプロイに加えて&lt;code&gt;Kubernetes&lt;/code&gt;YAMLファイルでのアプリ定義も行った.&lt;br&gt;
アプリを動作させるために必要なすべての情報がシンプルなファイルに記述されているため, バージョンコントロール(Gitなど)で管理したり, 他の開発者と簡単に共有することができる.&lt;br&gt;
また, &lt;code&gt;Kubernetes&lt;/code&gt;YAMLファイルがあればアプリを異なるクラスタに配置することも簡単に行うことができる(例: テスト環境と本番環境を分ける場合など).&lt;br&gt;
[追加]俗に言う&lt;code&gt;Infrastructure as Code&lt;/code&gt;というもの. &lt;code&gt;Kubernetes&lt;/code&gt;ではアプリの実行に必要なインフラをコードとして管理することで動作環境への依存をなくしている.&lt;/p&gt;</description></item><item><title>Docker Quickstartを超意訳する Part 2</title><link>https://blog.uzimihsr.com/post/2019-10-12-docker-02/</link><pubDate>Sat, 12 Oct 2019 22:43:36 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2019-10-12-docker-02/</guid><description>&lt;h2 id="アプリのコンテナ化"&gt;アプリのコンテナ化
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2019-10-11-docker-01/" target="_blank" rel="noopener"
 &gt;Part 1&lt;/a&gt;ではDockerについて簡単な説明と環境構築を行った.&lt;br&gt;
Part 2では実際にアプリをコンテナ化してみる.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="get-started-part-2-containerizing-an-application"&gt;Get Started, Part 2: Containerizing an Application
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/part2/" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/get-started/part2/&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="もくじ"&gt;もくじ
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;Prerequisites&lt;/li&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Setting Up&lt;/li&gt;
&lt;li&gt;Build and Test Your Image&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="prerequisites"&gt;Prerequisites
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/part2/#prerequisites" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/get-started/part2/#prerequisites&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;このパートに入る前に, &lt;a class="link" href="https://uzimihsr.github.io/post/2019-10-11-docker-01/" target="_blank" rel="noopener"
 &gt;Part 1&lt;/a&gt;の内容を完了していること.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="introduction"&gt;Introduction
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/part2/#introduction" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/get-started/part2/#introduction&lt;/a&gt;&lt;br&gt;
&lt;code&gt;Docker Desktop&lt;/code&gt;のおかげでコンテナオーケストレーターが既にセットアップされているので, コンテナアプリ開発の準備はできている.&lt;br&gt;
コンテナアプリ開発は一般的に以下のフローに沿って行う.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;作成したいアプリの各コンポーネントについて&lt;code&gt;image&lt;/code&gt;を作成し, それを元にコンテナの作成とテストを行う.&lt;/li&gt;
&lt;li&gt;コンテナとインフラの設定を組み合わせたアプリを&lt;code&gt;Docker Stack&lt;/code&gt;ファイルまたは&lt;code&gt;Kubernetes&lt;/code&gt;のYAMLファイルで定義する.&lt;/li&gt;
&lt;li&gt;コンテナ化したアプリをテスト, 共有, デプロイする.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;このパートでは上記フローの1つめに着目し, コンテナの元になる&lt;code&gt;image&lt;/code&gt;の作成を行う.&lt;br&gt;
Part 1で学んだように&lt;code&gt;image&lt;/code&gt;はコンテナ化されたプロセスを動かすためのプライベートなファイルシステムを提供するものであるから, 開発者はアプリケーションの動作に必要なものだけを内包する&lt;code&gt;image&lt;/code&gt;を作成すれば良い.&lt;/p&gt;
&lt;p&gt;コンテナ化された開発環境ではアプリの依存関係をすべて&lt;code&gt;image&lt;/code&gt;に閉じ込めてしまうので, 開発マシンに&lt;code&gt;Docker&lt;/code&gt;以外のものをインストールする必要がない.&lt;br&gt;
したがって, 同じマシン上で複数のアプリを開発する際に異なるアプリ間での依存関係の競合がなくなる.&lt;br&gt;
そのため, &lt;code&gt;image&lt;/code&gt;の作成方法さえ取得してしまえばコンテナ化された開発環境は一般的な開発環境よりも構築が容易で使いやすい.&lt;/p&gt;
&lt;h3 id="setting-up"&gt;Setting Up
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/part2/#setting-up" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/get-started/part2/#setting-up&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1&lt;/strong&gt;: GitHubから&lt;a class="link" href="https://github.com/docker-training/node-bulletin-board" target="_blank" rel="noopener"
 &gt;サンプルプロジェクト&lt;/a&gt;をcloneしてくる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# リポジトリをclone&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git clone -b v1 https://github.com/docker-training/node-bulletin-board
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Cloning into &lt;span class="s1"&gt;&amp;#39;node-bulletin-board&amp;#39;&lt;/span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;remote: Enumerating objects: 190, &lt;span class="k"&gt;done&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;remote: Counting objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;190/190&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;remote: Compressing objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;132/132&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;remote: Total &lt;span class="m"&gt;190&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;delta 79&lt;span class="o"&gt;)&lt;/span&gt;, reused &lt;span class="m"&gt;158&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;delta 55&lt;span class="o"&gt;)&lt;/span&gt;, pack-reused &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Receiving objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;190/190&lt;span class="o"&gt;)&lt;/span&gt;, 194.66 KiB &lt;span class="p"&gt;|&lt;/span&gt; 432.00 KiB/s, &lt;span class="k"&gt;done&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Resolving deltas: 100% &lt;span class="o"&gt;(&lt;/span&gt;79/79&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# cloneしてきたリポジトリのbulletin-board-appディレクトリに移動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; node-bulletin-board/bulletin-board-app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ファイルを確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Dockerfile app.js fonts package.json server.js
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;LICENSE backend index.html readme.md site.css
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これはNode.jsで書かれた簡単な掲示板アプリケーションで, 今回はこのアプリをコンテナ化していく.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2&lt;/strong&gt;: &lt;code&gt;Dockerfile&lt;/code&gt;というファイルを見てみる. &lt;br&gt;&lt;code&gt;Dockerfile&lt;/code&gt;にはコンテナで使用するプライベートファイルシステム(&lt;code&gt;image&lt;/code&gt;)を構築するための手順と, この&lt;code&gt;image&lt;/code&gt;を元にコンテナを起動する際の情報(メタデータ)が書かれている. &lt;br&gt;今回使用する掲示板アプリの&lt;code&gt;Dockerfile&lt;/code&gt;は以下の内容になっている.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-dockerfile" data-lang="dockerfile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# node:6.11.5をベースimageとして使用&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;node:6.11.5&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# image内での作業ディレクトリを/usr/src/appに変更&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/usr/src/app&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 開発マシンのpackage.jsonをimageの作業ディレクトリにコピー&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; package.json .&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# npm(Node.jsのパッケージマネージャ)によりアプリの依存パッケージをインストール&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; npm install&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 開発マシンの現在のディレクトリの中身をimageの作業ディレクトリにコピー&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; . .&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# コンテナが起動した際に`npm start`コマンドを実行&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CMD&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;npm&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;start&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Dockerfile&lt;/code&gt;を書くことはコンテナアプリ開発の第一歩である.&lt;br&gt;
&lt;code&gt;Dockerfile&lt;/code&gt;に記載された各行のコマンドは独自の&lt;code&gt;image&lt;/code&gt;を作成するための操作を定義し, この&lt;code&gt;Dockerfile&lt;/code&gt;の場合は次の内容を定義している:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;FROM&lt;/code&gt;で既に存在する&lt;code&gt;image&lt;/code&gt;(node:6.11.5)をベースとして指定する. &lt;br&gt;&lt;a class="link" href="https://hub.docker.com/layers/node/library/node/6.11.5/images/sha256-852391892b9f2cf86cce28977a6594bb5b118d97da4b48c56ea6f5fe18b975de" target="_blank" rel="noopener"
 &gt;node:6.11.5&lt;/a&gt;はNode.jsのベンダーによってビルド, &lt;code&gt;Docker&lt;/code&gt;チームによって検証された高品質な&lt;code&gt;official image&lt;/code&gt;であり, node 6.11.5のインタプリタと基本的な依存パッケージを内包している.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WORKDIR&lt;/code&gt;で&lt;code&gt;image&lt;/code&gt;内の作業ディレクトリを**/usr/src/app**に指定する. &lt;br&gt;以降のコマンドは全てこのディレクトリで行われる. このディレクトリは開発マシンのディレクトリとは無関係である. &lt;br&gt;[追加]指定したディレクトリが存在しない場合は自動で生成される.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;COPY&lt;/code&gt;で開発マシンの&lt;strong&gt;package.json&lt;/strong&gt;を&lt;code&gt;image&lt;/code&gt;の現在のディレクトリにコピーする. &lt;br&gt;今回の場合は**/usr/src/app/package.json**に配置される.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;RUN&lt;/code&gt;で&lt;code&gt;npm install&lt;/code&gt;コマンドを&lt;code&gt;image&lt;/code&gt;内で実行する. &lt;br&gt;このコマンドは現在のディレクトリにある&lt;strong&gt;package.json&lt;/strong&gt;(依存関係が定義されたファイル)を読み込み, アプリの依存パッケージをインストールする.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;COPY&lt;/code&gt;で開発マシンの残りのソースコードを&lt;code&gt;image&lt;/code&gt;の現在のディレクトリにコピーする.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以上のコマンドは一般的な開発環境でNode.jsのアプリをインストールする際とほぼ同じである.&lt;br&gt;
しかし&lt;code&gt;Dockerfile&lt;/code&gt;でこれらを定義することで, 開発マシンの環境には一切影響を与えずに必要な操作を全て&lt;code&gt;image&lt;/code&gt;に閉じ込めることができる.&lt;br&gt;
[追加]この開発マシンにNode.jsがなくても&lt;code&gt;image&lt;/code&gt;さえあればアプリが動く. すごい.&lt;/p&gt;
&lt;p&gt;上記手順はファイルシステムの構築方法を定義しているが, この&lt;code&gt;Dockerfile&lt;/code&gt;にはもう1行コマンドが存在する.&lt;br&gt;
&lt;code&gt;CMD&lt;/code&gt;はこの&lt;code&gt;image&lt;/code&gt;を元にコンテナが起動する際のメタデータを定義する.&lt;br&gt;
この例では, この&lt;code&gt;image&lt;/code&gt;を使用して実行するプロセスが&lt;code&gt;npm start&lt;/code&gt;コマンドであることを示している.&lt;br&gt;
[追加]&lt;code&gt;npm start&lt;/code&gt;はアプリを実行するコマンド.&lt;/p&gt;
&lt;p&gt;上記は&lt;code&gt;FROM&lt;/code&gt;でベースとなる&lt;code&gt;image&lt;/code&gt;を指定し, その後にファイルシステムの構築に必要なコマンドを1行ずつ記述, 最後にメタデータを定義するというシンプルな&lt;code&gt;Dockerfile&lt;/code&gt;の良いお手本である.&lt;br&gt;
また, この例で示したのは&lt;code&gt;Dockerfile&lt;/code&gt;で使用できるコマンドのほんの一部であり, その他のコマンドについては&lt;a class="link" href="https://docs.docker.com/engine/reference/builder/" target="_blank" rel="noopener"
 &gt;Dockerfile reference&lt;/a&gt;で説明されている.&lt;/p&gt;
&lt;h3 id="build-and-test-your-image"&gt;Build and Test Your Image
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/part2/#build-and-test-your-image" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/get-started/part2/#build-and-test-your-image&lt;/a&gt;&lt;br&gt;
ソースコードと&lt;code&gt;Dockerfile&lt;/code&gt;が用意できたので, いよいよ&lt;code&gt;image&lt;/code&gt;をビルドして, それを元にコンテナが想定通り動作するか確認する.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1&lt;/strong&gt;: &lt;strong&gt;node-bulletin-board/bulletin-board-app&lt;/strong&gt; ディレクトリにいることを確認し, 掲示板アプリの&lt;code&gt;image&lt;/code&gt;をビルドする.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 現在のディレクトリを確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;pwd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/path/to/node-bulletin-board/bulletin-board-app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 現在のディレクトリ(.)にあるDockerfileを使用してimage(bulletinboard:1.0)をビルド&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image build -t bulletinboard:1.0 .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ビルド時のログを見ると&lt;code&gt;Dockerfile&lt;/code&gt;に定義された操作を1行ずつ読み込んで実行し,&lt;br&gt;
作成した&lt;code&gt;image&lt;/code&gt;にタグ(&lt;strong&gt;bulletinboard:1.0&lt;/strong&gt;)をつけていることがわかる.&lt;br&gt;
[追加]ビルド時に&lt;code&gt;-t&lt;/code&gt;オプションでリポジトリ名:タグを指定できる.&lt;br&gt;
&lt;code&gt;image&lt;/code&gt;は基本的にリポジトリ名とタグで管理され, リポジトリ名はバージョンに依存しないその&lt;code&gt;image&lt;/code&gt;の名前, タグはバージョンなどの情報を表す.&lt;br&gt;
(例: node:6.11.5の場合はnodeがリポジトリ名, 6.11.5がタグ)&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;ビルド時のログ(クリックで展開)&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image build -t bulletinboard:1.0 .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Sending build context to Docker daemon 45.57kB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 1/6 : FROM node:6.11.5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;6.11.5: Pulling from library/node
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;85b1f47fba49: Pull &lt;span class="nb"&gt;complete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ba6bd283713a: Pull &lt;span class="nb"&gt;complete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;817c8cd48a09: Pull &lt;span class="nb"&gt;complete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;47cc0ed96dc3: Pull &lt;span class="nb"&gt;complete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;8888adcbd08b: Pull &lt;span class="nb"&gt;complete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;6f2de60646b9: Pull &lt;span class="nb"&gt;complete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1666693bf996: Pull &lt;span class="nb"&gt;complete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2fe410df7942: Pull &lt;span class="nb"&gt;complete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Digest: sha256:fe109b92edafd9821fbc1c80fd7587a1b4e1ff76fec3af675869e23e50bbf45b
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Status: Downloaded newer image &lt;span class="k"&gt;for&lt;/span&gt; node:6.11.5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; 852391892b9f
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 2/6 : WORKDIR /usr/src/app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; Running in 7d1414939508
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Removing intermediate container 7d1414939508
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; 5d0751457bd4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 3/6 : COPY package.json .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; 50081a240492
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 4/6 : RUN npm install
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; Running in 3c9f159d46c7
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;vue-event-bulletin@1.0.0 /usr/src/app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;+-- body-parser@1.19.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; +-- bytes@3.1.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; +-- content-type@1.0.4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; +-- debug@2.6.9
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;-- ms@2.0.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; +-- depd@1.1.2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; +-- http-errors@1.7.2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; +-- inherits@2.0.3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;-- toidentifier@1.0.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; +-- iconv-lite@0.4.24
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;-- safer-buffer@2.1.2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; +-- on-finished@2.3.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;-- ee-first@1.1.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; +-- qs@6.7.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; +-- raw-body@2.4.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;-- unpipe@1.0.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;-- type-is@1.6.18
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; +-- media-typer@0.3.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;-- mime-types@2.1.24
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;-- mime-db@1.40.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;+-- bootstrap@3.4.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;+-- ejs@2.7.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;+-- errorhandler@1.5.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; +-- accepts@1.3.7
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;-- negotiator@0.6.2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;-- escape-html@1.0.3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;+-- express@4.17.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; +-- array-flatten@1.1.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; +-- content-disposition@0.5.3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; +-- cookie@0.4.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; +-- cookie-signature@1.0.6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; +-- encodeurl@1.0.2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; +-- etag@1.8.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; +-- finalhandler@1.1.2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; +-- fresh@0.5.2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; +-- merge-descriptors@1.0.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; +-- methods@1.1.2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; +-- parseurl@1.3.3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; +-- path-to-regexp@0.1.7
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; +-- proxy-addr@2.0.5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; +-- forwarded@0.1.2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;-- ipaddr.js@1.9.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; +-- range-parser@1.2.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; +-- safe-buffer@5.1.2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; +-- send@0.17.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; +-- destroy@1.0.4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; +-- mime@1.6.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;-- ms@2.1.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; +-- serve-static@1.14.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; +-- setprototypeof@1.1.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; +-- statuses@1.5.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; +-- utils-merge@1.0.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;-- vary@1.1.2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;+-- method-override@2.3.10
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;+-- morgan@1.9.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; +-- basic-auth@2.0.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;-- on-headers@1.0.2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;+-- vue@1.0.28
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;-- envify@3.4.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; +-- jstransform@11.0.3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; +-- base62@1.2.8
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; +-- commoner@0.10.8
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; +-- commander@2.20.3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; +-- detective@4.7.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; +-- acorn@5.7.3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;-- defined@1.0.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; +-- glob@5.0.15
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; +-- inflight@1.0.6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;-- wrappy@1.0.2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; +-- minimatch@3.0.4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;-- brace-expansion@1.1.11
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; +-- balanced-match@1.0.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;-- concat-map@0.0.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; +-- once@1.4.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;-- path-is-absolute@1.0.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; +-- graceful-fs@4.2.2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; +-- mkdirp@0.5.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;-- minimist@0.0.8
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; +-- private@0.1.8
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; +-- q@1.5.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;-- recast@0.11.23
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; +-- ast-types@0.9.6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; +-- esprima@3.1.3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;-- source-map@0.5.7
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; +-- esprima-fb@15001.1.0-dev-harmony-fb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; +-- object-assign@2.1.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;-- source-map@0.4.4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;-- amdefine@1.0.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;-- through@2.3.8
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sb"&gt;`&lt;/span&gt;-- vue-resource@0.1.17
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm WARN vue-event-bulletin@1.0.0 No repository field.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Removing intermediate container 3c9f159d46c7
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; 64d35ff348c3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 5/6 : COPY . .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; c8fa377b131a
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 6/6 : CMD &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;npm&amp;#34;&lt;/span&gt;, &lt;span class="s2"&gt;&amp;#34;start&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; Running in f0aeac57fc19
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Removing intermediate container f0aeac57fc19
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; 06f7fe6f1ca0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Successfully built 06f7fe6f1ca0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Successfully tagged bulletinboard:1.0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;[追加]ホスト(今回は開発マシン)にある&lt;code&gt;image&lt;/code&gt;の一覧は&lt;code&gt;docker image ls&lt;/code&gt;で確認できる.&lt;br&gt;
今回の場合は&lt;strong&gt;bulletinboard:1.0&lt;/strong&gt;とそのベースに使用したnode:6.11.5が存在していることがわかる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# imageの一覧を表示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;REPOSITORY TAG IMAGE ID CREATED SIZE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bulletinboard 1.0 06f7fe6f1ca0 &lt;span class="m"&gt;51&lt;/span&gt; minutes ago 681MB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;node 6.11.5 852391892b9f &lt;span class="m"&gt;23&lt;/span&gt; months ago 662MB
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;2&lt;/strong&gt;: 作成した&lt;code&gt;image&lt;/code&gt;を使用してコンテナを起動する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ホストの8000番ポートをコンテナ(bb)の8000番ポートに割り当て, &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# image(bulletinboard:1.0)を用いてコンテナ(bb)をデタッチドモードで起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run --publish 8000:8080 --detach --name bb bulletinboard:1.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bee46e68b8cf8db5c946060f887a9a4f5bcca18e6ac6958c76d35f34d3f330b5
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここでは複数のフラグ(オプション)を組み合わせて使用している:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--publish&lt;/code&gt;でホスト(この場合は開発マシン)の8000番ポートとコンテナの8000番ポートを疎通させるよう指定する. &lt;br&gt;コンテナにはそれぞれ独自のポートが複数あり, ネットワークからコンテナにアクセスするためには使用するポートをこのように指定する必要がある. &lt;br&gt;コンテナの指定していないポートを使う通信はデフォルトで設定されているファイアウォールによりすべて遮断される. &lt;br&gt;[追加]&lt;code&gt;-p&lt;/code&gt;オプションでも同じことができる.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--detach&lt;/code&gt;でこのコンテナをバックグラウンドで起動するよう指定する. &lt;br&gt;[追加]&lt;code&gt;-d&lt;/code&gt;オプションでも同じ. この起動方法を&lt;code&gt;デタッチドモード&lt;/code&gt;という.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--name&lt;/code&gt;でこのコンテナに名前(bb)をつける. この名前は以降のコマンドでこのコンテナを指定するときに使用できる.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;また, 上記のコマンドでは実行した際にコンテナでどのプロセスを実行するかの指定がされていない.&lt;br&gt;
これは&lt;code&gt;Dockerfile&lt;/code&gt;の&lt;code&gt;CMD&lt;/code&gt;でコンテナ起動時に自動実行するプロセス(&lt;code&gt;npm start&lt;/code&gt;)が指定されていて, 改めて指定する必要が無いためである.&lt;/p&gt;
&lt;p&gt;[追加]起動中のコンテナの一覧は&lt;code&gt;docker container ls&lt;/code&gt;で確認できる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 起動しているコンテナ一覧を表示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cc1a42172625 bulletinboard:1.0 &lt;span class="s2"&gt;&amp;#34;npm start&amp;#34;&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; seconds ago Up &lt;span class="m"&gt;4&lt;/span&gt; seconds 0.0.0.0:8000-&amp;gt;8080/tcp bb
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;3&lt;/strong&gt;: http://localhost:8000 をブラウザで開き, 掲示板アプリが実際に起動していることを確認する.&lt;br&gt;
&lt;img alt="掲示板アプリの画面" class="gallery-image" data-flex-basis="523px" data-flex-grow="218" height="1321" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-10-12-docker-02/2019-10-12-sc01.png" srcset="https://blog.uzimihsr.com/post/2019-10-12-docker-02/2019-10-12-sc01_hu_b175e9736c8680b2.png 800w, https://blog.uzimihsr.com/post/2019-10-12-docker-02/2019-10-12-sc01_hu_96649ea0c6fbe202.png 1600w, https://blog.uzimihsr.com/post/2019-10-12-docker-02/2019-10-12-sc01_hu_5c52fe2fc505afe8.png 2400w, https://blog.uzimihsr.com/post/2019-10-12-docker-02/2019-10-12-sc01.png 2880w" width="2880"&gt;&lt;br&gt;
ここまで来ればアプリの動作検証に必要な任意の作業(例: 単体テストの実行)を行うことができる.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4&lt;/strong&gt;: 掲示板コンテナが問題なく動作することを確認したら, このコンテナを削除する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# コンテナ(bb)を強制的に削除&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container rm --force bb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bb
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;[追加]&lt;code&gt;--force&lt;/code&gt;を指定するとコンテナがプロセスを実行中でも強制的にコンテナを削除することができる.&lt;br&gt;
また, コンテナを削除せず停止だけ行いたい場合は&lt;code&gt;docker container stop&lt;/code&gt;を使用する. また, &lt;code&gt;docker container start&lt;/code&gt;で停止しているコンテナを起動できる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# コンテナ(bb)を停止&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container stop bb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 停止しているものも含め全てのコンテナを表示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container ls -a
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cc1a42172625 bulletinboard:1.0 &lt;span class="s2"&gt;&amp;#34;npm start&amp;#34;&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; minutes ago Exited &lt;span class="o"&gt;(&lt;/span&gt;0&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="m"&gt;32&lt;/span&gt; seconds ago bb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 停止しているコンテナ(bb)を起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container start bb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 起動しているコンテナ一覧を表示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cc1a42172625 bulletinboard:1.0 &lt;span class="s2"&gt;&amp;#34;npm start&amp;#34;&lt;/span&gt; &lt;span class="m"&gt;6&lt;/span&gt; minutes ago Up &lt;span class="m"&gt;12&lt;/span&gt; seconds 0.0.0.0:8000-&amp;gt;8080/tcp bb
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="conclusion"&gt;Conclusion
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/part2/#conclusion" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/get-started/part2/#conclusion&lt;/a&gt;&lt;br&gt;
このパートでは簡単なアプリケーションのコンテナ化を行い, コンテナ化したアプリが正常に動作することを確認した.&lt;br&gt;
次は&lt;code&gt;Kubernetes&lt;/code&gt;形式のYAMLファイルでコンテナの起動/管理方法を定義して&lt;code&gt;Kubernetes&lt;/code&gt;上で動作させるか(Part 3で説明), または&lt;code&gt;Stack&lt;/code&gt;ファイルを記述してこのパートと同じ内容を&lt;code&gt;Swarm&lt;/code&gt;上で行う(Part 4で説明).&lt;/p&gt;</description></item><item><title>Docker Quickstartを超意訳する Part 1</title><link>https://blog.uzimihsr.com/post/2019-10-11-docker-01/</link><pubDate>Fri, 11 Oct 2019 23:31:23 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2019-10-11-docker-01/</guid><description>&lt;h2 id="kubernetesの前にdockerだ"&gt;Kubernetesの前にDockerだ!
&lt;/h2&gt;&lt;p&gt;仕事でコンテナオーケストレーションシステムの&lt;a class="link" href="https://kubernetes.io/ja/" target="_blank" rel="noopener"
 &gt;Kubernetes&lt;/a&gt;に触れる機会が多い.&lt;br&gt;
しかし, その中で使われる&lt;a class="link" href="https://www.docker.com/" target="_blank" rel="noopener"
 &gt;Docker&lt;/a&gt;コンテナについてそもそもよくわかっておらず,&lt;br&gt;
いつもなんとなくで済ましているので公式のクイックスタートガイドを読んでみる.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="はじめに"&gt;はじめに
&lt;/h2&gt;&lt;p&gt;この記事は&lt;a class="link" href="https://uzimihsr.github.io/post/2019-10-10-docker-get-started-05/" target="_blank" rel="noopener"
 &gt;悲しみ&lt;/a&gt;を乗り越えて書いている.&lt;/p&gt;
&lt;p&gt;元々読んでいたGet Startedは主に&lt;code&gt;docker-compose&lt;/code&gt;を用いたアプリのデプロイ手順を記述していたが,&lt;/p&gt;
&lt;p&gt;それを意訳している最中でドキュメントがアップデートされ,&lt;br&gt;
こんぽーずってなんだっけ?レベルで内容が削られてしまった.&lt;/p&gt;
&lt;p&gt;その代わりに&lt;code&gt;Kuberetes&lt;/code&gt;を用いてアプリをデプロイする内容が増えているので,&lt;br&gt;
もう一度意訳してみる.&lt;/p&gt;
&lt;h2 id="読むもの"&gt;読むもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Docker公式のQuickstartガイド
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.docker.com/get-started/" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/get-started/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Dockerでアプリを作る手順がまとめられている&lt;/li&gt;
&lt;li&gt;5つのパートで構成
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2019-10-11-docker-01/#get-started-part-1-orientation-and-setup" target="_blank" rel="noopener"
 &gt;Part 1&lt;/a&gt; : Dockerの環境構築&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2019-10-12-docker-02/" target="_blank" rel="noopener"
 &gt;Part 2&lt;/a&gt; : イメージの作成, コンテナの実行&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2019-10-13-docker-03/" target="_blank" rel="noopener"
 &gt;Part 3&lt;/a&gt; : Kubernetesの環境構築とアプリのデプロイ&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2019-10-14-docker-04/" target="_blank" rel="noopener"
 &gt;Part 4&lt;/a&gt; : Swarmの環境構築とアプリのデプロイ&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2019-10-15-docker-05/" target="_blank" rel="noopener"
 &gt;Part 5&lt;/a&gt; : Docker Hubでのコンテナの共有&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="超意訳する上でのルール"&gt;超意訳する上でのルール
&lt;/h2&gt;&lt;p&gt;以下のルールを守って訳していく.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;できるだけ元記事の流れに従って訳していく&lt;/li&gt;
&lt;li&gt;超意訳なので翻訳の精度は保証しない&lt;/li&gt;
&lt;li&gt;元記事に無い内容には[追加]をつける&lt;/li&gt;
&lt;li&gt;ライセンスとかよくわかんなくて怖いので画像などは自前で用意する&lt;/li&gt;
&lt;li&gt;突然記憶喪失になっても思い出せるくらいわかりやすくする&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="動作環境"&gt;動作環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;masOS Mojave 10.14&lt;/li&gt;
&lt;li&gt;Docker Desktop 2.1.0.3&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;それでは早速Part 1からはじめる.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="get-started-part-1-orientation-and-setup"&gt;Get Started, Part 1: Orientation and setup
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/get-started/&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="もくじ"&gt;もくじ
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;Docker concepts
&lt;ul&gt;
&lt;li&gt;Images and containers&lt;/li&gt;
&lt;li&gt;Containers and virtual machines&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Install Docker Desktop&lt;/li&gt;
&lt;li&gt;Enable Kubernetes&lt;/li&gt;
&lt;li&gt;Enable Docker Swarm&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="docker-concepts"&gt;Docker concepts
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/#docker-concepts" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/get-started/#docker-concepts&lt;/a&gt;&lt;br&gt;
&lt;code&gt;Docker&lt;/code&gt;とはコンテナでアプリをビルド, シェア, 実行するためのプラットフォームである.&lt;br&gt;
コンテナを使ってアプリをデプロイすることを&lt;strong&gt;コンテナ化&lt;/strong&gt;と言う.&lt;br&gt;
コンテナ自体は前からある技術だが, &lt;code&gt;Docker&lt;/code&gt;はアプリを簡単にデプロイするための新しいコンテナの活用の形である.&lt;/p&gt;
&lt;p&gt;コンテナ化は以下の特徴のため, 広く使われるようになった.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Flexible(柔軟)
&lt;ul&gt;
&lt;li&gt;どんなに複雑なアプリでもコンテナにできる.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Lightweight(軽量)
&lt;ul&gt;
&lt;li&gt;コンテナはホストのカーネルを共有/活用するため, &lt;br&gt;リソース面で仮想マシンより効率的である.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Portable(移植が容易)
&lt;ul&gt;
&lt;li&gt;コンテナはローカルでビルド, クラウドでデプロイ, どこでも実行が可能である.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Loosely coupled(疎結合)
&lt;ul&gt;
&lt;li&gt;それぞれのコンテナは自己完結/カプセル化されており, &lt;br&gt;他のコンテナに影響を与えずに交換/更新が可能である.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Scalable(スケーリングしやすい)
&lt;ul&gt;
&lt;li&gt;コンピューティング環境をまたいだコンテナの増大/分散が可能である.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Secure(安全)
&lt;ul&gt;
&lt;li&gt;ユーザーが特に設定しなくてもコンテナ内の各プロセスは分離され, &lt;br&gt;厳格に管理される.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="images-and-containers"&gt;Images and containers
&lt;/h4&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/#images-and-containers" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/get-started/#images-and-containers&lt;/a&gt;&lt;br&gt;
コンテナといっても基本的にはホストや他のコンテナから独立し, 必要なものをすべて内包した1つのプロセスに他ならない.&lt;br&gt;
ここで言う独立とは各コンテナが自身のプライベートなファイルシステムを使用することを指し, そのファイルシステムは&lt;code&gt;Docker image&lt;/code&gt;によって提供される.&lt;br&gt;
1つの&lt;code&gt;image&lt;/code&gt;にはコードやバイナリ, ランタイムなどのアプリを実行するために必要な全ての要素が内包される.&lt;/p&gt;
&lt;h4 id="containers-and-virtual-machines"&gt;Containers and virtual machines
&lt;/h4&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/#containers-and-virtual-machines" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/get-started/#containers-and-virtual-machines&lt;/a&gt;&lt;br&gt;
コンテナはLinux上で動作し, ホストマシンのカーネルを他のコンテナと共有している.&lt;br&gt;
コンテナはそれぞれが独立したプロセスを実行し, ホストマシンのメモリをアプリの実行に必要なぶんだけ使用するため軽量である.&lt;br&gt;
[追加]コンテナはアプリとそれを実行するのに必要な依存関係しか含まないので軽い.&lt;/p&gt;
&lt;p&gt;対称的に, ホストマシン上で動作するVM(仮想マシン)は内部で普通のOSとほぼ変わらないゲストOSを動かし, 制御プログラム(スーパーバイザー)を介してマシンのリソースを使用する.&lt;br&gt;
簡単に比較すると, VMはアプリの実行に必要な分より多くのリソースを使用するため重い.&lt;br&gt;
[追加]VMはアプリと依存関係に加えてOSを含んでいるので重い. ここではハイパーバイザー型のVMについて説明されているが, ホスト型もほぼ同じ(というかホスト型のほうが重い).&lt;/p&gt;
&lt;p&gt;&lt;img alt="コンテナとVMの比較" class="gallery-image" data-flex-basis="695px" data-flex-grow="289" height="673" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-10-11-docker-01/2019-10-11-container-vs-vm.png" srcset="https://blog.uzimihsr.com/post/2019-10-11-docker-01/2019-10-11-container-vs-vm_hu_5ca7cee5f9ad9db7.png 800w, https://blog.uzimihsr.com/post/2019-10-11-docker-01/2019-10-11-container-vs-vm_hu_4fa7b09c0d5e28a3.png 1600w, https://blog.uzimihsr.com/post/2019-10-11-docker-01/2019-10-11-container-vs-vm.png 1951w" width="1951"&gt;&lt;/p&gt;
&lt;h3 id="install-docker-desktop"&gt;Install Docker Desktop
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/#install-docker-desktop" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/get-started/#install-docker-desktop&lt;/a&gt;&lt;br&gt;
コンテナの開発を始めるには&lt;code&gt;Docker Desktop&lt;/code&gt;を使うのが手っ取り早い.&lt;br&gt;
ローカルの開発マシンに&lt;code&gt;Kubernetes&lt;/code&gt;と&lt;code&gt;Swarm&lt;/code&gt;を簡単にセットアップしてくれて, クラスタの構築をせずにコンテナオーケストレーションの機能を使用できるので非常に便利である.&lt;br&gt;
OSX用&lt;code&gt;Docker Desktop&lt;/code&gt;は以下よりインストールできる.&lt;br&gt;
&lt;a class="link" href="https://docs.docker.com/docker-for-mac/install/" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/docker-for-mac/install/&lt;/a&gt;&lt;br&gt;
[追加]&lt;code&gt;Kubernetes&lt;/code&gt;, &lt;code&gt;Swarm&lt;/code&gt;に関してはそれぞれPart3, 4で解説される.&lt;/p&gt;
&lt;h3 id="enable-kubernetes"&gt;Enable Kubernetes
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/#enable-kubernetes" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/get-started/#enable-kubernetes&lt;/a&gt;&lt;br&gt;
&lt;code&gt;Docker Desktop&lt;/code&gt;は&lt;code&gt;Kubernetes&lt;/code&gt;を簡単にセットアップしてくれる.&lt;br&gt;
以下の手順で実際にセットアップと動作確認を行う.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1&lt;/strong&gt;: メニューバーにある&lt;code&gt;Docker&lt;/code&gt;のアイコンをクリックし, &lt;code&gt;Preferences -&amp;gt; Kubernetes&lt;/code&gt;と進む.&lt;br&gt;
&lt;img class="gallery-image" data-flex-basis="158px" data-flex-grow="65" height="737" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-10-11-docker-01/2019-10-11-sc01.png" width="486"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2&lt;/strong&gt;: &lt;strong&gt;Enable Kubernetes&lt;/strong&gt; のチェックボックスを選択し, &lt;strong&gt;Apply&lt;/strong&gt; を押す.&lt;br&gt;&lt;code&gt;Docker Desktop&lt;/code&gt;が&lt;code&gt;Kubernetes&lt;/code&gt;のセットアップを行い, 準備が完了すると &lt;strong&gt;Kubernetes is running&lt;/strong&gt; の緑色のランプが光る.&lt;br&gt;
&lt;img class="gallery-image" data-flex-basis="288px" data-flex-grow="120" height="1020" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-10-11-docker-01/2019-10-11-sc02.png" srcset="https://blog.uzimihsr.com/post/2019-10-11-docker-01/2019-10-11-sc02_hu_48c06effec43acd2.png 800w, https://blog.uzimihsr.com/post/2019-10-11-docker-01/2019-10-11-sc02.png 1224w" width="1224"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3&lt;/strong&gt;: &lt;code&gt;Kubernetes&lt;/code&gt;の動作を確認するため, &lt;code&gt;pod.yaml&lt;/code&gt;というファイルを次の内容で作成する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Pod&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;demo&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;testpod&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;alpine:3.5&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;ping&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;8.8.8.8&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この&lt;code&gt;pod.yaml&lt;/code&gt;は&lt;code&gt;8.8.8.8&lt;/code&gt;に&lt;code&gt;ping&lt;/code&gt;を飛ばすだけのコンテナ&lt;strong&gt;testpod&lt;/strong&gt;を1つ持つ&lt;strong&gt;demo&lt;/strong&gt;という名前の&lt;code&gt;Pod&lt;/code&gt;を定義している.&lt;br&gt;
[追加]&lt;code&gt;Pod&lt;/code&gt;についてはPart3で説明.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4&lt;/strong&gt;: &lt;code&gt;pod.yaml&lt;/code&gt;があるディレクトリに移動し, &lt;code&gt;Pod&lt;/code&gt;を作成する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# マニフェストファイル(pod.yaml)があるディレクトリで操作&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# pod.yamlで定義されたPodを起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f pod.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod/demo created
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;5&lt;/strong&gt;: &lt;code&gt;Pod&lt;/code&gt;(&lt;strong&gt;demo&lt;/strong&gt;)が起動しているか確認する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Podの一覧を表示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;demo 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 15s
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;6&lt;/strong&gt;: &lt;code&gt;Pod&lt;/code&gt;(&lt;strong&gt;demo&lt;/strong&gt;)のログを表示し, &lt;code&gt;ping&lt;/code&gt;のログが表示されることを確認する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Pod(demo)のログを確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl logs demo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;PING 8.8.8.8 &lt;span class="o"&gt;(&lt;/span&gt;8.8.8.8&lt;span class="o"&gt;)&lt;/span&gt;: &lt;span class="m"&gt;56&lt;/span&gt; data bytes
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;[追加]自分の場合は&lt;code&gt;ping&lt;/code&gt;が正しく返ってきていないが, とりあえず&lt;code&gt;ping&lt;/code&gt;コマンドを実行したときのログが正しく表示されているのでここでは問題ない.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;7&lt;/strong&gt;: 作成した&lt;code&gt;Pod&lt;/code&gt;を削除する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# pod.yamlで定義されたPodを削除&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl delete -f pod.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pod &lt;span class="s2"&gt;&amp;#34;demo&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;[追加]&lt;code&gt;kubectl delete pod demo&lt;/code&gt;でも同様に&lt;code&gt;Pod&lt;/code&gt;を削除できる.&lt;/p&gt;
&lt;h3 id="enable-docker-swarm"&gt;Enable Docker Swarm
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/#enable-docker-swarm" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/get-started/#enable-docker-swarm&lt;/a&gt;&lt;br&gt;
&lt;code&gt;Docker Desktop&lt;/code&gt;は&lt;code&gt;Docker Engine&lt;/code&gt;上で動作していて, この&lt;code&gt;Docker Engine&lt;/code&gt;には&lt;code&gt;Swarm&lt;/code&gt;の動作に必要なものが最初から入っている.&lt;br&gt;
以下の手順でセットアップと動作確認を行う.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1&lt;/strong&gt;: &lt;code&gt;Docker&lt;/code&gt;を&lt;code&gt;Swarm&lt;/code&gt;モードにする.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Swarmクラスタを初期化&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker swarm init
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Swarm initialized: current node &lt;span class="o"&gt;(&lt;/span&gt;gezwfuy4mutsw8sbfoqnctkez&lt;span class="o"&gt;)&lt;/span&gt; is now a manager.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;To add a worker to this swarm, run the following command:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; docker swarm join --token SWMTKN-1-6232qe43fjsexb2wt8j0pqdo44rqt5tapg9zedin4ywt7nk4s9-evu0arm6l2e95rdn18i524mt5 192.168.65.3:2377
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;To add a manager to this swarm, run &lt;span class="s1"&gt;&amp;#39;docker swarm join-token manager&amp;#39;&lt;/span&gt; and follow the instructions.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;2&lt;/strong&gt;: &lt;code&gt;8.8.8.8&lt;/code&gt;に&lt;code&gt;ping&lt;/code&gt;を送る&lt;code&gt;Service&lt;/code&gt;(&lt;strong&gt;demo&lt;/strong&gt;)を起動する.&lt;br&gt;
[追加]&lt;code&gt;Service&lt;/code&gt;についてはPart3,4で説明.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# alpine(image)を使用して8.8.8.8にpingを送るService(demo)を起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker service create --name demo alpine:3.5 ping 8.8.8.8
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;5rko6rb8oe86uhadrk0ruwahb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;overall progress: &lt;span class="m"&gt;1&lt;/span&gt; out of &lt;span class="m"&gt;1&lt;/span&gt; tasks
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1/1: running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;verify: Service converged
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;3&lt;/strong&gt;: &lt;code&gt;Service&lt;/code&gt;(&lt;strong&gt;demo&lt;/strong&gt;)がコンテナを起動していることを確認する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Service(demo)が起動しているコンテナの一覧を表示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker service ps demo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ngoves00al7u demo.1 alpine:3.5 docker-desktop Running Running &lt;span class="m"&gt;18&lt;/span&gt; minutes ago
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;4&lt;/strong&gt;: &lt;code&gt;Service&lt;/code&gt;(&lt;strong&gt;demo&lt;/strong&gt;)のログを確認する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Service(demo)のログを確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker service logs demo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;demo.1.ngoves00al7u@docker-desktop &lt;span class="p"&gt;|&lt;/span&gt; PING 8.8.8.8 &lt;span class="o"&gt;(&lt;/span&gt;8.8.8.8&lt;span class="o"&gt;)&lt;/span&gt;: &lt;span class="m"&gt;56&lt;/span&gt; data bytes
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;[追加]自分の場合は&lt;code&gt;ping&lt;/code&gt;が正しく返ってきていないが, とりあえず&lt;code&gt;ping&lt;/code&gt;コマンドを実行したときのログが正しく表示されているのでここでは問題ない.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5&lt;/strong&gt;: 作成した&lt;code&gt;Service&lt;/code&gt;(&lt;strong&gt;demo&lt;/strong&gt;)を削除する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Service(demo)を削除&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker service rm demo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;demo
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="conclusion"&gt;Conclusion
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/#conclusion" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/get-started/#conclusion&lt;/a&gt;&lt;br&gt;
このパートでは&lt;code&gt;Docker Desktop&lt;/code&gt;をインストールし, &lt;code&gt;Kubernetes&lt;/code&gt;と&lt;code&gt;Swarm&lt;/code&gt;で簡単なコンテナを起動できることを確認した.&lt;br&gt;
次のパートでは実際にコンテナ型アプリを開発する.&lt;/p&gt;</description></item><item><title>読んでる途中でDocker Get Startedが更新されちゃった話</title><link>https://blog.uzimihsr.com/post/2019-10-10-docker-get-started-05/</link><pubDate>Thu, 10 Oct 2019 22:54:19 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2019-10-10-docker-get-started-05/</guid><description>&lt;h2 id="dockerおさらい"&gt;Dockerおさらい
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2019-10-07-docker-get-started-04/" target="_blank" rel="noopener"
 &gt;前回&lt;/a&gt;のつづき&amp;hellip;?&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="嘘だろ"&gt;嘘だろ&amp;hellip;?
&lt;/h2&gt;&lt;p&gt;Part5まで来たところでなんとGet Startedの内容が更新されてしまった.&lt;br&gt;
&lt;a class="link" href="https://docs.docker.com/get-started/" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/get-started/&lt;/a&gt;&lt;br&gt;
章立ても変わってPart6が消えている.&lt;/p&gt;
&lt;p&gt;せっかくやってきたのに残念だけど, もう一度最初から読み返すか&amp;hellip;&lt;br&gt;
今度は理解も進んでいるので, もっとうまくまとめられるようにするか&amp;hellip;&lt;br&gt;
正直読み返しても文字が多くてわかりづらかったしな&amp;hellip;&lt;/p&gt;
&lt;p&gt;にしても, なんでこんなタイムリーなタイミングで&amp;hellip;&lt;br&gt;
ちょっとやる気が出ない.&lt;/p&gt;</description></item><item><title>[Deprecated]Docker Get Startedを読む Part4</title><link>https://blog.uzimihsr.com/post/2019-10-07-docker-get-started-04/</link><pubDate>Wed, 09 Oct 2019 22:14:07 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2019-10-07-docker-get-started-04/</guid><description>&lt;h2 id="dockerおさらい"&gt;Dockerおさらい
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2019-10-06-docker-get-started-03/" target="_blank" rel="noopener"
 &gt;前回&lt;/a&gt;のつづき&lt;/p&gt;
&lt;h2 id="deprecated"&gt;Deprecated
&lt;/h2&gt;&lt;p&gt;公式の&lt;a class="link" href="https://docs.docker.com/get-started/" target="_blank" rel="noopener"
 &gt;Get Started&lt;/a&gt;が更新されてしまったので,&lt;br&gt;
この記事の内容は古くなっている. 非推奨.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="読んだもの"&gt;読んだもの
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/part4/" target="_blank" rel="noopener"
 &gt;Get Started, Part 4: Swarms&lt;/a&gt;&lt;br&gt;
複数のマシンでDockerを稼働させるためのswarmに関する内容.&lt;/p&gt;
&lt;h2 id="事前準備"&gt;事前準備
&lt;/h2&gt;&lt;p&gt;このパートに入る前に以下の条件をクリアすること.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;バージョン1.13以降のDockerがインストール済みであること&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.docker.com/get-started/part3/" target="_blank" rel="noopener"
 &gt;Part 3&lt;/a&gt;で説明したDocker Composeが入っていること&lt;/li&gt;
&lt;li&gt;Docker Machineが入っていること
&lt;ul&gt;
&lt;li&gt;Docker Desktop for Macには入ってるので大丈夫&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.docker.com/get-started/" target="_blank" rel="noopener"
 &gt;Part 1&lt;/a&gt;, &lt;a class="link" href="https://docs.docker.com/get-started/part2/" target="_blank" rel="noopener"
 &gt;Part 2&lt;/a&gt;の内容を理解していること&lt;/li&gt;
&lt;li&gt;Part2で作成したイメージがDocker Hubにアップロードされていて, 正常に動くこと&lt;/li&gt;
&lt;li&gt;Part3で作成した&lt;code&gt;docker-compose.yml&lt;/code&gt;があること&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="はじめに"&gt;はじめに
&lt;/h2&gt;&lt;p&gt;このパートでは複数台のマシンで構成されるswarmクラスタにアプリをデプロイする.&lt;br&gt;
swarmクラスタとは複数のマシンをDocker化し1つにしたもので, 複数クラスタ, 複数マシンで動作するアプリケーションを実現するものである.&lt;/p&gt;
&lt;h2 id="swarmクラスタを理解する"&gt;swarmクラスタを理解する
&lt;/h2&gt;&lt;p&gt;swarmとは:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dockerが稼働する複数台のマシンが1つのクラスタにまとまったもの
&lt;ul&gt;
&lt;li&gt;swarmを構成するマシンはノードと呼ばれる&lt;/li&gt;
&lt;li&gt;swarmを構成するマシンは物理マシン/VMを問わない&lt;/li&gt;
&lt;li&gt;swarmマネージャとワーカーで構成される
&lt;ul&gt;
&lt;li&gt;swarmマネージャ
&lt;ul&gt;
&lt;li&gt;1つのswarmに1台だけ存在するノード&lt;/li&gt;
&lt;li&gt;dockerコマンドを実行する&lt;/li&gt;
&lt;li&gt;他のマシン(ノード)をワーカーとして管理/指示を行う役割&lt;/li&gt;
&lt;li&gt;コンテナを実行するときの方針を定める役割
&lt;ul&gt;
&lt;li&gt;方針は&lt;code&gt;docker-compose.yml&lt;/code&gt;で定義できる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ワーカー
&lt;ul&gt;
&lt;li&gt;swarmマネージャ以外のノード&lt;/li&gt;
&lt;li&gt;リソースを提供する&lt;/li&gt;
&lt;li&gt;他のワーカーへ指示を出すことはできない&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これまではシングルホストモードでDockerを使用してきたが, このパートではswarmモードでDockerを使用していく.&lt;br&gt;
swarmモードでは操作中のローカルマシンではなく, クラスタ単位でDockerのコマンドが実行されるようになる&lt;/p&gt;
&lt;h2 id="swarmをセットアップする"&gt;swarmをセットアップする
&lt;/h2&gt;&lt;p&gt;上記の通りswarmは物理/VMを問わない複数のノード(マシン)で構成されており,&lt;br&gt;
1つのマシンで&lt;code&gt;docker swarm init&lt;/code&gt;を実行するとdockerがswarmモードになり, そのマシンがswarmマネージャになる.&lt;br&gt;
他のマシンで&lt;code&gt;docker swarm join&lt;/code&gt;を実行するとそのマシンがswarmクラスタにワーカーとして登録される.&lt;br&gt;
ここでは例として2台のVMでswarmクラスタを構成してみる.&lt;/p&gt;
&lt;h3 id="クラスタを作成する"&gt;クラスタを作成する
&lt;/h3&gt;&lt;p&gt;まずは手元のマシンでVMを建てる準備をする.&lt;br&gt;
自分の場合はMacなので&lt;a class="link" href="https://www.virtualbox.org/wiki/Downloads" target="_blank" rel="noopener"
 &gt;VirtualBox&lt;/a&gt;をインストールした.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;docker-machine&lt;/code&gt;コマンドを使ってDocker用のVMを2台作成する.&lt;br&gt;
今回はmyvm1, myvm2という名前のVMを作成する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-machine create --driver virtualbox myvm1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-machine create --driver virtualbox myvm2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;作成したVM(docker-machine)のIPアドレスなどの情報は&lt;code&gt;docker-machine ls&lt;/code&gt;コマンドで確認できる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-machine ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;myvm1 - virtualbox Running tcp://192.168.99.100:2376 v18.09.9
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;myvm2 - virtualbox Running tcp://192.168.99.101:2376 v18.09.9
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;1台目のVM(myvm1)はswarmマネージャとして, 2台目(myvm2)はワーカーとして使用する.&lt;br&gt;
VM(docker-machine)上でコマンドを実行するには&lt;code&gt;docker-machine ssh&lt;/code&gt;コマンドを利用する.&lt;br&gt;
ここではmyvm1に&lt;code&gt;docker swarm init&lt;/code&gt;コマンドを実行させてswarmマネージャにする.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-machine ssh myvm1 &lt;span class="s2"&gt;&amp;#34;docker swarm init --advertise-addr 192.168.99.100&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Swarm initialized: current node &lt;span class="o"&gt;(&lt;/span&gt;zfpm1vq86ladj9dn5cs5pdg7x&lt;span class="o"&gt;)&lt;/span&gt; is now a manager.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;To add a worker to this swarm, run the following command:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; docker swarm join --token SWMTKN-1-1gpfpimuxhtsz3i8mywpwb3lmsfwzldgpq7h70iuapkuq83id6-27xtpkdnuf42c7uwu6xrmz9sz 192.168.99.100:2377
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;To add a manager to this swarm, run &lt;span class="s1"&gt;&amp;#39;docker swarm join-token manager&amp;#39;&lt;/span&gt; and follow the instructions.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;docker swarm init&lt;/code&gt;コマンドの出力結果を見ると, このswarmに新たにワーカーを追加するためのコマンドが表示されている.&lt;br&gt;
これに従って, myvm2をこのswarmに追加する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-machine ssh myvm2 &lt;span class="s2"&gt;&amp;#34;docker swarm join --token SWMTKN-1-1gpfpimuxhtsz3i8mywpwb3lmsfwzldgpq7h70iuapkuq83id6-27xtpkdnuf42c7uwu6xrmz9sz 192.168.99.100:2377&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;This node joined a swarm as a worker.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これでswarmが構築できた.&lt;br&gt;
試しにswarmマネージャ(myvm1)から&lt;code&gt;docker node ls&lt;/code&gt;コマンドを使用するとこのswarmに存在するノードの一覧が表示される.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-machine ssh myvm1 &lt;span class="s2"&gt;&amp;#34;docker node ls&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;zfpm1vq86ladj9dn5cs5pdg7x * myvm1 Ready Active Leader 18.09.9
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2t7nqlaes8gl08swfe5d81lim myvm2 Ready Active 18.09.9
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="アプリをswarmクラスタにデプロイする"&gt;アプリをswarmクラスタにデプロイする
&lt;/h2&gt;&lt;p&gt;難しいのはここまで.&lt;br&gt;
ここからはpart3と同様の手順を進めていく.&lt;br&gt;
ただしdockerコマンドはswarmマネージャ(myvm1)からのみ実行可能であることに注意.&lt;/p&gt;
&lt;h3 id="docker-machineコマンドを実行するシェルをswarmマネージャに合わせて設定する"&gt;docker-machineコマンドを実行するシェルをswarmマネージャに合わせて設定する
&lt;/h3&gt;&lt;p&gt;ここまでdockerコマンドを実行するためには手元のシェルで&lt;code&gt;docker-machine ssh&lt;/code&gt;を使用してswarmマネージャ(myvm1)にコマンドを送信していた.&lt;br&gt;
このままでも問題ないが, 手元の&lt;code&gt;docker-compose.yml&lt;/code&gt;を使いたい場合に少し面倒になる.&lt;br&gt;
そのため, 手元のシェルをmyvm1のDockerデーモンと疎通させる設定を行う.&lt;br&gt;
手元のシェルで&lt;code&gt;docker-machine env myvm1&lt;/code&gt;コマンドを実行するとmyvm1と疎通するためのコマンドが出力されるので, これを貼り付けるだけで設定が完了する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-machine env myvm1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;DOCKER_TLS_VERIFY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;DOCKER_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;tcp://192.168.99.100:2376&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;DOCKER_CERT_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/Users/uzimihsr/.docker/machine/machines/myvm1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;DOCKER_MACHINE_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;myvm1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Run this command to configure your shell:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# eval $(docker-machine env myvm1)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;docker-machine env myvm1&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この状態でswarmのノード確認コマンド&lt;code&gt;docker node ls&lt;/code&gt;を実行すると, myvm1にssh経由で実行した際と同じ出力が得られる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker node ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;zfpm1vq86ladj9dn5cs5pdg7x * myvm1 Ready Active Leader 18.09.9
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2t7nqlaes8gl08swfe5d81lim myvm2 Ready Active 18.09.9
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ちなみに別のシェルを開いて疎通の設定をせずに同じコマンドを打つと当然ながらswarmマネージャとして振る舞えないのでエラーになる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker node ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Error response from daemon: This node is not a swarm manager. Use &lt;span class="s2"&gt;&amp;#34;docker swarm init&amp;#34;&lt;/span&gt; or &lt;span class="s2"&gt;&amp;#34;docker swarm join&amp;#34;&lt;/span&gt; to connect this node to swarm and try again.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="swarmマネージャからアプリをデプロイする"&gt;swarmマネージャからアプリをデプロイする
&lt;/h3&gt;&lt;p&gt;シェルの設定が完了し, 直接swarmマネージャ(myvm1)でコマンドが実行できるようになったのでいよいよアプリをデプロイする.&lt;br&gt;
Part3と同じ&lt;code&gt;docker-compose.yml&lt;/code&gt;が手元にあることを確認し, &lt;code&gt;docker stack deploy&lt;/code&gt;コマンドを実行する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker-compose.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker stack deploy -c ./docker-compose.yml getstartedlab
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Creating network getstartedlab_webnet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Creating service getstartedlab_web
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これでアプリがデプロイされた. すごい簡単.&lt;br&gt;
Part3と同様にタスクの確認を行う.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker stack ps getstartedlab
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ikvg0oxrqbc7 getstartedlab_web.1 uzimihsr/get-started:part2 myvm1 Running Running &lt;span class="m"&gt;3&lt;/span&gt; minutes ago
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uy3juv1txuon getstartedlab_web.2 uzimihsr/get-started:part2 myvm2 Running Running &lt;span class="m"&gt;3&lt;/span&gt; minutes ago
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;j6545cpwqmvl getstartedlab_web.3 uzimihsr/get-started:part2 myvm2 Running Running &lt;span class="m"&gt;3&lt;/span&gt; minutes ago
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Part3で確認したものと同じく3つのサービスが表示される(元々は5個だがPart3の後半で3個にスケーリングしている).&lt;br&gt;
また, 注目すべきは&lt;code&gt;NODE&lt;/code&gt;の列で, サービスがそれぞれmyvm1とmyvm2に分かれて稼働していることがわかる.&lt;/p&gt;
&lt;h3 id="クラスタにアクセスする"&gt;クラスタにアクセスする
&lt;/h3&gt;&lt;p&gt;デプロイされたアプリにはmyvm1, myvm2両方のIPアドレスでアクセスできる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-machine ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;myvm1 * virtualbox Running tcp://192.168.99.100:2376 v18.09.9
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;myvm2 - virtualbox Running tcp://192.168.99.101:2376 v18.09.9
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;curlで何度か叩いてみる.&lt;br&gt;
今回使用するアプリはdockerが稼働するマシンの4000番ポートをコンテナの80番ポートに割り当てていることに注意.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://192.168.99.100:4000
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;h3&amp;gt;Hello World!&amp;lt;/h3&amp;gt;&amp;lt;b&amp;gt;Hostname:&amp;lt;/b&amp;gt; bf3c2f00e239&amp;lt;br/&amp;gt;&amp;lt;b&amp;gt;Visits:&amp;lt;/b&amp;gt; &amp;lt;i&amp;gt;cannot connect to Redis, counter disabled&amp;lt;/i&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://192.168.99.100:4000
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;h3&amp;gt;Hello World!&amp;lt;/h3&amp;gt;&amp;lt;b&amp;gt;Hostname:&amp;lt;/b&amp;gt; df6c4458369c&amp;lt;br/&amp;gt;&amp;lt;b&amp;gt;Visits:&amp;lt;/b&amp;gt; &amp;lt;i&amp;gt;cannot connect to Redis, counter disabled&amp;lt;/i&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://192.168.99.100:4000
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;h3&amp;gt;Hello World!&amp;lt;/h3&amp;gt;&amp;lt;b&amp;gt;Hostname:&amp;lt;/b&amp;gt; 0541e646a6ce&amp;lt;br/&amp;gt;&amp;lt;b&amp;gt;Visits:&amp;lt;/b&amp;gt; &amp;lt;i&amp;gt;cannot connect to Redis, counter disabled&amp;lt;/i&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://192.168.99.101:4000
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;h3&amp;gt;Hello World!&amp;lt;/h3&amp;gt;&amp;lt;b&amp;gt;Hostname:&amp;lt;/b&amp;gt; df6c4458369c&amp;lt;br/&amp;gt;&amp;lt;b&amp;gt;Visits:&amp;lt;/b&amp;gt; &amp;lt;i&amp;gt;cannot connect to Redis, counter disabled&amp;lt;/i&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://192.168.99.101:4000
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;h3&amp;gt;Hello World!&amp;lt;/h3&amp;gt;&amp;lt;b&amp;gt;Hostname:&amp;lt;/b&amp;gt; bf3c2f00e239&amp;lt;br/&amp;gt;&amp;lt;b&amp;gt;Visits:&amp;lt;/b&amp;gt; &amp;lt;i&amp;gt;cannot connect to Redis, counter disabled&amp;lt;/i&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://192.168.99.101:4000
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;h3&amp;gt;Hello World!&amp;lt;/h3&amp;gt;&amp;lt;b&amp;gt;Hostname:&amp;lt;/b&amp;gt; 0541e646a6ce&amp;lt;br/&amp;gt;&amp;lt;b&amp;gt;Visits:&amp;lt;/b&amp;gt; &amp;lt;i&amp;gt;cannot connect to Redis, counter disabled&amp;lt;/i&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;負荷分散で3種類のホストがランダムに呼び出されているのが確認できる.&lt;/p&gt;
&lt;p&gt;myvm1, myvm2どちらのIPアドレスでも同じように動作するのは, swarmのノードがingressルーティングメッシュに属しているためである.&lt;br&gt;
(超意訳)今回のように&lt;code&gt;docker-compose.yml&lt;/code&gt;でマシンの4000番ポートをコンテナの80番ポートに割り当てる設定をした場合, 各ノード自身が4000番ポートをswarmでデプロイされたサービスのために確保する. また, 各ノードの4000番ポートにはロードバランサーが割り当てられ, このロードバランサーはswarm内でノードに関係なく全てのコンテナに対して負荷分散を行う.&lt;/p&gt;
&lt;h2 id="アプリの繰り返しとスケーリング"&gt;アプリの繰り返しとスケーリング
&lt;/h2&gt;&lt;p&gt;Part3と同様に, &lt;code&gt;docker-compose.yml&lt;/code&gt;を編集することでアプリのスケーリングを行うことができる.&lt;br&gt;
また, この状態からswarmにノードを増やすこともできる.&lt;br&gt;
今回はmyvm3を作成し, myvm2と同様にワーカーとしてswarmに追加する.&lt;br&gt;
さらにコンテナ数を現在の3から8に増やしてみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-machine create --driver virtualbox myvm3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-machine ssh myvm3 &lt;span class="s2"&gt;&amp;#34;docker swarm join --token SWMTKN-1-1gpfpimuxhtsz3i8mywpwb3lmsfwzldgpq7h70iuapkuq83id6-27xtpkdnuf42c7uwu6xrmz9sz 192.168.99.100:2377&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;This node joined a swarm as a worker.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker node ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;zfpm1vq86ladj9dn5cs5pdg7x * myvm1 Ready Active Leader 18.09.9
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2t7nqlaes8gl08swfe5d81lim myvm2 Ready Active 18.09.9
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;p4n9y3kez6u35fkduojjloa17 myvm3 Ready Active 19.03.3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim docker-compose.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker stack deploy -c ./docker-compose.yml getstartedlab
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker stack ps getstartedlab
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ikvg0oxrqbc7 getstartedlab_web.1 uzimihsr/get-started:part2 myvm1 Running Running &lt;span class="m"&gt;23&lt;/span&gt; hours ago
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uy3juv1txuon getstartedlab_web.2 uzimihsr/get-started:part2 myvm2 Running Running &lt;span class="m"&gt;23&lt;/span&gt; hours ago
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;j6545cpwqmvl getstartedlab_web.3 uzimihsr/get-started:part2 myvm2 Running Running &lt;span class="m"&gt;23&lt;/span&gt; hours ago
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hax39564wx4d getstartedlab_web.4 uzimihsr/get-started:part2 myvm3 Running Running &lt;span class="m"&gt;23&lt;/span&gt; seconds ago
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;t9qx3iyptfi7 getstartedlab_web.5 uzimihsr/get-started:part2 myvm1 Running Running &lt;span class="m"&gt;33&lt;/span&gt; seconds ago
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;4e84bwdkq8hj getstartedlab_web.6 uzimihsr/get-started:part2 myvm1 Running Running &lt;span class="m"&gt;33&lt;/span&gt; seconds ago
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;vpf7nwgvonlk getstartedlab_web.7 uzimihsr/get-started:part2 myvm2 Running Running &lt;span class="m"&gt;34&lt;/span&gt; seconds ago
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aca3i7e0f615 getstartedlab_web.8 uzimihsr/get-started:part2 myvm3 Running Running &lt;span class="m"&gt;23&lt;/span&gt; seconds ago
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;details&gt;&lt;summary&gt;レプリカ数を変更したdocker-compose.yml&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;3&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;web&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;uzimihsr/get-started:part2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# イメージインスタンスの数を8に指定&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;replicas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;limits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cpus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;0.1&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;50M&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;restart_policy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;on&lt;/span&gt;-&lt;span class="l"&gt;failure&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;4000:80&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;webnet&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;webnet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;コンテナ数が増え, 新たに追加したワーカー(myvm3)にもサービスがデプロイされている.&lt;br&gt;
以上, 簡単にノードの追加, アプリのスケーリングができることがわかった.&lt;/p&gt;
&lt;h2 id="クリーンアップと再起動"&gt;クリーンアップと再起動
&lt;/h2&gt;&lt;p&gt;アプリの削除と再起動も簡単に行える.&lt;/p&gt;
&lt;h3 id="スタックとswarm"&gt;スタックとswarm
&lt;/h3&gt;&lt;p&gt;スタックは&lt;code&gt;docker stack rm&lt;/code&gt;コマンドで削除できる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker stack rm getstartedlab
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Removing service getstartedlab_web
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Removing network getstartedlab_webnet
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;各ノードで&lt;code&gt;docker swarm leave&lt;/code&gt;コマンドを使用するとそのノードを現在のswarmから開放することができる. が, Part5で使用するので現時点でswarmの解体は行わない.&lt;/p&gt;
&lt;h3 id="docker-machineシェルの変数を解除"&gt;docker-machineシェルの変数を解除
&lt;/h3&gt;&lt;p&gt;swarmマネージャ(myvm1)と疎通してコマンドを実行するために設定したシェルは次のように設定を解除することができる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;docker-machine env -u&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker node ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Error response from daemon: This node is not a swarm manager. Use &lt;span class="s2"&gt;&amp;#34;docker swarm init&amp;#34;&lt;/span&gt; or &lt;span class="s2"&gt;&amp;#34;docker swarm join&amp;#34;&lt;/span&gt; to connect this node to swarm and try again.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="docker-machineを再起動する"&gt;docker-machineを再起動する
&lt;/h3&gt;&lt;p&gt;VM(docker-machine)はローカルマシンを停止するか, &lt;code&gt;docker-machine stop&lt;/code&gt;コマンドで停止することができる.&lt;br&gt;
今回は全部のVMを停止してみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-machine stop &lt;span class="k"&gt;$(&lt;/span&gt;docker-machine ls -q&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Stopping &lt;span class="s2"&gt;&amp;#34;myvm3&amp;#34;&lt;/span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Stopping &lt;span class="s2"&gt;&amp;#34;myvm1&amp;#34;&lt;/span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Stopping &lt;span class="s2"&gt;&amp;#34;myvm2&amp;#34;&lt;/span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Machine &lt;span class="s2"&gt;&amp;#34;myvm1&amp;#34;&lt;/span&gt; was stopped.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Machine &lt;span class="s2"&gt;&amp;#34;myvm3&amp;#34;&lt;/span&gt; was stopped.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Machine &lt;span class="s2"&gt;&amp;#34;myvm2&amp;#34;&lt;/span&gt; was stopped.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-machine ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;myvm1 - virtualbox Stopped Unknown
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;myvm2 - virtualbox Stopped Unknown
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;myvm3 - virtualbox Stopped Unknown
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;また, 停止したVMは&lt;code&gt;docker-machine start&lt;/code&gt;コマンドで再起動できる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-machine start myvm1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-machine ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;myvm1 - virtualbox Running tcp://192.168.99.100:2376 v18.09.9
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;myvm2 - virtualbox Stopped Unknown
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;myvm3 - virtualbox Stopped Unknown
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-machine start &lt;span class="k"&gt;$(&lt;/span&gt;docker-machine ls -q&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-machine ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;myvm1 - virtualbox Running tcp://192.168.99.100:2376 v18.09.9
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;myvm2 - virtualbox Running tcp://192.168.99.101:2376 v18.09.9
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;myvm3 - virtualbox Running tcp://192.168.99.102:2376 v19.03.3
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="感想まとめ"&gt;感想(まとめ)
&lt;/h2&gt;&lt;p&gt;swarmに関する内容がもりもりだった.&lt;br&gt;
個人的にはdocker-machineを利用するとdockerをインストールしたVMが簡単に立てられて便利だと思った. VirtualBoxすごい.&lt;br&gt;
要点としては,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;swarmを利用すると複数台のマシンのリソースを利用してDockerが動かせること&lt;/li&gt;
&lt;li&gt;swarmはマネージャとワーカーの2種類のノードで構成されること
&lt;ul&gt;
&lt;li&gt;ワーカーは計算リソースを提供するのみでコンテナやノードの操作は行わない&lt;/li&gt;
&lt;li&gt;マネージャはワーカーの管理を行い, これまでローカルマシンで実行していたdockerコマンドを使用してswarmクラスタにアプリをデプロイ/スケーリングする&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;docker-machineを利用してローカルマシン1台の中に複数のノード用VMを簡単に作成できること&lt;/li&gt;
&lt;li&gt;複数のノードで構成される1つのswarmはまるで1つのマシンのように扱うことができ, 実際にどのノードでコンテナが動くかに関係なくswarm内でロードバランシングが行えること&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;がわかれば十分.&lt;/p&gt;
&lt;p&gt;次は&lt;a class="link" href="https://docs.docker.com/get-started/part5/" target="_blank" rel="noopener"
 &gt;Get Started, Part 5: Stacks&lt;/a&gt;を読む.&lt;br&gt;
そろそろ疲れてきた.&lt;/p&gt;</description></item><item><title>[Deprecated]Docker Get Startedを読む Part3</title><link>https://blog.uzimihsr.com/post/2019-10-06-docker-get-started-03/</link><pubDate>Sun, 06 Oct 2019 16:58:10 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2019-10-06-docker-get-started-03/</guid><description>&lt;h2 id="dockerおさらい"&gt;Dockerおさらい
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2019-10-05-docker-get-started-02/" target="_blank" rel="noopener"
 &gt;前回&lt;/a&gt;のつづき&lt;/p&gt;
&lt;h2 id="deprecated"&gt;Deprecated
&lt;/h2&gt;&lt;p&gt;公式の&lt;a class="link" href="https://docs.docker.com/get-started/" target="_blank" rel="noopener"
 &gt;Get Started&lt;/a&gt;が更新されてしまったので,&lt;br&gt;
この記事の内容は古くなっている. 非推奨.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="読んだもの"&gt;読んだもの
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/part3/" target="_blank" rel="noopener"
 &gt;Get Started, Part 3: Services&lt;/a&gt;&lt;br&gt;
コンテナを実際に使うためのサービスに関する内容.&lt;/p&gt;
&lt;h2 id="事前準備"&gt;事前準備
&lt;/h2&gt;&lt;p&gt;このパートに入る前に以下の条件をクリアすること.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;バージョン1.13以降のDockerがインストール済みであること&lt;/li&gt;
&lt;li&gt;Docker Composeが入っていること
&lt;ul&gt;
&lt;li&gt;Docker Desktop for Macには入ってるので大丈夫&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.docker.com/get-started/" target="_blank" rel="noopener"
 &gt;Part 1&lt;/a&gt;, &lt;a class="link" href="https://docs.docker.com/get-started/part2/" target="_blank" rel="noopener"
 &gt;Part 2&lt;/a&gt;の内容を理解していること&lt;/li&gt;
&lt;li&gt;Part2で作成したイメージがDocker Hubにアップロードされていて, 正常に動くこと&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="はじめに"&gt;はじめに
&lt;/h2&gt;&lt;p&gt;このパートではDockerにおけるアプリ開発の3つの&lt;a class="link" href="https://uzimihsr.github.io/post/2019-10-05-docker-get-started-02/#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB" target="_blank" rel="noopener"
 &gt;段階&lt;/a&gt;のうち,&lt;br&gt;
アプリのスケーリングとロードバランシング(負荷分散)を行うサービスについて説明する.&lt;/p&gt;
&lt;h2 id="サービスとは"&gt;サービスとは
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;分散アプリケーションを構成するそれぞれのアプリケーション
&lt;ul&gt;
&lt;li&gt;例:動画共有サイト(分散アプリケーション)
&lt;ul&gt;
&lt;li&gt;DBに動画を保存するサービス(アプリ)&lt;/li&gt;
&lt;li&gt;アップロードされた動画をエンコードするサービス(アプリ)&lt;/li&gt;
&lt;li&gt;フロントエンド用のサービス(アプリ)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;本番環境のコンテナ
&lt;ul&gt;
&lt;li&gt;あくまで1つのイメージを使用&lt;/li&gt;
&lt;li&gt;イメージ(コンテナ)の実行方法を定義するもの
&lt;ul&gt;
&lt;li&gt;使用するポートの指定&lt;/li&gt;
&lt;li&gt;サービスの規模に合わせたコンテナのレプリカ数の指定など&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;(超意訳)イメージの使い方を細かく設定した実用性の高いコンテナのラッパー?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt;で定義する&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="はじめてのdocker-composeyml"&gt;はじめてのdocker-compose.yml
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt;はYAML形式でコンテナの動作を定義するファイルである.&lt;/p&gt;
&lt;h3 id="docker-composeyml"&gt;docker-compose.yml
&lt;/h3&gt;&lt;p&gt;実際に作ってみる.&lt;br&gt;
どのディレクトリでもいいので&lt;code&gt;docker-compose.yml&lt;/code&gt;を以下の内容で作成する.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ mkdir workspace
$ cd workspace
$ vim docker-compose.yml
&lt;/code&gt;&lt;/pre&gt;&lt;details&gt;&lt;summary&gt;docker-compose.yml&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;3&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# webという名前のサービスを定義&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;web&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Part2でDocker Hubに登録したイメージを指定&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;uzimihsr/get-started:part2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# イメージインスタンスの数を5に指定&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;replicas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;limits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 各インスタンスのCPU性能を10%に制限&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cpus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;0.1&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 各インスタンスのメモリを50MBに制限&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;50M&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;restart_policy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# コンテナが停止した場合すぐに再起動するよう設定&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;on&lt;/span&gt;-&lt;span class="l"&gt;failure&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# ローカルマシンの4000番ポートをwebの80番に割り当て&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;4000:80&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# webnetという名前のネットワークでポートを共有するよう設定&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;webnet&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# webnetという名前のネットワークを定義&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 何も指定しない場合は負荷分散ネットワークになる&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;webnet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;ざっくり説明するとこの&lt;code&gt;docker-compose.yml&lt;/code&gt;は&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;webという名前のサービスを定義
&lt;ul&gt;
&lt;li&gt;Docker Hubの&lt;a class="link" href="https://hub.docker.com/r/uzimihsr/get-started/tags" target="_blank" rel="noopener"
 &gt;イメージ&lt;/a&gt;を使用する&lt;/li&gt;
&lt;li&gt;コンテナレプリカは5個稼働させる&lt;/li&gt;
&lt;li&gt;各インスタンス(レプリカ?)のCPUはシステムの10%, メモリは50MBに設定&lt;/li&gt;
&lt;li&gt;コンテナが死んだら再起動させる&lt;/li&gt;
&lt;li&gt;ホスト(Dockerを起動しているマシン)の4000番ポートをwebサービスの80番ポートに割り当てる&lt;/li&gt;
&lt;li&gt;webnetというネットワークを使用する&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;webnetという名前のネットワークを定義
&lt;ul&gt;
&lt;li&gt;負荷分散ネットワーク&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;という設定を行っている.&lt;/p&gt;
&lt;h2 id="ロードバランスしたアプリを動かす"&gt;ロードバランスしたアプリを動かす
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt;の内容を実行するため, まずはswarmクラスタを初期化する.&lt;br&gt;
swarmについては&lt;a class="link" href="https://docs.docker.com/get-started/part4/" target="_blank" rel="noopener"
 &gt;Part 4&lt;/a&gt;で説明するので, 今はおまじないだと思って大丈夫.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker swarm init
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Swarm initialized: current node &lt;span class="o"&gt;(&lt;/span&gt;hw3rcr1q9vlpp3qgfw959knwb&lt;span class="o"&gt;)&lt;/span&gt; is now a manager.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;それでは&lt;code&gt;docker stack deploy&lt;/code&gt;コマンドを使用して実際にアプリを立ち上げる.&lt;br&gt;
&lt;code&gt;-c FILE_PATH&lt;/code&gt;オプションで使用する&lt;code&gt;docker-compose.yml&lt;/code&gt;へのパスを指定できる.&lt;br&gt;
今回は現在のディレクトリにある&lt;code&gt;docker-compose.yml&lt;/code&gt;を指定して, getstartedlabという名前のアプリ(スタック)を起動する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker-compose.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker stack deploy -c docker-compose.yml getstartedlab
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Creating network getstartedlab_webnet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Creating service getstartedlab_web
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;実際に起動したサービスの一覧は&lt;code&gt;docker service ls&lt;/code&gt;で確認できる.&lt;br&gt;
または, &lt;code&gt;docker stack services getstartedlab&lt;/code&gt;でもgetstartedlabスタックに関連するサービスの一覧が表示される.&lt;br&gt;
今回はgetstartedlabスタックの中でgetstartedlab_webというサービスが作成されていることが確認できる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker service ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ID NAME MODE REPLICAS IMAGE PORTS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bggiqgkl98zv getstartedlab_web replicated 5/5 uzimihsr/get-started:part2 *:4000-&amp;gt;80/tcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker stack services getstartedlab
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ID NAME MODE REPLICAS IMAGE PORTS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bggiqgkl98zv getstartedlab_web replicated 5/5 uzimihsr/get-started:part2 *:4000-&amp;gt;80/tcp
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;また, サービスの中で起動されているコンテナはタスクと呼ばれ, それぞれにユニークなIDが振られて管理される.&lt;br&gt;
今回は&lt;code&gt;docker service ps&lt;/code&gt;コマンドでgetstartedlab_webサービスのタスクを確認する.&lt;br&gt;
または, 他のコンテナが何も起動していない場合に限り&lt;code&gt;docker container ls -q&lt;/code&gt;コマンドでコンテナIDの一覧を取得することができる.&lt;br&gt;
(タスクのIDとは違うことに注意)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker service ps getstartedlab_web
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;p8z32hd4620k getstartedlab_web.1 uzimihsr/get-started:part2 docker-desktop Running Running &lt;span class="m"&gt;8&lt;/span&gt; minutes ago
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;x6qtw0s78rl4 getstartedlab_web.2 uzimihsr/get-started:part2 docker-desktop Running Running &lt;span class="m"&gt;8&lt;/span&gt; minutes ago
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;d5u6qaw9y74a getstartedlab_web.3 uzimihsr/get-started:part2 docker-desktop Running Running &lt;span class="m"&gt;8&lt;/span&gt; minutes ago
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;qmhi68ujtazx getstartedlab_web.4 uzimihsr/get-started:part2 docker-desktop Running Running &lt;span class="m"&gt;8&lt;/span&gt; minutes ago
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;j692c5bbtilh getstartedlab_web.5 uzimihsr/get-started:part2 docker-desktop Running Running &lt;span class="m"&gt;8&lt;/span&gt; minutes ago
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container ls -q
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;0d3641cc5d70
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3fccce9c79e8
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;7ec5196a0211
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;374fec7c58a7
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;152251abda79
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ロードバランシング(負荷分散)が行われているか確認する.&lt;br&gt;
ブラウザでも良いが, 今回はcurlで何回かURLを叩いてみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://localhost:4000
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;h3&amp;gt;Hello World!&amp;lt;/h3&amp;gt;&amp;lt;b&amp;gt;Hostname:&amp;lt;/b&amp;gt; 374fec7c58a7&amp;lt;br/&amp;gt;&amp;lt;b&amp;gt;Visits:&amp;lt;/b&amp;gt; &amp;lt;i&amp;gt;cannot connect to Redis, counter disabled&amp;lt;/i&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://localhost:4000
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;h3&amp;gt;Hello World!&amp;lt;/h3&amp;gt;&amp;lt;b&amp;gt;Hostname:&amp;lt;/b&amp;gt; 3fccce9c79e8&amp;lt;br/&amp;gt;&amp;lt;b&amp;gt;Visits:&amp;lt;/b&amp;gt; &amp;lt;i&amp;gt;cannot connect to Redis, counter disabled&amp;lt;/i&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://localhost:4000
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;h3&amp;gt;Hello World!&amp;lt;/h3&amp;gt;&amp;lt;b&amp;gt;Hostname:&amp;lt;/b&amp;gt; 0d3641cc5d70&amp;lt;br/&amp;gt;&amp;lt;b&amp;gt;Visits:&amp;lt;/b&amp;gt; &amp;lt;i&amp;gt;cannot connect to Redis, counter disabled&amp;lt;/i&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://localhost:4000
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;h3&amp;gt;Hello World!&amp;lt;/h3&amp;gt;&amp;lt;b&amp;gt;Hostname:&amp;lt;/b&amp;gt; 7ec5196a0211&amp;lt;br/&amp;gt;&amp;lt;b&amp;gt;Visits:&amp;lt;/b&amp;gt; &amp;lt;i&amp;gt;cannot connect to Redis, counter disabled&amp;lt;/i&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://localhost:4000
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;h3&amp;gt;Hello World!&amp;lt;/h3&amp;gt;&amp;lt;b&amp;gt;Hostname:&amp;lt;/b&amp;gt; 152251abda79&amp;lt;br/&amp;gt;&amp;lt;b&amp;gt;Visits:&amp;lt;/b&amp;gt; &amp;lt;i&amp;gt;cannot connect to Redis, counter disabled&amp;lt;/i&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;注目すべきはHostnameの部分で, アクセスする度にホストが変わっていることから負荷分散(ラウンドロビン方式)が正常に行われていることがわかる.&lt;/p&gt;
&lt;p&gt;getstartedlabスタック内のタスクは&lt;code&gt;docker stack ps getstartedlab&lt;/code&gt;で確認できるが,&lt;br&gt;
今回はgetstartedlab_webサービスしか動いていないため,&lt;br&gt;
先程&lt;code&gt;docker service ps&lt;/code&gt;で確認したのと同じタスクの一覧が表示される.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker stack ps getstartedlab
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;p8z32hd4620k getstartedlab_web.1 uzimihsr/get-started:part2 docker-desktop Running Running &lt;span class="m"&gt;22&lt;/span&gt; minutes ago
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;x6qtw0s78rl4 getstartedlab_web.2 uzimihsr/get-started:part2 docker-desktop Running Running &lt;span class="m"&gt;22&lt;/span&gt; minutes ago
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;d5u6qaw9y74a getstartedlab_web.3 uzimihsr/get-started:part2 docker-desktop Running Running &lt;span class="m"&gt;22&lt;/span&gt; minutes ago
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;qmhi68ujtazx getstartedlab_web.4 uzimihsr/get-started:part2 docker-desktop Running Running &lt;span class="m"&gt;22&lt;/span&gt; minutes ago
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;j692c5bbtilh getstartedlab_web.5 uzimihsr/get-started:part2 docker-desktop Running Running &lt;span class="m"&gt;22&lt;/span&gt; minutes ago
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="アプリをスケーリングする"&gt;アプリをスケーリングする
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt;の&lt;code&gt;services.web.deploy.replicas&lt;/code&gt;の値を変更することでアプリのスケーリングができる.&lt;br&gt;
以下の手順でgetstartedlabスタックを更新してみる.&lt;br&gt;
なお, 更新前にスタックを停止したりコンテナを削除する必要はない(自動でやってくれる).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim docker-compose.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker stack deploy -c docker-compose.yml getstartedlab
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Updating service getstartedlab_web &lt;span class="o"&gt;(&lt;/span&gt;id: bggiqgkl98zvy8ayiqmwxyt79&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;details&gt;&lt;summary&gt;レプリカ数を変更したdocker-compose.yml&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;3&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;web&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;uzimihsr/get-started:part2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# イメージインスタンスの数を3に指定&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;replicas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;limits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cpus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;0.1&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;50M&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;restart_policy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;on&lt;/span&gt;-&lt;span class="l"&gt;failure&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;4000:80&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;webnet&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;webnet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;再びgetstartedlabスタックのタスクを確認してみると, タスクが減っている(今回は3を指定した)ことが確認できる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker stack ps getstartedlab
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;p8z32hd4620k getstartedlab_web.1 uzimihsr/get-started:part2 docker-desktop Running Running &lt;span class="m"&gt;35&lt;/span&gt; minutes ago
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;x6qtw0s78rl4 getstartedlab_web.2 uzimihsr/get-started:part2 docker-desktop Running Running &lt;span class="m"&gt;35&lt;/span&gt; minutes ago
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;d5u6qaw9y74a getstartedlab_web.3 uzimihsr/get-started:part2 docker-desktop Running Running &lt;span class="m"&gt;35&lt;/span&gt; minutes ago
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;余談だが, &lt;code&gt;docker inspect&lt;/code&gt;コマンドでコンテナ(タスク)の詳細を確認することもできる.&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;docker inspect&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker inspect p8z32hd4620k
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;ID&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;p8z32hd4620kaipbv9uzlte2j&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Version&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Index&amp;#34;&lt;/span&gt;: &lt;span class="m"&gt;22&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;CreatedAt&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;2019-10-06T09:01:36.6249845Z&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;UpdatedAt&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;2019-10-06T09:01:41.9956973Z&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Labels&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Spec&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;ContainerSpec&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Image&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;uzimihsr/get-started:part2@sha256:ca9c71fd6d4195a2dd6e83f708383451b612910d64e7103a26f710b4428fbbc9&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Labels&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;com.docker.stack.namespace&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;getstartedlab&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Privileges&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;CredentialSpec&amp;#34;&lt;/span&gt;: null,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;SELinuxContext&amp;#34;&lt;/span&gt;: null
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Isolation&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;default&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Resources&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Limits&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;NanoCPUs&amp;#34;&lt;/span&gt;: 100000000,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;MemoryBytes&amp;#34;&lt;/span&gt;: &lt;span class="m"&gt;52428800&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;RestartPolicy&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Condition&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;on-failure&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;MaxAttempts&amp;#34;&lt;/span&gt;: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Placement&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Platforms&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Architecture&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;amd64&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;OS&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;linux&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Networks&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Target&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;uvihn12ykm2owgxebox1wxrb7&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Aliases&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;web&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;ForceUpdate&amp;#34;&lt;/span&gt;: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;ServiceID&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;bggiqgkl98zvy8ayiqmwxyt79&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Slot&amp;#34;&lt;/span&gt;: 1,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;NodeID&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;hw3rcr1q9vlpp3qgfw959knwb&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Status&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Timestamp&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;2019-10-06T09:01:41.9350846Z&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;State&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;running&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Message&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;started&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;ContainerStatus&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;ContainerID&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;374fec7c58a77a554ebdd5b079fcd72b36462275f99c730131f0a0b83744dfeb&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;PID&amp;#34;&lt;/span&gt;: 71366,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;ExitCode&amp;#34;&lt;/span&gt;: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;PortStatus&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;DesiredState&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;running&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;NetworksAttachments&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Network&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;ID&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;5w9oj87tachjift8phcql9ayo&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Version&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Index&amp;#34;&lt;/span&gt;: &lt;span class="m"&gt;6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;CreatedAt&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;2019-10-06T08:55:54.1014898Z&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;UpdatedAt&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;2019-10-06T08:55:54.117508Z&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Spec&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Name&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;ingress&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Labels&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;DriverConfiguration&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Ingress&amp;#34;&lt;/span&gt;: true,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;IPAMOptions&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Driver&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Configs&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Subnet&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;10.255.0.0/16&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Gateway&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;10.255.0.1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Scope&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;swarm&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;DriverState&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Name&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;overlay&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Options&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;com.docker.network.driver.overlay.vxlanid_list&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;4096&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;IPAMOptions&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Driver&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Name&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;default&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Configs&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Subnet&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;10.255.0.0/16&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Gateway&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;10.255.0.1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Addresses&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;10.255.0.4/16&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Network&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;ID&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;uvihn12ykm2owgxebox1wxrb7&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Version&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Index&amp;#34;&lt;/span&gt;: &lt;span class="m"&gt;12&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;CreatedAt&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;2019-10-06T09:01:32.1749865Z&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;UpdatedAt&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;2019-10-06T09:01:32.1787669Z&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Spec&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Name&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;getstartedlab_webnet&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Labels&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;com.docker.stack.namespace&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;getstartedlab&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;DriverConfiguration&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Name&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;overlay&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Scope&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;swarm&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;DriverState&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Name&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;overlay&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Options&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;com.docker.network.driver.overlay.vxlanid_list&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;4097&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;IPAMOptions&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Driver&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Name&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;default&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Configs&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Subnet&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;10.0.0.0/24&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Gateway&amp;#34;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;#34;10.0.0.1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Addresses&amp;#34;&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;10.0.0.3/24&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;h3 id="アプリとswarmの停止"&gt;アプリとswarmの停止
&lt;/h3&gt;&lt;p&gt;アプリ(スタック)を停止するには&lt;code&gt;docker stack rm&lt;/code&gt;コマンドを使用する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker stack rm getstartedlab
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Removing service getstartedlab_web
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Removing network getstartedlab_webnet
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;また, swarmも&lt;code&gt;docker swarm leave&lt;/code&gt;コマンドで停止する.&lt;br&gt;
&lt;code&gt;--force&lt;/code&gt;オプションで強制的に停止できる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker swarm leave --force
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node left the swarm.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="感想まとめ"&gt;感想(まとめ)
&lt;/h2&gt;&lt;p&gt;仕方ない部分があるが, swarmとスタックに関する説明が後回しなのはちょっとわかりづらいと思った.&lt;br&gt;
あと後半の説明が力尽きてる感があった.&lt;br&gt;
要点としては,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;コンテナを実用化するには負荷分散やスケーリングが必要になること&lt;/li&gt;
&lt;li&gt;それらの設定を管理するためにサービスを使うこと&lt;/li&gt;
&lt;li&gt;サービス(とネットワーク)は&lt;code&gt;docker-compose.yml&lt;/code&gt;で定義できること&lt;/li&gt;
&lt;li&gt;アプリを起動する前にswarmクラスタを初期化すること
&lt;ul&gt;
&lt;li&gt;swarmに関してはPart4で説明&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;アプリはスタックという単位で扱うこと
&lt;ul&gt;
&lt;li&gt;スタックに関してはPart5で説明&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;レプリカ数を変化させることでアプリのスケーリングができること&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;がわかれば十分だと思う.&lt;/p&gt;
&lt;p&gt;次は&lt;a class="link" href="https://docs.docker.com/get-started/part4/" target="_blank" rel="noopener"
 &gt;Get Started, Part 4: Swarms&lt;/a&gt;を読む.&lt;/p&gt;</description></item><item><title>[Deprecated]Docker Get Startedを読む Part2</title><link>https://blog.uzimihsr.com/post/2019-10-05-docker-get-started-02/</link><pubDate>Sat, 05 Oct 2019 12:47:56 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2019-10-05-docker-get-started-02/</guid><description>&lt;h2 id="dockerおさらい"&gt;Dockerおさらい
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2019-10-03-docker-get-started-01/" target="_blank" rel="noopener"
 &gt;前回&lt;/a&gt;のつづき&lt;/p&gt;
&lt;h2 id="deprecated"&gt;Deprecated
&lt;/h2&gt;&lt;p&gt;公式の&lt;a class="link" href="https://docs.docker.com/get-started/" target="_blank" rel="noopener"
 &gt;Get Started&lt;/a&gt;が更新されてしまったので,&lt;br&gt;
この記事の内容は古くなっている. 非推奨.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="読んだもの"&gt;読んだもの
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/part2/" target="_blank" rel="noopener"
 &gt;Get Started, Part 2: Containers&lt;/a&gt;&lt;br&gt;
主にコンテナをつくるためのDockerfileの書き方とか, イメージの取り扱いに関する内容.&lt;/p&gt;
&lt;h2 id="事前準備"&gt;事前準備
&lt;/h2&gt;&lt;p&gt;このパートに入る前に以下の条件をクリアすること.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;バージョン1.13以降のDockerがインストール済みであること&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.docker.com/get-started/" target="_blank" rel="noopener"
 &gt;Part 1&lt;/a&gt;の内容を理解していること&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$ docker run hello-world&lt;/code&gt;が正常に動くこと&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="はじめに"&gt;はじめに
&lt;/h2&gt;&lt;p&gt;Dockerによるアプリ開発には大きく分けて3つの段階がある.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;スタック
&lt;ul&gt;
&lt;li&gt;一番上&lt;/li&gt;
&lt;li&gt;全てのサービスの挙動を定義する&lt;/li&gt;
&lt;li&gt;Part 5で説明&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;サービス
&lt;ul&gt;
&lt;li&gt;スタックとコンテナの中間&lt;/li&gt;
&lt;li&gt;実際のコンテナの挙動を定義する&lt;/li&gt;
&lt;li&gt;Part 3で説明&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;コンテナ
&lt;ul&gt;
&lt;li&gt;一番下&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;このパートで説明&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="新しい開発環境"&gt;新しい開発環境
&lt;/h2&gt;&lt;p&gt;Pythonでのアプリ開発を例に通常のマシンとDockerでの開発を比較する.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;通常のマシンの場合:
&lt;ul&gt;
&lt;li&gt;Pythonランタイムのインストールが必要&lt;/li&gt;
&lt;li&gt;アプリの動作/開発環境のセットアップが必要
&lt;ul&gt;
&lt;li&gt;(超意訳)アプリが動作するための依存関係とかを全部クリアする必要があるので, マシンが他の用途に使いづらくなる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Dockerの場合:
&lt;ul&gt;
&lt;li&gt;Pythonランタイムが動くイメージがすでにあるのでインストールが不要&lt;/li&gt;
&lt;li&gt;コードや依存するパッケージなどを全て1つのイメージにまとめることができる&lt;/li&gt;
&lt;li&gt;そのイメージは&lt;code&gt;Dockerfile&lt;/code&gt;を使って定義できる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="dockerfileによるコンテナの定義"&gt;Dockerfileによるコンテナの定義
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Dockerfile&lt;/code&gt;はコンテナの中身を定義する.&lt;br&gt;
コンテナ内のネットワークインターフェースとかディスクドライブは,&lt;br&gt;
コンテナを動作させるシステムの環境からは切り離されて仮想化されている.&lt;br&gt;
したがって, 開発者はコンテナのポートを外部に開放する設定と,&lt;br&gt;
アプリに必要なファイルのコンテナ内へのコピーに気を配るだけで良い.&lt;br&gt;
たったそれだけで, どの環境でもDockerさえあれば同じように動作するコンテナを作ることができる.&lt;/p&gt;
&lt;h3 id="dockerfile"&gt;Dockerfile
&lt;/h3&gt;&lt;p&gt;実際にDockerfileを書いてみる.&lt;br&gt;
適当なディレクトリで, &lt;code&gt;Dockerfile&lt;/code&gt;という名前のファイルを以下の内容で作成する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mkdir workspace
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; workspace
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim Dockerfile
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;details&gt;&lt;summary&gt;Dockerfile&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-docker" data-lang="docker"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# FROM : 親イメージの指定を行う.&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# pythonの公式イメージをこれからつくるイメージの親イメージとして使用する&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;python:2.7-slim&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# WORKDIR : イメージ内での作業ディレクトリを指定する.&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# このイメージ内での作業ディレクトリを/appにする&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# /appがない場合は自動で生成される&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/app&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# COPY : ローカルの環境からイメージにファイルをコピーする.&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# このDockerfileを開いている現在のディレクトリ(workspace)の内容をイメージ内の/appにコピーする&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; . /app&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# RUN : イメージの中でコマンドを実行する.&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# pip(pythonのパッケージマネージャ)を使用して, requirements.txt(コピーしてきたもの)に記述されている必要なパッケージを全てこのイメージにインストールする&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# このDockerfileを編集している今のシステムにはインストールされない&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; pip install --trusted-host pypi.python.org -r requirements.txt&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# EXPOSE : コンテナのポートを外部に開放する.&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# このコンテナの80番ポートを外部からアクセス可能にする&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;80&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# ENV : コンテナ内での環境変数を定義する&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 環境変数NAMEにworldを定義する&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ENV&lt;/span&gt; NAME World&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# CMD : コンテナが起動した際に実行するコマンドを定義する.&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# コンテナが起動した際に`$ python app.py`を実行する&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CMD&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;python&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;app.py&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;ざっくり説明するとこの&lt;code&gt;Dockerfile&lt;/code&gt;は&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;pythonが動かせるイメージを持ってくる&lt;/li&gt;
&lt;li&gt;必要なファイルをローカルからコピーする&lt;/li&gt;
&lt;li&gt;アプリに必要なパッケージとかの設定をする&lt;/li&gt;
&lt;li&gt;コンテナのポートを開放する&lt;/li&gt;
&lt;li&gt;アプリの起動コマンドを設定する&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;という一連の操作を定義している.&lt;br&gt;
&lt;code&gt;requirements.txt&lt;/code&gt;と&lt;code&gt;app.py&lt;/code&gt;はこのあとイメージをビルドする前に作成する.&lt;/p&gt;
&lt;h2 id="今回作るアプリ"&gt;今回作るアプリ
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Dockerfile&lt;/code&gt;内で使用する&lt;code&gt;requirements.txt&lt;/code&gt;と&lt;code&gt;app.py&lt;/code&gt;を作成する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;pwd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/path/to/workspace
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim requirements.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim app.py
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;details&gt;&lt;summary&gt;requirements.txt&lt;/summary&gt;&lt;div&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Flask
Redis
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;Flask&lt;/code&gt; : pythonでwebアプリを作るためのフレームワーク&lt;br&gt;
&lt;code&gt;Redis&lt;/code&gt; : データベース(Redis)を扱うためのパッケージ&lt;/p&gt;
&lt;/div&gt;&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;app.py&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;redis&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Redis&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RedisError&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;socket&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Connect to Redis&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;redis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Redis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;redis&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;socket_connect_timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;socket_timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vm"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;visits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;incr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;counter&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;RedisError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;visits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;lt;i&amp;gt;cannot connect to Redis, counter disabled&amp;lt;/i&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;lt;h3&amp;gt;Hello &lt;/span&gt;&lt;span class="si"&gt;{name}&lt;/span&gt;&lt;span class="s2"&gt;!&amp;lt;/h3&amp;gt;&amp;#34;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&amp;lt;b&amp;gt;Hostname:&amp;lt;/b&amp;gt; &lt;/span&gt;&lt;span class="si"&gt;{hostname}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;br/&amp;gt;&amp;#34;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&amp;lt;b&amp;gt;Visits:&amp;lt;/b&amp;gt; &lt;/span&gt;&lt;span class="si"&gt;{visits}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;NAME&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;world&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;hostname&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gethostname&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;visits&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;visits&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;0.0.0.0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;&lt;code&gt;requirements.txt&lt;/code&gt;は今回作成するFlaskアプリに必要なパッケージを定義し,&lt;br&gt;
&lt;code&gt;app.py&lt;/code&gt;はHTTPアクセスに対して変数&lt;code&gt;html&lt;/code&gt;で定義された内容(環境変数&lt;code&gt;NAME&lt;/code&gt;, 接続してきたホスト名, DBで保存しているカウント数)を表示する.&lt;br&gt;
これで必要なファイルの準備は完了.&lt;br&gt;
しかし&lt;code&gt;Redis&lt;/code&gt;が実際にイメージの中でまだ動いていないため,&lt;br&gt;
このまま起動してもエラーメッセージが表示されることに注意.&lt;br&gt;
(&lt;code&gt;resuirements.txt&lt;/code&gt;で入れたのはあくまでpythonからRedisを使うためのパッケージ)&lt;/p&gt;
&lt;p&gt;以上でアプリを動かす準備ができた.&lt;br&gt;
本来このFlaskアプリを動作させるためにはPythonやパッケージ(&lt;code&gt;Flask&lt;/code&gt;, &lt;code&gt;Redis&lt;/code&gt;)をシステムにインストールする必要があるが,&lt;br&gt;
今回はそれらがすべてイメージ内で行われるためその必要がない.&lt;br&gt;
また, Dockerで使用するイメージはそれ単体が存在するだけで使用できるので,&lt;br&gt;
イメージをシステムにインストールする必要もない. 超便利!&lt;br&gt;
(実際にDockerを使わずに何もない環境からこのアプリを作るのはちょっと面倒)&lt;/p&gt;
&lt;h2 id="アプリのビルド"&gt;アプリのビルド
&lt;/h2&gt;&lt;p&gt;アプリに必要なものは全て準備できたので, さっそくビルドする.&lt;br&gt;
まずは現在のディレクトリに&lt;code&gt;Dockerfile&lt;/code&gt;, &lt;code&gt;app.py&lt;/code&gt;, &lt;code&gt;requirements.txt&lt;/code&gt;があることを確認する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;pwd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/path/to/workspace
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Dockerfile app.py requirements.txt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ビルド用のコマンド&lt;code&gt;docker build&lt;/code&gt;を使用してイメージのビルドを行う.&lt;br&gt;
&lt;code&gt;-t repository:tag&lt;/code&gt;のオプションでリポジトリ名:タグ(≒イメージ名)の指定ができる.&lt;br&gt;
(&lt;code&gt;tag&lt;/code&gt;を指定しない場合は自動的に&lt;code&gt;latest&lt;/code&gt;が付与される. 今はそんなに重要じゃない.)&lt;br&gt;
最後の&lt;code&gt;.&lt;/code&gt;は現在のディレクトリにある&lt;code&gt;Dockerfile&lt;/code&gt;を使用することを示す.&lt;br&gt;
今回はfriendlyhelloというリポジトリ名でイメージをビルドする.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker build -t friendlyhello .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;余談だが, ビルド時のログを見ると&lt;code&gt;Dockerfile&lt;/code&gt;の内容を1行ずつ実行していることがわかる.&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;ビルド時のログ&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker build -t friendlyhello .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Sending build context to Docker daemon 5.12kB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 1/7 : FROM python:2.7-slim
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2.7-slim: Pulling from library/python
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;b8f262c62ec6: Pull &lt;span class="nb"&gt;complete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;8cbb51e0b077: Pull &lt;span class="nb"&gt;complete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;82627a456962: Pull &lt;span class="nb"&gt;complete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;33f3f5c560fe: Pull &lt;span class="nb"&gt;complete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Digest: sha256:68bb099b780cf7aa60df3af68d573dc420907acfa54cbb2a53ade8886d965272
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Status: Downloaded newer image &lt;span class="k"&gt;for&lt;/span&gt; python:2.7-slim
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; f462855313cd
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 2/7 : WORKDIR /app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; Running in 4d73545dac95
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Removing intermediate container 4d73545dac95
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; 9cd55a4d5845
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 3/7 : COPY . /app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; 689b85f40a7f
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 4/7 : RUN pip install --trusted-host pypi.python.org -r requirements.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; Running in e8a28b64a049
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;t be maintained after that date. A future version of pip will drop support &lt;span class="k"&gt;for&lt;/span&gt; Python 2.7. More details about Python &lt;span class="m"&gt;2&lt;/span&gt; support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Collecting Flask &lt;span class="o"&gt;(&lt;/span&gt;from -r requirements.txt &lt;span class="o"&gt;(&lt;/span&gt;line 1&lt;span class="o"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Downloading https://files.pythonhosted.org/packages/9b/93/628509b8d5dc749656a9641f4caf13540e2cdec85276964ff8f43bbb1d3b/Flask-1.1.1-py2.py3-none-any.whl &lt;span class="o"&gt;(&lt;/span&gt;94kB&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Collecting Redis &lt;span class="o"&gt;(&lt;/span&gt;from -r requirements.txt &lt;span class="o"&gt;(&lt;/span&gt;line 2&lt;span class="o"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Downloading https://files.pythonhosted.org/packages/bd/64/b1e90af9bf0c7f6ef55e46b81ab527b33b785824d65300bb65636534b530/redis-3.3.8-py2.py3-none-any.whl &lt;span class="o"&gt;(&lt;/span&gt;66kB&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Collecting click&amp;gt;&lt;span class="o"&gt;=&lt;/span&gt;5.1 &lt;span class="o"&gt;(&lt;/span&gt;from Flask-&amp;gt;-r requirements.txt &lt;span class="o"&gt;(&lt;/span&gt;line 1&lt;span class="o"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Downloading https://files.pythonhosted.org/packages/fa/37/45185cb5abbc30d7257104c434fe0b07e5a195a6847506c074527aa599ec/Click-7.0-py2.py3-none-any.whl &lt;span class="o"&gt;(&lt;/span&gt;81kB&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Collecting Werkzeug&amp;gt;&lt;span class="o"&gt;=&lt;/span&gt;0.15 &lt;span class="o"&gt;(&lt;/span&gt;from Flask-&amp;gt;-r requirements.txt &lt;span class="o"&gt;(&lt;/span&gt;line 1&lt;span class="o"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Downloading https://files.pythonhosted.org/packages/ce/42/3aeda98f96e85fd26180534d36570e4d18108d62ae36f87694b476b83d6f/Werkzeug-0.16.0-py2.py3-none-any.whl &lt;span class="o"&gt;(&lt;/span&gt;327kB&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Collecting itsdangerous&amp;gt;&lt;span class="o"&gt;=&lt;/span&gt;0.24 &lt;span class="o"&gt;(&lt;/span&gt;from Flask-&amp;gt;-r requirements.txt &lt;span class="o"&gt;(&lt;/span&gt;line 1&lt;span class="o"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Downloading https://files.pythonhosted.org/packages/76/ae/44b03b253d6fade317f32c24d100b3b35c2239807046a4c953c7b89fa49e/itsdangerous-1.1.0-py2.py3-none-any.whl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Collecting Jinja2&amp;gt;&lt;span class="o"&gt;=&lt;/span&gt;2.10.1 &lt;span class="o"&gt;(&lt;/span&gt;from Flask-&amp;gt;-r requirements.txt &lt;span class="o"&gt;(&lt;/span&gt;line 1&lt;span class="o"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Downloading https://files.pythonhosted.org/packages/65/e0/eb35e762802015cab1ccee04e8a277b03f1d8e53da3ec3106882ec42558b/Jinja2-2.10.3-py2.py3-none-any.whl &lt;span class="o"&gt;(&lt;/span&gt;125kB&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Collecting MarkupSafe&amp;gt;&lt;span class="o"&gt;=&lt;/span&gt;0.23 &lt;span class="o"&gt;(&lt;/span&gt;from Jinja2&amp;gt;&lt;span class="o"&gt;=&lt;/span&gt;2.10.1-&amp;gt;Flask-&amp;gt;-r requirements.txt &lt;span class="o"&gt;(&lt;/span&gt;line 1&lt;span class="o"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Downloading https://files.pythonhosted.org/packages/fb/40/f3adb7cf24a8012813c5edb20329eb22d5d8e2a0ecf73d21d6b85865da11/MarkupSafe-1.1.1-cp27-cp27mu-manylinux1_x86_64.whl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Installing collected packages: click, Werkzeug, itsdangerous, MarkupSafe, Jinja2, Flask, Redis
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Successfully installed Flask-1.1.1 Jinja2-2.10.3 MarkupSafe-1.1.1 Redis-3.3.8 Werkzeug-0.16.0 click-7.0 itsdangerous-1.1.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Removing intermediate container e8a28b64a049
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; 5aeaca8be74e
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 5/7 : EXPOSE &lt;span class="m"&gt;80&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; Running in 7ee28830810e
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Removing intermediate container 7ee28830810e
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; a8c8153b4bd3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 6/7 : ENV NAME World
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; Running in 98d95719d709
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Removing intermediate container 98d95719d709
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; cfd1c0282f2e
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 7/7 : CMD &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;python&amp;#34;&lt;/span&gt;, &lt;span class="s2"&gt;&amp;#34;app.py&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; Running in 5e9ef2b09c2a
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Removing intermediate container 5e9ef2b09c2a
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; c807461f0dca
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Successfully built c807461f0dca
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Successfully tagged friendlyhello:latest
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;ビルドしたイメージを確認する.&lt;br&gt;
&lt;code&gt;docker image ls&lt;/code&gt;コマンドでローカルマシンにあるイメージの一覧が取得できる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;REPOSITORY TAG IMAGE ID CREATED SIZE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;friendlyhello latest c807461f0dca &lt;span class="m"&gt;9&lt;/span&gt; minutes ago 148MB
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="アプリの実行"&gt;アプリの実行
&lt;/h2&gt;&lt;p&gt;いよいよ作成したイメージからコンテナを起動し, アプリを実行する.&lt;br&gt;
&lt;code&gt;docker run&lt;/code&gt;コマンドで使用するイメージを指定するとコンテナが立ち上がる.&lt;br&gt;
&lt;code&gt;-p localport:containerport&lt;/code&gt;オプションでコンテナを起動するローカルマシンのポート(localport)をコンテナのポート(containerport)に割り当てることができる.&lt;br&gt;
今回はローカルマシンの4000番ポートを起動するコンテナの80番ポートに割り当てる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker run -p 4000:80 friendlyhello
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* Serving Flask app &lt;span class="s2"&gt;&amp;#34;app&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;lazy loading&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* Environment: production
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; WARNING: This is a development server. Do not use it in a production deployment.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Use a production WSGI server instead.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* Debug mode: off
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* Running on http://0.0.0.0:80/ &lt;span class="o"&gt;(&lt;/span&gt;Press CTRL+C to quit&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Flaskのログが表示され, &lt;code&gt;http://0.0.0.0:80/&lt;/code&gt;にアクセスするよう促されるが,&lt;br&gt;
これはあくまでコンテナ内でのメッセージなので,&lt;br&gt;
コンテナの80番ポートに割り当てられているローカルマシンの4000番ポート(http://localhost:4000) をブラウザで開く.&lt;br&gt;
&lt;img alt="アプリを開いた画面" class="gallery-image" data-flex-basis="719px" data-flex-grow="299" height="284" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-10-05-docker-get-started-02/2019-10-05-screenshot.png" srcset="https://blog.uzimihsr.com/post/2019-10-05-docker-get-started-02/2019-10-05-screenshot_hu_2c78545e20a2e804.png 800w, https://blog.uzimihsr.com/post/2019-10-05-docker-get-started-02/2019-10-05-screenshot.png 851w" width="851"&gt;&lt;/p&gt;
&lt;p&gt;アプリが動作して, Hello, World!とホスト名が表示される.&lt;br&gt;
前述の通り, イメージ内にRedisがないのでその旨を示すエラーメッセージも表示されている.&lt;/p&gt;
&lt;p&gt;一旦&lt;code&gt;Ctrl+C&lt;/code&gt;でコンテナを停止し, 今度は&lt;code&gt;-d&lt;/code&gt;オプションをつけてバックグラウンドでコンテナを起動する.&lt;br&gt;
この起動方法をデタッチドモードと言う.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker run -d -p 4000:80 friendlyhello
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;先程はブラウザで開いたので, 今度は&lt;code&gt;curl&lt;/code&gt;コマンドで動作確認する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://localhost:4000
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;h3&amp;gt;Hello World!&amp;lt;/h3&amp;gt;&amp;lt;b&amp;gt;Hostname:&amp;lt;/b&amp;gt; xxxxxxxxxxxx&amp;lt;br/&amp;gt;&amp;lt;b&amp;gt;Visits:&amp;lt;/b&amp;gt; &amp;lt;i&amp;gt;cannot connect to Redis, counter disabled&amp;lt;/i&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ブラウザのときと同じHTTPレスポンスが返ってくることがわかる.&lt;/p&gt;
&lt;p&gt;また, 起動中のコンテナ一覧を&lt;code&gt;docker container ls&lt;/code&gt;コマンドで確認できる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cc47aa120f15 friendlyhello &lt;span class="s2"&gt;&amp;#34;python app.py&amp;#34;&lt;/span&gt; &lt;span class="m"&gt;58&lt;/span&gt; seconds ago Up &lt;span class="m"&gt;57&lt;/span&gt; seconds 0.0.0.0:4000-&amp;gt;80/tcp zen_liskov
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;今度は起動中のコンテナを停止してみる.&lt;br&gt;
コンテナの停止には&lt;code&gt;docker container stop&lt;/code&gt;コマンドを使用する.&lt;br&gt;
停止するコンテナは&lt;code&gt;CONTAINER ID&lt;/code&gt;で指定する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container stop cc47aa120f15
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="イメージをシェアする"&gt;イメージをシェアする
&lt;/h2&gt;&lt;p&gt;ビルドしたイメージを別の環境でも動かすためにはレジストリにアップロードする必要がある.&lt;br&gt;
レジストリとはリポジトリが集まる場所で, リポジトリとはイメージの集まりのことである.&lt;br&gt;
レジストリの1つのアカウントは複数のリポジトリを作ることができるので,&lt;br&gt;
感覚的にはレジストリがGitHub, リポジトリがGitHubリポジトリに似ている.&lt;br&gt;
デフォルトでは&lt;a class="link" href="https://hub.docker.com/" target="_blank" rel="noopener"
 &gt;Docker Hub&lt;/a&gt;がレジストリとして使用される.&lt;/p&gt;
&lt;h3 id="docker-idでログインする"&gt;Docker IDでログインする
&lt;/h3&gt;&lt;p&gt;事前に&lt;a class="link" href="https://hub.docker.com/" target="_blank" rel="noopener"
 &gt;hub.docker.com&lt;/a&gt;でアカウントを作成しておく.&lt;br&gt;
ローカルマシンからDocker Hubにログインするには&lt;code&gt;docker login&lt;/code&gt;コマンドを使用する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker login
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="イメージにタグをつける"&gt;イメージにタグをつける
&lt;/h3&gt;&lt;p&gt;レジストリ上でイメージは&lt;code&gt;username/repository:tag&lt;/code&gt;の形式で識別される(usernameはレジストリID).&lt;br&gt;
Dockerイメージにはタグで意味のあるバージョン名または番号を付与する必要があるので,&lt;br&gt;
イメージをアップロードする前にはタグをつけ直す必要がある.&lt;br&gt;
タグの付与には&lt;code&gt;docker tag&lt;/code&gt;コマンドを使用する.&lt;br&gt;
今回は作成したfriendlyhelloイメージに&lt;code&gt;uzimihsr/get-started:part2&lt;/code&gt;という名前をつける.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker tag friendlyhello uzimihsr/get-started:part2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;イメージ一覧を表示すると, 先程まで使用していたfriendlyhelloと同じイメージIDのuzimihsr/get-startedが作成されている.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;REPOSITORY TAG IMAGE ID CREATED SIZE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;friendlyhello latest c807461f0dca About an hour ago 148MB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uzimihsr/get-started part2 c807461f0dca About an hour ago 148MB
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="イメージを公開する"&gt;イメージを公開する
&lt;/h3&gt;&lt;p&gt;タグ付けしたイメージは&lt;code&gt;docker push&lt;/code&gt;コマンドでアップロードできる.&lt;br&gt;
先程タグを付け直したuzimihsr/get-startedをアップロードする.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker push uzimihsr/get-started:part2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;実際にアップロードしたイメージはここ.&lt;br&gt;
&lt;a class="link" href="https://hub.docker.com/r/uzimihsr/get-started/tags" target="_blank" rel="noopener"
 &gt;https://hub.docker.com/r/uzimihsr/get-started/tags&lt;/a&gt;&lt;br&gt;
&lt;img alt="Docker Hub" class="gallery-image" data-flex-basis="585px" data-flex-grow="244" height="1180" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-10-05-docker-get-started-02/2019-10-05-docker-hub.png" srcset="https://blog.uzimihsr.com/post/2019-10-05-docker-get-started-02/2019-10-05-docker-hub_hu_284b19f1e7cae172.png 800w, https://blog.uzimihsr.com/post/2019-10-05-docker-get-started-02/2019-10-05-docker-hub_hu_c57eca728408bfb2.png 1600w, https://blog.uzimihsr.com/post/2019-10-05-docker-get-started-02/2019-10-05-docker-hub_hu_80e332d4bcfe15f0.png 2400w, https://blog.uzimihsr.com/post/2019-10-05-docker-get-started-02/2019-10-05-docker-hub.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;h3 id="リモートリポジトリから入手したイメージを実行する"&gt;リモートリポジトリから入手したイメージを実行する
&lt;/h3&gt;&lt;p&gt;Docker Hubにイメージの公開ができたので, 試しに公開したイメージを使ってコンテナを起動してみる.&lt;br&gt;
確実にリモートリポジトリから取得したイメージを使用するため, 現在手元にあるイメージとコンテナを削除する.&lt;br&gt;
コンテナの削除には&lt;code&gt;docker container rm&lt;/code&gt;コマンドを使用する.&lt;br&gt;
削除するコンテナのIDを指定するか, &lt;code&gt;$(docker container ls -a -q)&lt;/code&gt;を指定すると全てのコンテナを削除してくれる.&lt;br&gt;
同様にイメージの削除には&lt;code&gt;docker image rm&lt;/code&gt;コマンドを使用する.&lt;br&gt;
今回はコンテナを全削除し, 作成したイメージを削除する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container rm &lt;span class="k"&gt;$(&lt;/span&gt;docker container ls -a -q&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image rm -f c807461f0dca
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;REPOSITORY TAG IMAGE ID CREATED SIZE
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Docker Hubにあるイメージを指定してコンテナを起動させる.&lt;br&gt;
&lt;a class="link" href="https://uzimihsr.github.io/post/2019-10-03-docker-get-started-01/" target="_blank" rel="noopener"
 &gt;Part1&lt;/a&gt;で&lt;a class="link" href="https://hub.docker.com/_/hello-world/" target="_blank" rel="noopener"
 &gt;hello-world&lt;/a&gt;を起動したときと同様に, イメージが手元に無いので自動でダウンロードしてくる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker run -p 4000:80 uzimihsr/get-started:part2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Unable to find image &lt;span class="s1"&gt;&amp;#39;uzimihsr/get-started:part2&amp;#39;&lt;/span&gt; locally
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;part2: Pulling from uzimihsr/get-started
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;b8f262c62ec6: Already exists
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;8cbb51e0b077: Already exists
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;82627a456962: Already exists
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;33f3f5c560fe: Already exists
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;c94901432fd6: Pull &lt;span class="nb"&gt;complete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;15e44dce546a: Pull &lt;span class="nb"&gt;complete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;7f08569cb4d3: Pull &lt;span class="nb"&gt;complete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Digest: sha256:ca9c71fd6d4195a2dd6e83f708383451b612910d64e7103a26f710b4428fbbc9
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Status: Downloaded newer image &lt;span class="k"&gt;for&lt;/span&gt; uzimihsr/get-started:part2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; * Serving Flask app &lt;span class="s2"&gt;&amp;#34;app&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;lazy loading&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; * Environment: production
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; WARNING: This is a development server. Do not use it in a production deployment.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Use a production WSGI server instead.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; * Debug mode: off
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; * Running on http://0.0.0.0:80/ &lt;span class="o"&gt;(&lt;/span&gt;Press CTRL+C to quit&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;再度 http://localhost:4000/ にアクセスすると今までと同様にアプリが起動していることが確認できる.&lt;/p&gt;
&lt;h2 id="感想"&gt;感想
&lt;/h2&gt;&lt;p&gt;Dockerfileのあたりはイメージの根幹を成す部分なのでかなり内容がもりだくさんだった.&lt;br&gt;
要点としては,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Dockerfile&lt;/code&gt;を使ってイメージ(コンテナ)を定義できること&lt;/li&gt;
&lt;li&gt;親となるイメージにいろいろ操作を加えて自分のアプリ用の新しいイメージが作れること&lt;/li&gt;
&lt;li&gt;イメージ内の環境は隔離されていて, ローカルマシンのシステムには影響がないこと&lt;/li&gt;
&lt;li&gt;イメージはタグで管理されること&lt;/li&gt;
&lt;li&gt;ビルドしたイメージはDocker Hubを使って別環境からも参照できること&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;がわかればこのパートは十分だと思う.&lt;/p&gt;
&lt;p&gt;次は&lt;a class="link" href="https://docs.docker.com/get-started/part3/" target="_blank" rel="noopener"
 &gt;Get Started, Part 3: Services&lt;/a&gt;を読みたい.&lt;br&gt;
(追記)&lt;a class="link" href="https://uzimihsr.github.io/post/2019-10-06-docker-get-started-03/" target="_blank" rel="noopener"
 &gt;読んだ&lt;/a&gt;&lt;/p&gt;</description></item><item><title>[Deprecated]Docker Get Startedを読む Part1</title><link>https://blog.uzimihsr.com/post/2019-10-03-docker-get-started-01/</link><pubDate>Thu, 03 Oct 2019 23:54:16 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2019-10-03-docker-get-started-01/</guid><description>&lt;h2 id="dockerおさらい"&gt;Dockerおさらい
&lt;/h2&gt;&lt;p&gt;Dockerについて&lt;a class="link" href="https://www.katacoda.com/courses/docker" target="_blank" rel="noopener"
 &gt;Katacoda&lt;/a&gt;で一通り勉強したので, 復習も兼ねて公式ドキュメントを読んでみる.&lt;/p&gt;
&lt;h2 id="deprecated"&gt;Deprecated
&lt;/h2&gt;&lt;p&gt;公式の&lt;a class="link" href="https://docs.docker.com/get-started/" target="_blank" rel="noopener"
 &gt;Get Started&lt;/a&gt;が更新されてしまったので,&lt;br&gt;
この記事の内容は古くなっている. 非推奨.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="読んだもの"&gt;読んだもの
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/get-started/" target="_blank" rel="noopener"
 &gt;Get Started, Part 1: Orientation and setup&lt;/a&gt;&lt;br&gt;
この記事の内容を自分の主観バリバリで超意訳しながらまとめていく.&lt;/p&gt;
&lt;h2 id="dockerのコンセプト"&gt;Dockerのコンセプト
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Dockerとはなんぞや?
&lt;ul&gt;
&lt;li&gt;コンテナでアプリを開発, デプロイ, 実行するためのプラットフォーム.&lt;/li&gt;
&lt;li&gt;コンテナ自体は前からある技術だけど, コンテナを使ってアプリを簡単にデプロイできる点が新しい.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;コンテナ化すると良いこと
&lt;ul&gt;
&lt;li&gt;どんなに複雑なアプリでもコンテナ化が可能&lt;/li&gt;
&lt;li&gt;複数のコンテナで同じカーネルを活用するため軽量&lt;/li&gt;
&lt;li&gt;臨機応変にアプリの更新が可能&lt;/li&gt;
&lt;li&gt;ローカルでも, クラウド上でも, どこでも利用できる&lt;/li&gt;
&lt;li&gt;コンテナの複製が簡単なのでスケーラビリティが高い&lt;/li&gt;
&lt;li&gt;コンテナ同士を柔軟に組み合わせて利用できる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="イメージとコンテナ"&gt;イメージとコンテナ
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;コンテナってどう作るの?
&lt;ul&gt;
&lt;li&gt;イメージを実行することで起動する&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;じゃあイメージってなに?
&lt;ul&gt;
&lt;li&gt;アプリを動かすために必要なものが全部入った実行可能なパッケージ&lt;/li&gt;
&lt;li&gt;イメージが実行状態になるとコンテナになる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="コンテナと仮想マシンのちがい"&gt;コンテナと仮想マシンのちがい
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;コンテナ
&lt;ul&gt;
&lt;li&gt;アプリの実行に必要な環境をつくる(OSは1つ)&lt;/li&gt;
&lt;li&gt;コンテナ単体で実行できる&lt;/li&gt;
&lt;li&gt;実行時に必要な分のリソース(メモリ)しか食わない&lt;/li&gt;
&lt;li&gt;一言で言えば軽いが目的の用途(アプリの実行)にしか使えない&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;仮想マシン(VM)
&lt;ul&gt;
&lt;li&gt;本当のマシンとほぼ同じ環境を作る(それぞれにOSがある)&lt;/li&gt;
&lt;li&gt;VMを管理するハイパーバイザを通さないとアクセスできない&lt;/li&gt;
&lt;li&gt;VMを維持している間はそれらを管理するマシンのリソースを喰っている&lt;/li&gt;
&lt;li&gt;一言で言えば重いが用途が多彩&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="dockerの環境構築"&gt;Dockerの環境構築
&lt;/h2&gt;&lt;p&gt;自分の場合は&lt;a class="link" href="https://hub.docker.com/editions/community/docker-ce-desktop-mac" target="_blank" rel="noopener"
 &gt;Docker Desktop for Mac&lt;/a&gt;をインストールした.&lt;br&gt;
簡単なので手順は割愛.&lt;br&gt;
docker-composeとKubernetesも入っているので便利.&lt;/p&gt;
&lt;h3 id="dockerのバージョン確認"&gt;Dockerのバージョン確認
&lt;/h3&gt;&lt;p&gt;さっそくバージョン確認用のコマンドを打ってみる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 普通のアプリと同様に--versionまたは-vオプションで確認可能&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker --version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Docker version 19.03.2, build 6a30dfc
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;details&gt;&lt;summary&gt;さらに詳細な情報を表示する&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 詳細情報を表示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# イメージ, コンテナの数とかが表示される&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker info
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Client:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Debug Mode: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Server:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Containers: &lt;span class="m"&gt;70&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Running: &lt;span class="m"&gt;32&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Paused: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Stopped: &lt;span class="m"&gt;38&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Images: &lt;span class="m"&gt;74&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Server Version: 19.03.2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Storage Driver: overlay2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Backing Filesystem: extfs
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Supports d_type: &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Native Overlay Diff: &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Logging Driver: json-file
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Cgroup Driver: cgroupfs
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Plugins:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Volume: &lt;span class="nb"&gt;local&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Network: bridge host ipvlan macvlan null overlay
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Log: awslogs fluentd gcplogs gelf journald json-file &lt;span class="nb"&gt;local&lt;/span&gt; logentries splunk syslog
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Swarm: inactive
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Runtimes: runc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Default Runtime: runc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Init Binary: docker-init
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; containerd version: 894b81a4b802e4eb2a91d1ce216b8817763c29fb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; runc version: 425e105d5a03fabd737a126ad93d62a9eeede87f
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; init version: fec3683
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Security Options:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; seccomp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Profile: default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Kernel Version: 4.9.184-linuxkit
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Operating System: Docker Desktop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; OSType: linux
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Architecture: x86_64
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; CPUs: &lt;span class="m"&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Total Memory: 1.952GiB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Name: docker-desktop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ID: K77N:CV6M:AWUD:E3CZ:B44M:DJSX:4GLO:SNXJ:LXBZ:HUML:A46J:SYHZ
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Docker Root Dir: /var/lib/docker
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Debug Mode: &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File Descriptors: &lt;span class="m"&gt;128&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Goroutines: &lt;span class="m"&gt;122&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; System Time: 2019-10-03T14:18:37.8900535Z
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; EventsListeners: &lt;span class="m"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; HTTP Proxy: gateway.docker.internal:3128
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; HTTPS Proxy: gateway.docker.internal:3129
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Registry: https://index.docker.io/v1/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Labels:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Experimental: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Insecure Registries:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 127.0.0.0/8
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Live Restore Enabled: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Product License: Community Engine
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;h3 id="dockerの動作確認"&gt;Dockerの動作確認
&lt;/h3&gt;&lt;p&gt;DockerでHello, World!する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Hello, World!を表示させるイメージを実行する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# hello-worldという名前のイメージはまだローカルにないので, Docker Hubから自動で取ってくる.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker run hello-world
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Unable to find image &lt;span class="s1"&gt;&amp;#39;hello-world:latest&amp;#39;&lt;/span&gt; locally
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;latest: Pulling from library/hello-world
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Digest: sha256:b8ba256769a0ac28dd126d584e0a2011cd2877f3f76e093a7ae560f2a5301c00
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Status: Downloaded newer image &lt;span class="k"&gt;for&lt;/span&gt; hello-world:latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Hello from Docker!
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;This message shows that your installation appears to be working correctly.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;To generate this message, Docker took the following steps:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 1. The Docker client contacted the Docker daemon.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 2. The Docker daemon pulled the &lt;span class="s2"&gt;&amp;#34;hello-world&amp;#34;&lt;/span&gt; image from the Docker Hub.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;(&lt;/span&gt;amd64&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 3. The Docker daemon created a new container from that image which runs the
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; executable that produces the output you are currently reading.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 4. The Docker daemon streamed that output to the Docker client, which sent it
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; to your terminal.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;To try something more ambitious, you can run an Ubuntu container with:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; $ docker run -it ubuntu bash
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Share images, automate workflows, and more with a free Docker ID:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; https://hub.docker.com/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;For more examples and ideas, visit:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; https://docs.docker.com/get-started/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Docker Hub&lt;/code&gt; : いろんなイメージが共有されてるクラウドサービス, イメージ専門のGitHubみたいなもん&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 手元にあるイメージを一覧表示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;REPOSITORY TAG IMAGE ID CREATED SIZE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hello-world latest fce289e99eb9 &lt;span class="m"&gt;9&lt;/span&gt; months ago 1.84kB
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;REPOSITORY&lt;/code&gt; : イメージの名前(タグがついていないもの)&lt;br&gt;
&lt;code&gt;TAG&lt;/code&gt; : イメージに付くタグ, バージョンとかを表す&lt;br&gt;
&lt;code&gt;IMAGE ID&lt;/code&gt; : イメージに振られるID&lt;br&gt;
&lt;code&gt;CREATED&lt;/code&gt; : イメージがいつ作成されたか&lt;br&gt;
&lt;code&gt;SIZE&lt;/code&gt; : イメージのサイズ&lt;/p&gt;
&lt;h2 id="感想"&gt;感想
&lt;/h2&gt;&lt;p&gt;イメージより先にいきなりコンテナの話から始まるのでちょっととっつきづらかった.&lt;br&gt;
コンテナの特徴とかVMとの違いとか自分の中であやふやだったのでなんとなく整理できてよかった.&lt;/p&gt;
&lt;p&gt;次は&lt;a class="link" href="https://docs.docker.com/get-started/part2/" target="_blank" rel="noopener"
 &gt;Get Started, Part 2: Containers&lt;/a&gt;を読みたい.&lt;br&gt;
(追記)読んだ:&lt;a class="link" href="https://uzimihsr.github.io/post/2019-10-05-docker-get-started-02/" target="_blank" rel="noopener"
 &gt;Part2&lt;/a&gt;&lt;/p&gt;</description></item><item><title>そとちゃんと初期費用</title><link>https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/</link><pubDate>Mon, 23 Sep 2019 15:05:07 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-meow.jpg" alt="Featured image of post そとちゃんと初期費用" /&gt;&lt;h2 id="1人暮らしで猫を養いはじめるのにかかったお金"&gt;1人暮らしで猫を養いはじめるのにかかったお金
&lt;/h2&gt;&lt;p&gt;最近友人に質問されたので, そとちゃんを迎えるときに買い揃えたものと金額をまとめた.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="もくじ"&gt;もくじ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%e3%81%9d%e3%81%a8%e3%81%a1%e3%82%83%e3%82%93" &gt;そとちゃん&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%e8%b2%b7%e3%81%a3%e3%81%9f%e3%82%82%e3%81%ae" &gt;買ったもの&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="そとちゃん"&gt;そとちゃん
&lt;/h3&gt;&lt;p&gt;そとちゃん 3歳 女の子(不妊手術済)&lt;br&gt;
元保護猫&lt;br&gt;
かわいい&lt;br&gt;
あそぶのが好き&lt;br&gt;
&lt;img alt="にゃーん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="2025" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-meow.jpg" srcset="https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-meow_hu_c41840e22de050ad.jpg 800w, https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-meow_hu_3350c68947c4f552.jpg 1600w, https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-meow_hu_255f8eeaa75e5431.jpg 2400w, https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-meow.jpg 2702w" width="2702"&gt;&lt;/p&gt;
&lt;h3 id="買ったもの"&gt;買ったもの
&lt;/h3&gt;&lt;p&gt;基本的にトイレ, 爪とぎ, キャリーバッグは必須だと思う.&lt;br&gt;
モノにもよるけどその3点だけなら1~2万円,&lt;br&gt;
さらに便利なグッズを揃えると追加で3万円くらいかかる.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;品目&lt;/th&gt;
 &lt;th style="text-align: right"&gt;だいたいの値段&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;ワクチン代&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: right"&gt;5,000円&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;システムトイレ&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: right"&gt;3,500円&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;猫砂&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: right"&gt;900円&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;トイレシート&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: right"&gt;1,300円&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;爪とぎベッド&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: right"&gt;1,800円&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;キャリーバッグ&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: right"&gt;8,000円&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;ごはん皿, 水飲み皿&lt;/td&gt;
 &lt;td style="text-align: right"&gt;2,000円&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;電子はかり&lt;/td&gt;
 &lt;td style="text-align: right"&gt;1,000円&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;キャットタワー&lt;/td&gt;
 &lt;td style="text-align: right"&gt;10,000円&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;自動給餌器&lt;/td&gt;
 &lt;td style="text-align: right"&gt;18,000円&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;浄水器&lt;/td&gt;
 &lt;td style="text-align: right"&gt;5,000円&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;合計&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: right"&gt;&lt;strong&gt;56,500円&lt;/strong&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;br&gt;&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;ワクチン代&lt;br&gt;
&lt;strong&gt;必須&lt;/strong&gt;.&lt;br&gt;
そとちゃんは保護猫団体の方でワクチン接種してもらっていたので,&lt;br&gt;
その分はこちらで負担した.&lt;br&gt;
たぶんどこの団体でも同じくらい請求されると思う.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;システムトイレ, 猫砂, トイレシート&lt;br&gt;
&lt;img alt="トイレ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-toilet.jpg" srcset="https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-toilet_hu_3872b565c42e2713.jpg 800w, https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-toilet_hu_ca4688abd6acfbf3.jpg 1600w, https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-toilet_hu_dfae7959c1363b5.jpg 2400w, https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-toilet.jpg 4032w" width="4032"&gt;&lt;br&gt;
&lt;a class="link" href="https://www.amazon.co.jp/gp/product/B07K8S83RT/ref=as_li_tl?ie=UTF8&amp;amp;camp=247&amp;amp;creative=1211&amp;amp;creativeASIN=B07K8S83RT&amp;amp;linkCode=as2&amp;amp;tag=uzimihsr-22&amp;amp;linkId=4eac485c7fb4e1148f3002fb6936b606" target="_blank" rel="noopener"
 &gt;アイリスオーヤマ 上から猫トイレ システムタイプ&lt;/a&gt;&lt;br&gt;
&lt;a class="link" href="https://www.amazon.co.jp/gp/product/B078BPC13P/ref=as_li_tl?ie=UTF8&amp;amp;camp=247&amp;amp;creative=1211&amp;amp;creativeASIN=B078BPC13P&amp;amp;linkCode=as2&amp;amp;tag=uzimihsr-22&amp;amp;linkId=985598e5398236244f57c022ff1dd617" target="_blank" rel="noopener"
 &gt;アイリスオーヤマ システムトイレ用 におわない消臭サンド&lt;/a&gt;&lt;br&gt;
&lt;a class="link" href="https://www.amazon.co.jp/gp/product/B07821992P/ref=as_li_tl?ie=UTF8&amp;amp;camp=247&amp;amp;creative=1211&amp;amp;creativeASIN=B07821992P&amp;amp;linkCode=as2&amp;amp;tag=uzimihsr-22&amp;amp;linkId=6202ed5b774c97f0df812901812a9ad8" target="_blank" rel="noopener"
 &gt;アイリスオーヤマ システムトイレ用 1週間におわない脱臭シート&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;必須&lt;/strong&gt;.&lt;br&gt;
猫のおしっこはかなり臭い.&lt;br&gt;
このタイプのトイレならにおいが気になりにくいし, 砂も部屋に飛び散らないのでとても良い.&lt;br&gt;
あと写真は撮れなかったけど入る前におててをトイレのフチに揃えて中を覗く仕草がとてもかわいい.&lt;br&gt;
&lt;del&gt;そとちゃんは砂かけが下手なのでうんちのにおいは漏れてくる&lt;/del&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;爪とぎベッド&lt;br&gt;
&lt;img alt="爪とぎ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-bowl.jpg" srcset="https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-bowl_hu_96a9d7c71eaf396f.jpg 800w, https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-bowl_hu_99fa3e2e61bc33e0.jpg 1600w, https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-bowl_hu_1e3c5ccf3640c491.jpg 2400w, https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-bowl.jpg 4032w" width="4032"&gt;&lt;br&gt;
&lt;a class="link" href="https://www.amazon.co.jp/gp/product/B071KDKGMY/ref=as_li_tl?ie=UTF8&amp;amp;camp=247&amp;amp;creative=1211&amp;amp;creativeASIN=B071KDKGMY&amp;amp;linkCode=as2&amp;amp;tag=uzimihsr-22&amp;amp;linkId=26f2db1d9be5f458cb37d8c4ec919848" target="_blank" rel="noopener"
 &gt;猫壱 バリバリボウル&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;必須&lt;/strong&gt;.&lt;br&gt;
猫は想像以上に爪とぎをする.&lt;br&gt;
爪とぎがないと平気で壁紙をガリガリする.&lt;br&gt;
これなら爪とぎとお昼寝どっちにも使えるし,&lt;br&gt;
へたってきたら中身の爪とぎだけ交換できるのでとても便利.&lt;br&gt;
&lt;del&gt;そとちゃんはこれがあってもたまに壁で爪とぎする&lt;/del&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;キャリーバッグ&lt;br&gt;
&lt;img alt="キャリーバッグ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-carry.jpg" srcset="https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-carry_hu_37ef1620b1a1d66c.jpg 800w, https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-carry_hu_d67c97709dac1bcb.jpg 1600w, https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-carry_hu_4b1a22e8451ccf9.jpg 2400w, https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-carry.jpg 4032w" width="4032"&gt;&lt;br&gt;
&lt;a class="link" href="https://www.amazon.co.jp/gp/product/B07S1PKMLF/ref=as_li_tl?ie=UTF8&amp;amp;camp=247&amp;amp;creative=1211&amp;amp;creativeASIN=B07S1PKMLF&amp;amp;linkCode=as2&amp;amp;tag=uzimihsr-22&amp;amp;linkId=86c77ba7dd7d393d784be2eaa30fbd8a" target="_blank" rel="noopener"
 &gt;TOUGHCAT キャリーバッグ&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;必須&lt;/strong&gt;.&lt;br&gt;
病院につれていくときに必要になる.&lt;br&gt;
うちの場合は動物病院まで徒歩10分なのでリュックタイプの小さいバッグだけど,&lt;br&gt;
長距離移動するときはケージみたいなもっと大きいのが必要になると思う.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ごはん皿, 水飲み皿, 電子はかり&lt;br&gt;
&lt;img alt="ごはん皿" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-dish.jpg" srcset="https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-dish_hu_6b2a0a83362afb47.jpg 800w, https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-dish_hu_10323f32c66964ae.jpg 1600w, https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-dish_hu_ba8ebdba09b989a0.jpg 2400w, https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-dish.jpg 4032w" width="4032"&gt;&lt;br&gt;
&lt;a class="link" href="https://www.amazon.co.jp/gp/product/B07N66Z5VM/ref=as_li_tl?ie=UTF8&amp;amp;camp=247&amp;amp;creative=1211&amp;amp;creativeASIN=B07N66Z5VM&amp;amp;linkCode=as2&amp;amp;tag=uzimihsr-22&amp;amp;linkId=fcab26c0b49e3b856b1298a085351821" target="_blank" rel="noopener"
 &gt;猫壱 脚付フードボウル&lt;/a&gt;&lt;br&gt;
&lt;a class="link" href="https://www.amazon.co.jp/gp/product/B07P8YK2PH/ref=as_li_tl?ie=UTF8&amp;amp;camp=247&amp;amp;creative=1211&amp;amp;creativeASIN=B07P8YK2PH&amp;amp;linkCode=as2&amp;amp;tag=uzimihsr-22&amp;amp;linkId=9005899643259dcb048c5c0f6fec0eeb" target="_blank" rel="noopener"
 &gt;猫壱 脚付ウォーターボウル&lt;/a&gt;&lt;br&gt;
&lt;a class="link" href="https://www.amazon.co.jp/gp/product/B01M0KYTS3/ref=as_li_tl?ie=UTF8&amp;amp;camp=247&amp;amp;creative=1211&amp;amp;creativeASIN=B01M0KYTS3&amp;amp;linkCode=as2&amp;amp;tag=uzimihsr-22&amp;amp;linkId=1522ddb1bd59999e67d9f2a637f58ec9" target="_blank" rel="noopener"
 &gt;タニタ はかり KF-100 WH&lt;/a&gt;&lt;br&gt;
あると便利.&lt;br&gt;
ごはんと水は普通のお茶碗であげても良いんだけど,&lt;br&gt;
少し高さがついている専用の皿のほうが食べやすそう.&lt;br&gt;
はかりはドライフードの重さを計ってカロリーを計算するのに使う.&lt;br&gt;
完全室内飼いの猫は太りやすいので&amp;hellip;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;キャットタワー&lt;br&gt;
&lt;img alt="キャットタワー" class="gallery-image" data-flex-basis="132px" data-flex-grow="55" height="4032" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-tower.jpg" srcset="https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-tower_hu_a681fba2044965d9.jpg 800w, https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-tower_hu_f4b4c5756eeabcf2.jpg 1600w, https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-tower.jpg 2225w" width="2225"&gt;&lt;br&gt;
&lt;a class="link" href="https://www.amazon.co.jp/gp/product/B079DQTH89/ref=as_li_tl?ie=UTF8&amp;amp;camp=247&amp;amp;creative=1211&amp;amp;creativeASIN=B079DQTH89&amp;amp;linkCode=as2&amp;amp;tag=uzimihsr-22&amp;amp;linkId=2ccb13a271b22b3a7d717758f5d70390" target="_blank" rel="noopener"
 &gt;FEANDREA キャットタワー NPCT99W&lt;/a&gt;&lt;br&gt;
あると便利.&lt;br&gt;
ベランダの近くに設置しているので, そとちゃんはよくタワーの上から外の景色を眺めている.&lt;br&gt;
運動不足の解消にもなるので, あって困ることは無いと思う.&lt;br&gt;
問題は1人暮らしの部屋(6.5畳)だとかなり場所を取られること.&lt;br&gt;
早く広い家に引っ越したい.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;自動給餌器&lt;br&gt;
&lt;img alt="カリカリマシーン" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-feeder.jpg" srcset="https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-feeder_hu_258aa8ef019772fa.jpg 800w, https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-feeder_hu_88253848cb3f60ef.jpg 1600w, https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-feeder_hu_16508aae7f7760c1.jpg 2400w, https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-feeder.jpg 4032w" width="4032"&gt;&lt;br&gt;
&lt;a class="link" href="https://www.amazon.co.jp/gp/product/B01M3MWUCP/ref=as_li_tl?ie=UTF8&amp;amp;camp=247&amp;amp;creative=1211&amp;amp;creativeASIN=B01M3MWUCP&amp;amp;linkCode=as2&amp;amp;tag=uzimihsr-22&amp;amp;linkId=b071b65cb122a8370ae286c3339079ac" target="_blank" rel="noopener"
 &gt;うちのこエレクトリック カリカリマシーンSP&lt;/a&gt;&lt;br&gt;
あると便利.&lt;br&gt;
自分が昼間は家を空けているので,&lt;br&gt;
これを使ってカリカリ(ドライフード)を決まった時間に小分けにして出すようにしている.&lt;br&gt;
忙しい朝もごはんを用意する必要が無いので本当に助かる.&lt;br&gt;
Webカメラとマイク, スピーカーがついていてスマホのアプリからそとちゃんの様子が見られたり,&lt;br&gt;
こちらから声をかけたりできるので外出中も安心できる.&lt;br&gt;
なお, そとちゃんはごはんの時間以外カメラには映らない模様&amp;hellip;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;浄水器&lt;br&gt;
&lt;img alt="ピュアクリスタル" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-water.jpg" srcset="https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-water_hu_70bbe90dd8d2fcac.jpg 800w, https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-water_hu_50c11c41906eba17.jpg 1600w, https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-water_hu_7650f03608ee28ae.jpg 2400w, https://blog.uzimihsr.com/post/2019-09-23-sotochan-money/2019-09-23-sotochan-water.jpg 4032w" width="4032"&gt;&lt;br&gt;
&lt;a class="link" href="https://www.amazon.co.jp/gp/product/B00VWKBF2Y/ref=as_li_tl?ie=UTF8&amp;amp;camp=247&amp;amp;creative=1211&amp;amp;creativeASIN=B00VWKBF2Y&amp;amp;linkCode=as2&amp;amp;tag=uzimihsr-22&amp;amp;linkId=45d79680c116665c2a402a21f0f3c20c" target="_blank" rel="noopener"
 &gt;ジェックス ピュアクリスタル セラミックス&lt;/a&gt;&lt;br&gt;
あると便利.&lt;br&gt;
毎朝飲み水を換える作業が面倒だったので購入.&lt;br&gt;
中に軟水化フィルターが入っていていつでもきれいな水が飲めるようになっている.&lt;br&gt;
水が流れると何故か猫はよく飲むみたいで, そとちゃんも本当によく飲む.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;そとちゃんを迎えるときに買ったものをまとめてみた.&lt;br&gt;
次はそとちゃんのごはんについて書きたい.&lt;/p&gt;</description></item><item><title>Go向けにAtomの設定をした</title><link>https://blog.uzimihsr.com/post/2019-09-07-golang-atom/</link><pubDate>Sat, 07 Sep 2019 11:47:25 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2019-09-07-golang-atom/</guid><description>&lt;h2 id="atomってideじゃなくね"&gt;AtomってIDEじゃなくね?
&lt;/h2&gt;&lt;p&gt;最近Goに触りだしたので, 普段使ってるエディタ(&lt;a class="link" href="https://atom.io/" target="_blank" rel="noopener"
 &gt;Atom&lt;/a&gt;)をGo向けにセットアップしてみた.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;p&gt;AtomをGoのIDE&lt;strong&gt;っぽく&lt;/strong&gt;する.&lt;br&gt;
IDEにするって言い切ると詳しい人に怒られそう.&lt;/p&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;MacBook Pro (Retina, 15-inch, Mid 2015)
&lt;ul&gt;
&lt;li&gt;macOS Mojave 10.14&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Atom
&lt;ul&gt;
&lt;li&gt;1.40.1&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/uzimihsr/setup/blob/master/atom.md" target="_blank" rel="noopener"
 &gt;インストール手順&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Go
&lt;ul&gt;
&lt;li&gt;go version go1.13 darwin/amd64&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/uzimihsr/setup/blob/master/go.md" target="_blank" rel="noopener"
 &gt;インストール手順&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="手順"&gt;手順
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;atom-ide-uiのインストール&lt;/li&gt;
&lt;li&gt;scriptのインストール&lt;/li&gt;
&lt;li&gt;go-plusのインストール&lt;/li&gt;
&lt;li&gt;go-debugのインストール&lt;/li&gt;
&lt;li&gt;go-signature-statusbarのインストール&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="atom-ide-uiのインストール"&gt;atom-ide-uiのインストール
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://atom.io/packages/atom-ide-ui" target="_blank" rel="noopener"
 &gt;atom-ide-ui&lt;/a&gt;&lt;br&gt;
AtomをIDEっぽくしてくれるパッケージ.&lt;br&gt;
Goの場合はgo-plusとの併用が必要になってくる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ apm install atom-ide-ui
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="scriptのインストール"&gt;scriptのインストール
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://atom.io/packages/script" target="_blank" rel="noopener"
 &gt;script&lt;/a&gt;&lt;br&gt;
Atom上でコードを実行してくれるパッケージ.&lt;br&gt;
&lt;code&gt;⌘+i&lt;/code&gt;で現在開いているコードを実行できる.&lt;br&gt;
.goファイルの場合は&lt;code&gt;go run&lt;/code&gt;するのと同じことをしてくれる.&lt;br&gt;
他の言語で実行オプションを細かく設定したい場合などは&lt;code&gt;$HOME/.atom/packages/script/lib/grammars&lt;/code&gt;にある設定ファイルを編集すれば良い.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ apm install script
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="go-plusのインストール"&gt;go-plusのインストール
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://atom.io/packages/go-plus" target="_blank" rel="noopener"
 &gt;go-plus&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;本命&lt;/strong&gt;. AtomでGoを書くときのサポート(整形, 補完, docの簡易表示, 関数定義ファイルへのジャンプ)をだいたいやってくれる.&lt;br&gt;
Goのパッケージをいくつか必要とするので, それらもインストールする.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go get -u golang.org/x/tools/cmd/goimports
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go get -u golang.org/x/tools/cmd/gorename
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go get -u github.com/sqs/goreturns
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go get -u github.com/mdempsky/gocode
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go get -u github.com/alecthomas/gometalinter
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go get -u github.com/mgechev/revive
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go get -u github.com/golangci/golangci-lint/cmd/golangci-lint
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go get -u github.com/zmb3/gogetdoc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go get -u github.com/zmb3/goaddimport
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go get -u github.com/rogpeppe/godef
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go get -u golang.org/x/tools/cmd/guru
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go get -u github.com/fatih/gomodifytags
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go get -u github.com/tpng/gopkgs
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go get -u github.com/ramya-rao-a/go-outline
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ apm install go-plus
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="go-debugのインストール"&gt;go-debugのインストール
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://atom.io/packages/go-debug" target="_blank" rel="noopener"
 &gt;go-debug&lt;/a&gt;&lt;br&gt;
go-plusで使用する. Goのデバッガ.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ go get -u github.com/go-delve/delve/cmd/dlv
$ apm install go-debug
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="go-signature-statusbarのインストール"&gt;go-signature-statusbarのインストール
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://atom.io/packages/go-signature-statusbar" target="_blank" rel="noopener"
 &gt;go-signature-statusbar&lt;/a&gt;
go-plusで使用する. 画面下のステータスバーにいい感じの情報を載せてくれる.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ apm install go-signature-statusbar
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="つかいかたの確認"&gt;つかいかたの確認
&lt;/h2&gt;&lt;p&gt;現状使いこなせてるのはこの程度.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;キーバインド&lt;/th&gt;
 &lt;th&gt;機能&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;⌘+s&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;保存時に自動で&lt;code&gt;goimports&lt;/code&gt;でコード整形が行われる.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;⌘+i&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;現在表示しているコードを実行する.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;⌘+click&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;godef&lt;/code&gt;で関数定義へジャンプする.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="384px" data-flex-grow="160" height="1800" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-09-07-golang-atom/2019-09-07-screenshot.png" srcset="https://blog.uzimihsr.com/post/2019-09-07-golang-atom/2019-09-07-screenshot_hu_86250ad87cdbe8d3.png 800w, https://blog.uzimihsr.com/post/2019-09-07-golang-atom/2019-09-07-screenshot_hu_2d5eb8a28f33225c.png 1600w, https://blog.uzimihsr.com/post/2019-09-07-golang-atom/2019-09-07-screenshot_hu_e5cb313ab0c5b509.png 2400w, https://blog.uzimihsr.com/post/2019-09-07-golang-atom/2019-09-07-screenshot.png 2880w" width="2880"&gt;&lt;/p&gt;
&lt;p&gt;動的にlintしてくれないのが残念だけど, そもそもGoのコード整形自体が強力なのであまり気にならなさそう.&lt;/p&gt;</description></item><item><title>Goでコマンドラインサイコロを作った</title><link>https://blog.uzimihsr.com/post/2019-09-04-golang-dice/</link><pubDate>Wed, 04 Sep 2019 22:15:18 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2019-09-04-golang-dice/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2019-09-04-golang-dice/2019-09-04-sotochan-omake.jpg" alt="Featured image of post Goでコマンドラインサイコロを作った" /&gt;&lt;h2 id="なんか作りたい"&gt;なんか作りたい
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://tour.golang.org/list" target="_blank" rel="noopener"
 &gt;A Tour of Go&lt;/a&gt;を一通りなぞったので, なんか作りたくなった.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="やったこと"&gt;やったこと
&lt;/h2&gt;&lt;p&gt;Goの練習として, コマンドラインで動くかんたんなサイコロを作ってみた.&lt;/p&gt;
&lt;p&gt;動作のイメージ :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ dice &lt;span class="c1"&gt;# 1~6の範囲でランダムに生成された整数を1つ出力&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ dice -f &lt;span class="m"&gt;10&lt;/span&gt; &lt;span class="c1"&gt;# -fオプションでサイコロの最大値を変更&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ dice -d &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="c1"&gt;# -dオプションで振るサイコロの数を変更&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ dice -f &lt;span class="m"&gt;10&lt;/span&gt; -d &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="c1"&gt;# -fオプションと-dオプションの併用も可能&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;6&lt;/span&gt; &lt;span class="m"&gt;9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;MacBook Pro (Retina, 15-inch, Mid 2015)
&lt;ul&gt;
&lt;li&gt;macOS Mojave 10.14&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Go
&lt;ul&gt;
&lt;li&gt;go version go1.12.9 darwin/amd64&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/uzimihsr/setup/blob/master/go.md" target="_blank" rel="noopener"
 &gt;インストール手順&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="手順"&gt;手順
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;dice.goの作成&lt;/li&gt;
&lt;li&gt;dice.goをインストール&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="dicegoの作成"&gt;dice.goの作成
&lt;/h3&gt;&lt;p&gt;とりあえず標準パッケージを使って作ってみた.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mkdir -p &lt;span class="nv"&gt;$GOPATH&lt;/span&gt;/src/github.com/uzimihsr/dice
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="nv"&gt;$GOPATH&lt;/span&gt;/src/github.com/uzimihsr/dice
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim dice.go
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;dice.go&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;flag&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;math/rand&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="c1"&gt;// コマンドラインオプションで与える値の変数定義&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;		&lt;/span&gt;&lt;span class="nx"&gt;faces&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;uint&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;		&lt;/span&gt;&lt;span class="nx"&gt;dices&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;uint&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="c1"&gt;// コマンドラインオプションの設定&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UintVar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;faces&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;f&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;The number of dice faces&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UintVar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;dices&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;d&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;The number of dices to throw&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="c1"&gt;// サイコロを振り, 出目を出力&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Seed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;UnixNano&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dices&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;		&lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;%d &amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Intn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;faces&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Goでコマンドラインツールを作る場合には&lt;a class="link" href="https://github.com/urfave/cli" target="_blank" rel="noopener"
 &gt;urfave/cli&lt;/a&gt;とか&lt;a class="link" href="https://github.com/spf13/cobra" target="_blank" rel="noopener"
 &gt;cobra&lt;/a&gt;が良いらしいんだけど,&lt;br&gt;
今回はそこまで高機能なものはつくらないので標準パッケージ&lt;a class="link" href="https://godoc.org/flag" target="_blank" rel="noopener"
 &gt;flag&lt;/a&gt;を使ってオプションの処理をした.&lt;/p&gt;
&lt;p&gt;サイコロの処理(乱数の生成)にはこちらも標準の&lt;a class="link" href="https://godoc.org/math/rand" target="_blank" rel="noopener"
 &gt;math/rand&lt;/a&gt;パッケージを使った.&lt;br&gt;
そのまま使うと乱数のSeedが1で固定され, 毎回同じ値が生成されてしまうので&lt;a class="link" href="https://godoc.org/time" target="_blank" rel="noopener"
 &gt;time&lt;/a&gt;パッケージで呼び出したUnix時間を乱数Seedとして使うようにした.&lt;/p&gt;
&lt;h3 id="dicegoをインストール"&gt;dice.goをインストール
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;go install&lt;/code&gt;を使ってdice.goの実行ファイルを&lt;code&gt;$GOPATH/bin&lt;/code&gt;にインストールする.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="nv"&gt;$GOPATH&lt;/span&gt;/src/github.com/uzimihsr/dice
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go install
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ which dice
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$GOPATH&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;/bin/dice
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ dice -f &lt;span class="m"&gt;12&lt;/span&gt; -d &lt;span class="m"&gt;6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;6&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="m"&gt;9&lt;/span&gt; &lt;span class="m"&gt;11&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;いい感じ.&lt;/p&gt;
&lt;p&gt;つくったやつは&lt;a class="link" href="https://hatenablog-parts.com/embed?url=https://github.com/uzimihsr/dice" target="_blank" rel="noopener"
 &gt;ここ&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="スマホをけとばすねこ with エリザベスカラー" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-09-04-golang-dice/2019-09-04-sotochan-omake.jpg" srcset="https://blog.uzimihsr.com/post/2019-09-04-golang-dice/2019-09-04-sotochan-omake_hu_cbd109c55b769678.jpg 800w, https://blog.uzimihsr.com/post/2019-09-04-golang-dice/2019-09-04-sotochan-omake_hu_a3e13fbdfb4c3894.jpg 1600w, https://blog.uzimihsr.com/post/2019-09-04-golang-dice/2019-09-04-sotochan-omake_hu_7aef6c4a306fdd90.jpg 2400w, https://blog.uzimihsr.com/post/2019-09-04-golang-dice/2019-09-04-sotochan-omake.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>GitHub Pages+HugoでつくったブログにGoogle Analyticsを埋め込む</title><link>https://blog.uzimihsr.com/post/2019-08-26-google-analytics/</link><pubDate>Mon, 26 Aug 2019 22:15:39 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2019-08-26-google-analytics/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-sotochan-omake.jpg" alt="Featured image of post GitHub Pages+HugoでつくったブログにGoogle Analyticsを埋め込む" /&gt;&lt;h2 id="需要があるかはわからない"&gt;需要があるかはわからない
&lt;/h2&gt;&lt;p&gt;ねこ記事でアクセス数稼ぎをするのはいいが, そのアクセス数を数える方法がなかったのでやってみた.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="なにをしたか"&gt;なにをしたか
&lt;/h2&gt;&lt;p&gt;Google AnalyticsをGitHub Pages上に公開している自分のブログ(&lt;a class="link" href="https://uzimihsr.github.io/post/2019-08-07-create-blog-1/" target="_blank" rel="noopener"
 &gt;Hugoで生成&lt;/a&gt;)に埋め込み, トラフィックを見られるようにした&lt;/p&gt;
&lt;h2 id="必要なもの"&gt;必要なもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Googleアカウント&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="どうやったか"&gt;どうやったか
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Google Analyticsの利用登録&lt;/li&gt;
&lt;li&gt;トラッキングコードをHugoに埋め込む&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="google-analyticsの利用登録"&gt;Google Analyticsの利用登録
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://analytics.google.com/analytics/web/" target="_blank" rel="noopener"
 &gt;Google Analytics&lt;/a&gt;にアクセスし, &lt;code&gt;Googleアナリティクスの利用を開始 -&amp;gt; 登録&lt;/code&gt;と進む.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Google Analytics" class="gallery-image" data-flex-basis="915px" data-flex-grow="381" height="748" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-google-analytics-1.png" srcset="https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-google-analytics-1_hu_e935c9dd65ee439a.png 800w, https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-google-analytics-1_hu_d3f7ae78302deff.png 1600w, https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-google-analytics-1_hu_b5ee04873cdbf5a8.png 2400w, https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-google-analytics-1.png 2853w" width="2853"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;アカウントの設定&lt;/code&gt;では自分のGoogleアカウント名を入力し, アカウントのデータ共有設定で必要なものにチェックをつける. スクショ失敗したので画像が無いが, 自分は全部チェックをつけた.&lt;/p&gt;
&lt;p&gt;&lt;img alt="アカウントの設定" class="gallery-image" data-flex-basis="724px" data-flex-grow="301" height="821" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-google-analytics-2.png" srcset="https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-google-analytics-2_hu_fe0bc402643a6b76.png 800w, https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-google-analytics-2_hu_5954ff7654ef9926.png 1600w, https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-google-analytics-2_hu_76017984a8399463.png 2400w, https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-google-analytics-2.png 2478w" width="2478"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;測定の対象を指定します。&lt;/code&gt;ではウェブを指定する.&lt;/p&gt;
&lt;p&gt;&lt;img alt="測定の対象を指定します。" class="gallery-image" data-flex-basis="401px" data-flex-grow="167" height="1482" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-google-analytics-3.png" srcset="https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-google-analytics-3_hu_4de92a7dcfa4b1b3.png 800w, https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-google-analytics-3_hu_bb69a858b048b50c.png 1600w, https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-google-analytics-3_hu_3eb4860561998269.png 2400w, https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-google-analytics-3.png 2478w" width="2478"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;プロパティの設定&lt;/code&gt;でウェブサイトの名前, URLを入力する.&lt;/p&gt;
&lt;p&gt;&lt;img alt="プロパティの設定" class="gallery-image" data-flex-basis="402px" data-flex-grow="167" height="1479" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-google-analytics-4.png" srcset="https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-google-analytics-4_hu_db1c6821c350d449.png 800w, https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-google-analytics-4_hu_2c6c01f9e27e64e5.png 1600w, https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-google-analytics-4_hu_cd4dcdd8698b5bcc.png 2400w, https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-google-analytics-4.png 2478w" width="2478"&gt;&lt;/p&gt;
&lt;p&gt;最後に利用規約に同意したらGoogle Analyticsのダッシュボードが開く.&lt;br&gt;
ここで表示されるトラッキングコード(UA-123456789-1)を控えておく.&lt;/p&gt;
&lt;p&gt;&lt;img alt="ダッシュボード" class="gallery-image" data-flex-basis="1541px" data-flex-grow="642" height="351" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-google-analytics-5.png" srcset="https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-google-analytics-5_hu_ac379074cd5c730c.png 800w, https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-google-analytics-5_hu_5ff2a7f7453b4356.png 1600w, https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-google-analytics-5.png 2255w" width="2255"&gt;&lt;/p&gt;
&lt;h3 id="トラッキングコードをhugoに埋め込む"&gt;トラッキングコードをHugoに埋め込む
&lt;/h3&gt;&lt;p&gt;Google Analyticsの準備ができたら, &lt;code&gt;config.toml&lt;/code&gt;に控えたトラッキングコードを記述する. ここに記述しておくと, Hugoで静的ページをビルドした際にトラッキング用のタグをすべてのhtmlに書き込んでくれるので便利.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;config.toml&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-toml" data-lang="toml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;baseurl&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://uzimihsr.github.io&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;DefaultContentLanguage&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;en&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;meow.md&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;beautifulhugo&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;metaDataFormat&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;yaml&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;pygmentsStyle&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;trac&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;pygmentsUseClasses&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;pygmentsCodeFences&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;pygmentsCodefencesGuessSyntax&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;author&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;googleAnalytics&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;UA-123456789-1&amp;#34;&lt;/span&gt; &lt;span class="c"&gt;# この行を追記&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="err"&gt;(以下省略)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;静的ページをビルドする. 自分の場合は&lt;a class="link" href="https://uzimihsr.github.io/post/2019-08-07-create-blog-1/#github-pages%E3%81%A7%E3%83%9A%E3%83%BC%E3%82%B8%E3%82%92%E5%85%AC%E9%96%8B%E3%81%99%E3%82%8B" target="_blank" rel="noopener"
 &gt;ビルド用スクリプト&lt;code&gt;deploy.sh&lt;/code&gt;&lt;/a&gt;を作成しているのでこれをそのまま使う.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ./deploy.sh &lt;span class="s2"&gt;&amp;#34;Google Analytics&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;もう一度ダッシュボードを更新すると, 設定したブログへのトラフィックが確認できる.&lt;/p&gt;
&lt;p&gt;&lt;img alt="ダッシュボード" class="gallery-image" data-flex-basis="436px" data-flex-grow="181" height="1597" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-google-analytics-6.png" srcset="https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-google-analytics-6_hu_c7ce2d7ffbb129ee.png 800w, https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-google-analytics-6_hu_8904bb3021840aa1.png 1600w, https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-google-analytics-6_hu_7f92384cf4f3fc9d.png 2400w, https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-google-analytics-6.png 2905w" width="2905"&gt;&lt;/p&gt;
&lt;p&gt;まだぜんぜんトラフィックがない. 悲しい&amp;hellip;&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="パソコンの横で眠くなるねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-sotochan-omake.jpg" srcset="https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-sotochan-omake_hu_36d70aeb91a02eda.jpg 800w, https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-sotochan-omake_hu_c4babd94d5c0a73d.jpg 1600w, https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-sotochan-omake_hu_269451f070e342bb.jpg 2400w, https://blog.uzimihsr.com/post/2019-08-26-google-analytics/2019-08-26-sotochan-omake.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>コード中でGoのバージョンを確認する</title><link>https://blog.uzimihsr.com/post/2019-08-25-golang-check-version/</link><pubDate>Sun, 25 Aug 2019 22:13:29 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2019-08-25-golang-check-version/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2019-08-25-golang-check-version/2019-08-25-sotochan-omake.jpg" alt="Featured image of post コード中でGoのバージョンを確認する" /&gt;&lt;h2 id="go-version-は使えるけども"&gt;go version は使えるけども
&lt;/h2&gt;&lt;p&gt;pythonの&lt;code&gt;sys.version&lt;/code&gt;みたいに&lt;code&gt;Go(golang)&lt;/code&gt;でもコード中でバージョンを確認する方法があったのでメモ.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="なにができるようになるか"&gt;なにができるようになるか
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Go&lt;/code&gt;のソースコード内でバージョン情報をstringで扱えるようになる.&lt;/p&gt;
&lt;h2 id="やりかた"&gt;やりかた
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://godoc.org/runtime#Version" target="_blank" rel="noopener"
 &gt;runtime.Version()&lt;/a&gt;を使えば良い. かんたん.&lt;/p&gt;
&lt;p&gt;試しに&lt;code&gt;goenv&lt;/code&gt;でGoのバージョンを変えながらコマンドライン上でバージョンを確認する&lt;code&gt;go version&lt;/code&gt;とコード中でバージョンを確認する&lt;code&gt;check-version.go&lt;/code&gt;を交互に動かしてみる.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;check-version.go&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;runtime&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Go version :&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Version&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ goenv versions
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1.11.13
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 1.12.9 &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; by /Users/username/.goenv/version&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ goenv global 1.12.9 &lt;span class="c1"&gt;# すでに設定されてるので意味無し&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;go version go1.12.9 darwin/amd64
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go run check-version.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Go version : go1.12.9
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ goenv global 1.11.13
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;go version go1.11.13 darwin/amd64
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go run check-version.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Go version : go1.11.13
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;できた. サンプルコードで実行環境吐き出させるときとかにつかいたい.&lt;/p&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="パソコンばっかいじってる飼い主に愛想をつかしておしりを向けて寝るねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-08-25-golang-check-version/2019-08-25-sotochan-omake.jpg" srcset="https://blog.uzimihsr.com/post/2019-08-25-golang-check-version/2019-08-25-sotochan-omake_hu_6753fc5955bda58.jpg 800w, https://blog.uzimihsr.com/post/2019-08-25-golang-check-version/2019-08-25-sotochan-omake_hu_a657160fdc7daeac.jpg 1600w, https://blog.uzimihsr.com/post/2019-08-25-golang-check-version/2019-08-25-sotochan-omake_hu_205826f226e58c7c.jpg 2400w, https://blog.uzimihsr.com/post/2019-08-25-golang-check-version/2019-08-25-sotochan-omake.jpg 4032w" width="4032"&gt;&lt;/p&gt;</description></item><item><title>うちに来るまでのそとちゃん</title><link>https://blog.uzimihsr.com/post/2019-08-24-sotochan-story/</link><pubDate>Sat, 24 Aug 2019 00:19:26 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2019-08-24-sotochan-story/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2019-08-24-sotochan-story/2019-08-24-sotochan-on-my-bed.jpg" alt="Featured image of post うちに来るまでのそとちゃん" /&gt;&lt;h2 id="そとちゃんは保護猫"&gt;そとちゃんは保護猫
&lt;/h2&gt;&lt;p&gt;そとちゃんは元野良猫(保護猫). 保護猫活動をしている方から譲ってもらってうちにきた.&lt;br&gt;
その方に聞いた話などから, わかっている範囲でこれまでのそとちゃんについて書いていく.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="もくじ"&gt;もくじ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;そとちゃん, 生まれる&lt;/li&gt;
&lt;li&gt;そとちゃん, 保護される&lt;/li&gt;
&lt;li&gt;そとちゃんと俺, 出会う&lt;/li&gt;
&lt;li&gt;そとちゃん, うちに来る&lt;/li&gt;
&lt;li&gt;今のそとちゃん&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="そとちゃん-生まれる"&gt;そとちゃん, 生まれる
&lt;/h3&gt;&lt;p&gt;そとちゃんはおそらく2016~2017年ごろに北関東のあたりで生まれた. 柄はキジトラ白なので, おそらく雑種.&lt;/p&gt;
&lt;p&gt;かなり人馴れしているのでもともとは人に飼われてたか, 地域で餌付けされていたのかもしれない.&lt;/p&gt;
&lt;p&gt;病院の先生の推測だと仔猫のときに猫風邪にかかっていて, 後遺症で右目の涙腺の機能が悪くなっている. そのため右目に目ヤニがたまりやすい.&lt;/p&gt;
&lt;p&gt;たぶんたいへんなにゃん生だった.&lt;/p&gt;
&lt;h3 id="そとちゃん-保護される"&gt;そとちゃん, 保護される
&lt;/h3&gt;&lt;p&gt;2018年の6月頃, そとちゃんは保護猫活動をしている人に保護された.&lt;/p&gt;
&lt;p&gt;群馬のどこかの民家の軒下で, 産気づいた状態で見つかった. そのときの体重は3.3kg.&lt;/p&gt;
&lt;p&gt;ちなみにそとちゃんという名前はその時つけられたもので, 家のそとにいたからそとちゃんなんだとか.&lt;br&gt;
&lt;del&gt;その名付け方だと野良猫みんなそとちゃんじゃね?&lt;/del&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="保護されたころのそとちゃん, 目つきわるい" class="gallery-image" data-flex-basis="179px" data-flex-grow="74" height="1478" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-08-24-sotochan-story/2019-08-24-sotochan-found.jpg" srcset="https://blog.uzimihsr.com/post/2019-08-24-sotochan-story/2019-08-24-sotochan-found_hu_6ca7595119483a8e.jpg 800w, https://blog.uzimihsr.com/post/2019-08-24-sotochan-story/2019-08-24-sotochan-found.jpg 1108w" width="1108"&gt;&lt;/p&gt;
&lt;p&gt;出産は大変な難産で, 仔猫は5匹くらいいたけども生きてお腹から出られたのはオスが2匹だけだった.&lt;/p&gt;
&lt;p&gt;&lt;img alt="生まれたばかりののそとちゃんのこども" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="650" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-08-24-sotochan-story/2019-08-24-sotochans-child.jpg" srcset="https://blog.uzimihsr.com/post/2019-08-24-sotochan-story/2019-08-24-sotochans-child_hu_28483dec56a4326b.jpg 800w, https://blog.uzimihsr.com/post/2019-08-24-sotochan-story/2019-08-24-sotochans-child.jpg 868w" width="868"&gt;&lt;/p&gt;
&lt;p&gt;産後はなんとかおっぱいもあげられて, 仔猫はなんとか育った.&lt;/p&gt;
&lt;p&gt;&lt;img alt="おっぱいをあげるそとちゃん1" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="720" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-08-24-sotochan-story/2019-08-24-sotochan-feeding-1.jpg" srcset="https://blog.uzimihsr.com/post/2019-08-24-sotochan-story/2019-08-24-sotochan-feeding-1_hu_c5ba8089b84975e4.jpg 800w, https://blog.uzimihsr.com/post/2019-08-24-sotochan-story/2019-08-24-sotochan-feeding-1.jpg 960w" width="960"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="おっぱいをあげるそとちゃん2" class="gallery-image" data-flex-basis="319px" data-flex-grow="133" height="662" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-08-24-sotochan-story/2019-08-24-sotochan-feeding-2.jpg" srcset="https://blog.uzimihsr.com/post/2019-08-24-sotochan-story/2019-08-24-sotochan-feeding-2_hu_4e8cfedae3d246e4.jpg 800w, https://blog.uzimihsr.com/post/2019-08-24-sotochan-story/2019-08-24-sotochan-feeding-2.jpg 882w" width="882"&gt;&lt;/p&gt;
&lt;p&gt;その後2匹の仔猫は揃って貰い手がみつかったが, 1匹はもらわれた先で今年の3月に病気で亡くなった.&lt;/p&gt;
&lt;p&gt;&lt;img alt="そとちゃんとそとちゃんのこども" class="gallery-image" data-flex-basis="179px" data-flex-grow="74" height="1478" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-08-24-sotochan-story/2019-08-24-sotochan-and-sotochans-child.jpg" srcset="https://blog.uzimihsr.com/post/2019-08-24-sotochan-story/2019-08-24-sotochan-and-sotochans-child_hu_d044cde6fa5f99b6.jpg 800w, https://blog.uzimihsr.com/post/2019-08-24-sotochan-story/2019-08-24-sotochan-and-sotochans-child.jpg 1108w" width="1108"&gt;&lt;/p&gt;
&lt;p&gt;たいへんなにゃん生だった.&lt;/p&gt;
&lt;h3 id="そとちゃんと俺-出会う"&gt;そとちゃんと俺, 出会う
&lt;/h3&gt;&lt;p&gt;その頃大学院に居た俺は猫動画中毒で, 就職したら自分でも猫を飼おうと考えていた.&lt;/p&gt;
&lt;p&gt;本当はブリーダーから譲渡してもらったり, 保護猫をもらいたいけど男の1人暮らしだと審査が通らないケースが多いと聞いて, あんまり良いイメージは無いけどペットショップかな&amp;hellip;と考えていたところに, 研究室の先輩(正確にはちょっと違う)の知り合いに猫を保護している人がいるのでどうか, という話をもらい今年の3月に一度面会することになった.&lt;/p&gt;
&lt;p&gt;その猫こそがそとちゃんである.&lt;/p&gt;
&lt;p&gt;&lt;img alt="そとちゃんと俺のファーストコンタクト" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-08-24-sotochan-story/2019-08-24-sotochan-first-contact.jpg" srcset="https://blog.uzimihsr.com/post/2019-08-24-sotochan-story/2019-08-24-sotochan-first-contact_hu_9bfbdc147c038f6c.jpg 800w, https://blog.uzimihsr.com/post/2019-08-24-sotochan-story/2019-08-24-sotochan-first-contact_hu_59a48488d78acc97.jpg 1600w, https://blog.uzimihsr.com/post/2019-08-24-sotochan-story/2019-08-24-sotochan-first-contact_hu_44555f2584af6755.jpg 2400w, https://blog.uzimihsr.com/post/2019-08-24-sotochan-story/2019-08-24-sotochan-first-contact.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;仔猫を送り出した後に不妊手術を受けて里親待ちになったそとちゃんだったが, 2~3歳の成猫だったのでなかなか貰い手がみつからなかった.&lt;/p&gt;
&lt;p&gt;俺は1人暮らしでなかなかかまってあげられないことを考えるとおとなしい成猫がほしかったし, 何より自分に似て右目がちょっと小さいところに謎の親近感が湧いてしまったのでこの子を引き取ることにした.&lt;/p&gt;
&lt;p&gt;この決断はほんとうに良かった.&lt;/p&gt;
&lt;h3 id="そとちゃん-うちに来る"&gt;そとちゃん, うちに来る
&lt;/h3&gt;&lt;p&gt;引き取るといっても引っ越しやら入社やらですぐに引き取ることが難しかったので, そとちゃんは5月からうちで預かることになった.&lt;/p&gt;
&lt;p&gt;社会人1ヶ月目を生き延びながら帰りに寄り道したホームセンターや通販でそとちゃん用の爪とぎ, トイレ, お皿, おもちゃなんかを少しづつ買い揃えていくのはとてもワクワクした.&lt;/p&gt;
&lt;p&gt;そして2019年5月1日, 元号が平成から令和に変わる日にそとちゃんはうちにやってきた.&lt;/p&gt;
&lt;p&gt;最初の数分は前の家が寂しかったのかにゃんにゃん鳴いていたのに, 少し目を離したすきに俺の枕を占領してぐーすか寝ていた.&lt;/p&gt;
&lt;p&gt;&lt;img alt="初日から余裕で寝るそとちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-08-24-sotochan-story/2019-08-24-sotochan-sleeping.jpg" srcset="https://blog.uzimihsr.com/post/2019-08-24-sotochan-story/2019-08-24-sotochan-sleeping_hu_2ea3d1bc50ea8201.jpg 800w, https://blog.uzimihsr.com/post/2019-08-24-sotochan-story/2019-08-24-sotochan-sleeping_hu_9c9360fd3930bdc3.jpg 1600w, https://blog.uzimihsr.com/post/2019-08-24-sotochan-story/2019-08-24-sotochan-sleeping_hu_83a617bbc7d64b27.jpg 2400w, https://blog.uzimihsr.com/post/2019-08-24-sotochan-story/2019-08-24-sotochan-sleeping.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;もともと人間が好きなのもあって初日の夜から普通に足にすりすりしてくれたし, 用意したおもちゃで元気に遊んでくれたので本当にうれしかった.&lt;/p&gt;
&lt;p&gt;そんなこんなで, そとちゃんとの暮らしがはじまった.&lt;/p&gt;
&lt;h3 id="今のそとちゃん"&gt;今のそとちゃん
&lt;/h3&gt;&lt;p&gt;そとちゃんの現在の体重は4.1kg. 保護されたときに比べるとだいぶふっくらしている.&lt;/p&gt;
&lt;p&gt;貰う前はおとなしいと思っていたが, それは大きな勘違いだった. 超おてんば. 超アグレッシブ.&lt;/p&gt;
&lt;p&gt;おもちゃは遊び方が激しすぎてすぐ壊れるし, ちょっと噛み癖があるのでしょっちゅう噛んでくる.&lt;/p&gt;
&lt;p&gt;元野良なのに妙に舌が肥えていて, 気に入ったごはんしか食べてくれない.&lt;/p&gt;
&lt;p&gt;でもとてもかわいい. 仕事から帰るとにゃんにゃん言いながら出迎えてくれるので疲れが吹き飛ぶ.&lt;/p&gt;
&lt;p&gt;そとちゃんを引き取って本当に良かったと思う.&lt;/p&gt;
&lt;p&gt;そとちゃんにもこれからのにゃん生を幸せに生きてほしい.&lt;/p&gt;
&lt;p&gt;&lt;img alt="今朝のそとちゃん" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-08-24-sotochan-story/2019-08-24-sotochan-on-my-bed.jpg" srcset="https://blog.uzimihsr.com/post/2019-08-24-sotochan-story/2019-08-24-sotochan-on-my-bed_hu_21f2e88d89c3e37e.jpg 800w, https://blog.uzimihsr.com/post/2019-08-24-sotochan-story/2019-08-24-sotochan-on-my-bed_hu_4ec04606c917de.jpg 1600w, https://blog.uzimihsr.com/post/2019-08-24-sotochan-story/2019-08-24-sotochan-on-my-bed_hu_58451f92f66b457d.jpg 2400w, https://blog.uzimihsr.com/post/2019-08-24-sotochan-story/2019-08-24-sotochan-on-my-bed.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;h2 id="おわり"&gt;おわり
&lt;/h2&gt;&lt;p&gt;以上, うちにくるまでのそとちゃんについて書いてみた.&lt;/p&gt;
&lt;p&gt;次はそとちゃんの好きなものとか細かい特徴について書きたい.&lt;/p&gt;</description></item><item><title>Raspberry PiにgoenvでGoの環境構築をした</title><link>https://blog.uzimihsr.com/post/2019-08-15-install-goenv-on-rasberry-pi/</link><pubDate>Thu, 15 Aug 2019 22:09:21 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2019-08-15-install-goenv-on-rasberry-pi/</guid><description>&lt;img src="https://blog.uzimihsr.com/post/2019-08-15-install-goenv-on-rasberry-pi/sotochan.jpg" alt="Featured image of post Raspberry PiにgoenvでGoの環境構築をした" /&gt;&lt;h2 id="goに触りたい-だけどmacがない"&gt;Goに触りたい, だけどMacがない
&lt;/h2&gt;&lt;p&gt;Go(golang)を勉強したい.&lt;br&gt;
しかし先日愛用していたMacが&lt;a class="link" href="https://support.apple.com/ja-jp/15-inch-macbook-pro-battery-recall" target="_blank" rel="noopener"
 &gt;バッテリー自主回収プログラム&lt;/a&gt;に旅立ってしまったので当分帰ってこない&amp;hellip;&lt;br&gt;
仕方がないので, だいぶ前に買って家に転がっていたラズパイを使ってGoを動かせるようにしてみた.&lt;br&gt;
需要は無いと思うが一応作業ログとして残しておく.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="なにができるようになるか"&gt;なにができるようになるか
&lt;/h2&gt;&lt;p&gt;Raspberry Pi上で任意のversionのGoが動くようになる.&lt;/p&gt;
&lt;h2 id="なんでラズパイ"&gt;なんでラズパイ?
&lt;/h2&gt;&lt;p&gt;Macが帰ってくるまで待つのも退屈だから.&lt;/p&gt;
&lt;h2 id="なんでgoenv"&gt;なんでgoenv?
&lt;/h2&gt;&lt;p&gt;今日会社で教わったから.&lt;br&gt;
Goのバージョン管理ができるらしくて便利そうだから.&lt;br&gt;
ラズパイには少し重そうなので若干不安ではある.&lt;/p&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Raspberry Pi 3 Model B+
&lt;ul&gt;
&lt;li&gt;OSはRaspbian(10.0)&lt;/li&gt;
&lt;li&gt;shellはzsh&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="いれるもの"&gt;いれるもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;goenv (2.0.0beta11)
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/syndbg/goenv" target="_blank" rel="noopener"
 &gt;repo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考にしたもの"&gt;参考にしたもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/syndbg/goenv/blob/master/INSTALL.md" target="_blank" rel="noopener"
 &gt;goenv Installation&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;ほとんどこの通りにやっただけ&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やること"&gt;やること
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;goenvのインストール&lt;/li&gt;
&lt;li&gt;Goのインストール&lt;/li&gt;
&lt;li&gt;Hello World&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="goenvのインストール"&gt;goenvのインストール
&lt;/h3&gt;&lt;p&gt;まずはgoenvのrepoを持ってくる.&lt;br&gt;
HOME直下に&lt;code&gt;.goenv&lt;/code&gt;が作成され, その中にファイルが入ってくる.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ git clone https://github.com/syndbg/goenv.git ~/.goenv
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;次にgoenvを使うために必要な環境変数を設定ファイルに追加していく.&lt;br&gt;
今回はzshを使っているので&lt;code&gt;.zshenv&lt;/code&gt;に書いていく.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ echo &amp;#39;export GOENV_ROOT=&amp;#34;$HOME/.goenv&amp;#34;&amp;#39; &amp;gt;&amp;gt; ~/.zshenv
$ echo &amp;#39;export PATH=&amp;#34;$GOENV_ROOT/bin:$PATH&amp;#34;&amp;#39; &amp;gt;&amp;gt; ~/.zshenv
$ echo &amp;#39;eval &amp;#34;$(goenv init -)&amp;#34;&amp;#39; &amp;gt;&amp;gt; ~/.zshenv
$ echo &amp;#39;export PATH=&amp;#34;$GOPATH/bin:$PATH&amp;#34;&amp;#39; &amp;gt;&amp;gt; ~/.zshenv
$ exec $SHELL
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;exec $SHELL&lt;/code&gt;が問題なく動けばgoenvを使う準備は完了.&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;`.zshenv`&lt;/summary&gt;&lt;div&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;#
# Defines environment variables.
#
...
# goenv
export GOPATH=&amp;#34;$HOME/go&amp;#34;
export GOENV_ROOT=&amp;#34;$HOME/.goenv&amp;#34;
export PATH=&amp;#34;$GOENV_ROOT/bin:$PATH&amp;#34;
eval &amp;#34;$(goenv init -)&amp;#34;
export PATH=&amp;#34;$GOPATH/bin:$PATH&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/details&gt;
&lt;h3 id="goのインストール"&gt;Goのインストール
&lt;/h3&gt;&lt;p&gt;さっそくgoenvをつかって使用可能なGoのバージョン一覧を取得し, 最新の&lt;code&gt;1.12.7&lt;/code&gt;をインストールした.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ goenv install -l

&amp;gt; Available versions:
&amp;gt; 1.2.2
&amp;gt; 1.3.0
&amp;gt; 1.3.1
&amp;gt; ...
&amp;gt; 1.12.7 # これを入れる
&amp;gt; 1.13beta1

$ goenv install 1.12.7
$ goenv versions

&amp;gt; 1.12.7

$ goenv global 1.12.7 # すべての場所でGo 1.12.7を使うよう設定
$ go version

&amp;gt; go version go1.12.7 linux/arm
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="hello-world"&gt;Hello World
&lt;/h3&gt;&lt;p&gt;本当にGoが動くかどうか検証する.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ mkdir -p $GOPATH/bin/hello-world
$ cd $GOPATH/bin/hello-world
$ vim hello.go
$ go run hello.go

&amp;gt;Hello, World!
&amp;gt;from go(goenv) on Raspberry Pi
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;できた.&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;`hello.go`&lt;/summary&gt;&lt;div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Hello, World!&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;from go(goenv) on Raspberry Pi&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;h2 id="おまけ"&gt;おまけ
&lt;/h2&gt;&lt;p&gt;&lt;img alt="作業中ずっと邪魔してきたねこ" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="3024" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.uzimihsr.com/post/2019-08-15-install-goenv-on-rasberry-pi/sotochan.jpg" srcset="https://blog.uzimihsr.com/post/2019-08-15-install-goenv-on-rasberry-pi/sotochan_hu_38f9d758373e41b3.jpg 800w, https://blog.uzimihsr.com/post/2019-08-15-install-goenv-on-rasberry-pi/sotochan_hu_78d0730f5100149e.jpg 1600w, https://blog.uzimihsr.com/post/2019-08-15-install-goenv-on-rasberry-pi/sotochan_hu_ca0e9e896ba99208.jpg 2400w, https://blog.uzimihsr.com/post/2019-08-15-install-goenv-on-rasberry-pi/sotochan.jpg 4032w" width="4032"&gt;&lt;/p&gt;
&lt;p&gt;次はねこについての記事を書きたい.&lt;/p&gt;</description></item><item><title>GitHub PagesとHugoでブログをつくった</title><link>https://blog.uzimihsr.com/post/2019-08-07-create-blog-1/</link><pubDate>Wed, 07 Aug 2019 23:20:05 +0900</pubDate><guid>https://blog.uzimihsr.com/post/2019-08-07-create-blog-1/</guid><description>&lt;h2 id="ブログをつくった"&gt;ブログをつくった
&lt;/h2&gt;&lt;p&gt;ブログをつくった.&lt;br&gt;
特に大きな目的があるわけではないが学んだことのアウトプットに使ったりうちのかわいいネッコについて書いたり趣味について書いたりしたい.&lt;br&gt;
つまりなんでも書き残したい.&lt;/p&gt;
&lt;h2 id="github-pagesとhugoでブログをつくった"&gt;GitHub PagesとHugoでブログをつくった
&lt;/h2&gt;&lt;p&gt;さっそくアウトプットの練習として今回ブログを作った手順を書いていく.&lt;br&gt;
突然記憶喪失になったときのためになるべくわかりやすく書きたい.&lt;/p&gt;
&lt;h2 id="なんでgithub-pages"&gt;なんでGitHub Pages?
&lt;/h2&gt;&lt;p&gt;無料だし, エンジニアっぽくてかっこいいから(偏見).&lt;/p&gt;
&lt;h2 id="なんでhugo"&gt;なんでHugo?
&lt;/h2&gt;&lt;p&gt;参考になる記事が多めだったから.&lt;br&gt;
あと人気っぽかったから.&lt;/p&gt;
&lt;h2 id="つかうもの"&gt;つかうもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;MacBook Pro (Retina, 15-inch, Mid 2015)
&lt;ul&gt;
&lt;li&gt;macOS Mojave 10.14&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;brew(Homebrew 2.1.9)
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://brew.sh/" target="_blank" rel="noopener"
 &gt;homebrew&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;GitHubのアカウント(uzimihsr)
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/" target="_blank" rel="noopener"
 &gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Hugo v0.56.3 (後でインストールする)
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://gohugo.io/" target="_blank" rel="noopener"
 &gt;Hugo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;git version 2.17.2&lt;/li&gt;
&lt;li&gt;テキストエディタ(何でも良い, 今回はVimを使った)&lt;/li&gt;
&lt;li&gt;ちょっとだけGitの操作&lt;/li&gt;
&lt;li&gt;そこそこターミナルの操作&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考にしたもの"&gt;参考にしたもの
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://pages.github.com/" target="_blank" rel="noopener"
 &gt;GitHub Pages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://gohugo.io/getting-started/quick-start/" target="_blank" rel="noopener"
 &gt;Hugo quick start&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://gohugo.io/hosting-and-deployment/hosting-on-github/" target="_blank" rel="noopener"
 &gt;Hugo hosting on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ブログを作るまでの手順"&gt;ブログを作るまでの手順
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;GitHub repositoryを作成&lt;/li&gt;
&lt;li&gt;Hugoでページを作成する&lt;/li&gt;
&lt;li&gt;GitHub Pagesでページを公開する&lt;/li&gt;
&lt;li&gt;記事を追加する&lt;/li&gt;
&lt;li&gt;サンプルページから脱却する&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="github-repositoryを作成"&gt;GitHub repositoryを作成
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://github.com/new" target="_blank" rel="noopener"
 &gt;GitHub&lt;/a&gt;で新たに&lt;code&gt;blog&lt;/code&gt;という名前のリポジトリを作成する.&lt;br&gt;
このrepoはHugoのプロジェクトを置くのに使う.&lt;br&gt;
今回作った例 : &lt;a class="link" href="https://github.com/uzimihsr/blog.git" target="_blank" rel="noopener"
 &gt;uzimihsr/blog.git&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;同様に, &lt;code&gt;username.github.io&lt;/code&gt;リポジトリを作成する.&lt;br&gt;
&lt;code&gt;username&lt;/code&gt;はアカウント名で置き換える.&lt;br&gt;
ここに配置したファイルがGitHub Pagesとして公開される.&lt;br&gt;
例 : &lt;a class="link" href="https://github.com/uzimihsr/uzimihsr.github.io.git" target="_blank" rel="noopener"
 &gt;uzimihsr/uzimihsr.github.io&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;以上2つのリポジトリを使ってブログページを作っていく.&lt;/p&gt;
&lt;h3 id="hugoでページを作成する"&gt;Hugoでページを作成する
&lt;/h3&gt;&lt;p&gt;Hugoをインストールして, サンプルページを作ってみる.&lt;br&gt;
以下, ターミナルで操作する.&lt;br&gt;
&lt;br&gt;
まずはHugoをインストール.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ brew install hugo
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;適当な作業用ディレクトリに移動(自分の場合は~/Workspaceを使う),&lt;br&gt;
hugoで新規プロジェクトを作成する.&lt;br&gt;
&lt;code&gt;Workspace/blog&lt;/code&gt;ディレクトリが作成される.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; ~/Workspace
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ brew install hugo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ hugo new site blog
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; blog
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Theme(いい感じのテンプレートみたいなもん)をインストールする.&lt;br&gt;
Themeの一覧は&lt;a class="link" href="https://themes.gohugo.io/" target="_blank" rel="noopener"
 &gt;ここ&lt;/a&gt;で見られるが, &lt;a class="link" href="https://themes.gohugo.io/beautifulhugo/" target="_blank" rel="noopener"
 &gt;Beautiful Hugo&lt;/a&gt;が良さそうなのでこれを使う.&lt;br&gt;
&lt;code&gt;git submodule add&lt;/code&gt;で&lt;code&gt;themes/beautifulhugo&lt;/code&gt;にBeautiful Hugoのリポジトリを追加する.&lt;br&gt;
他のThemeでもたぶん同じような操作でいけるはず.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git init
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git submodule add https://github.com/halogenica/beautifulhugo.git themes/beautifulhugo
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Beautiful Hugoは親切なのでサンプルページ(exampleSite)を用意してくれている.&lt;br&gt;
今回はそのまま使うので全部&lt;code&gt;blog&lt;/code&gt;直下にコピーする.&lt;br&gt;
コピーできたら, 早速ローカルで確認するためにhugo serverを立ち上げる.&lt;br&gt;
http://localhost:1313/ をブラウザで開くとexampleSiteのページが確認できる. 便利.&lt;br&gt;
だいたいわかったらCtrl+Cでhugo serverを止める.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cp -r themes/beautifulhugo/exampleSite/* .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ hugo server -D
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;次はいよいよ実際にページをビルドしてGitHub Pagesに公開する.&lt;br&gt;
が, その前に設定ファイルをいじっておく.&lt;br&gt;
&lt;code&gt;config.toml&lt;/code&gt;に指定した情報をThemeが読み込んでいい感じのページを生成してくれているらしいので, 自分用にいろいろ変更する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim config.toml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;config.toml&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-toml" data-lang="toml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;baseurl&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://uzimihsr.github.io&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;DefaultContentLanguage&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;en&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;meow.md&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;beautifulhugo&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;metaDataFormat&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;yaml&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;pygmentsStyle&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;trac&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;pygmentsUseClasses&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;pygmentsCodeFences&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;pygmentsCodefencesGuessSyntax&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;author&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Params&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;subtitle&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;にゃーん&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;logo&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;img/avatar-icon.png&amp;#34;&lt;/span&gt; &lt;span class="c"&gt;# Expecting square dimensions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;favicon&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;img/favicon.ico&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;dateFormat&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;January 2, 2006&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;commit&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;rss&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;comments&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;readingTime&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;wordCount&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;useHLJS&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;socialShare&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;delayDisqus&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;showRelatedPosts&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;uzimihsr&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;github&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;uzimihsr&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;twitter&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;uzimihsr&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="nx"&gt;menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Blog&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;weight&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="nx"&gt;menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Tags&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;tags&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;weight&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="nx"&gt;menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;About&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;page/about/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;weight&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="github-pagesでページを公開する"&gt;GitHub Pagesでページを公開する
&lt;/h3&gt;&lt;p&gt;ローカルの&lt;code&gt;blog&lt;/code&gt;ディレクトリにリモートの&lt;code&gt;blog&lt;/code&gt;リポジトリを紐付け,&lt;br&gt;
さらに&lt;code&gt;blog/public&lt;/code&gt;ディレクトリに&lt;code&gt;uzimihsr.github.io&lt;/code&gt;を紐付ける.&lt;br&gt;
Hugoでページをビルドすると&lt;code&gt;blog/public&lt;/code&gt;ディレクトリに必要なファイルが吐き出されるので,&lt;br&gt;
これを&lt;code&gt;uzimihsr.github.io&lt;/code&gt;にpushすることでGitHub Pagesが更新されていく.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git remote add origin https://github.com/uzimihsr/blog.git
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git submodule add -b master https://github.com/uzimihsr/uzimihsr.github.io.git public
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;いろいろごちゃごちゃしてきたので, かんたんに記事を更新できるようにスクリプト&lt;code&gt;deploy.sh&lt;/code&gt;を書く.&lt;br&gt;
このスクリプトはhugoコマンドでblogディレクトリの内容を元に静的ページをビルドし,&lt;br&gt;
&lt;code&gt;blog/public&lt;/code&gt;内に生成されたファイルをまとめて&lt;code&gt;uzimihsr.github.io&lt;/code&gt;リポジトリにpushしてくれる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim deploy.sh
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ chmod +x deploy.sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;deploy.sh&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/sh
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# If a command fails then the deploy stops&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;set&lt;/span&gt; -e
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;\033[0;32mDeploying updates to GitHub...\033[0m\n&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Build the project.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hugo &lt;span class="c1"&gt;# if using a theme, replace with `hugo -t &amp;lt;YOURTHEME&amp;gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Go To Public folder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; public
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Add changes to git.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git add .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Commit changes.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;rebuilding site &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;date&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; -n &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$*&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$*&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git commit -m &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$msg&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Push source and build repos.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git push origin master
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;作成したスクリプトを使ってページをビルドし, GitHub Pagesにpushする.&lt;br&gt;
すなわち, ブログを公開する. 更新されるのに少し時間がかかるが,&lt;br&gt;
&lt;a class="link" href="https://uzimihsr.github.io" target="_blank" rel="noopener"
 &gt;https://uzimihsr.github.io&lt;/a&gt; をブラウザで開くとローカルで確認したものと同じページが確認できる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ./deploy.sh &lt;span class="s2"&gt;&amp;#34;Initial commit&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="記事を追加する"&gt;記事を追加する
&lt;/h3&gt;&lt;p&gt;せっかくなので新しく記事を追加する.&lt;br&gt;
&lt;code&gt;blog/content/post&lt;/code&gt;にMarkdownが追加されるので, これをいい感じに編集する.&lt;br&gt;
一番上のテーブルにある&lt;code&gt;draft: false&lt;/code&gt;(下書き設定)を&lt;code&gt;draft: true&lt;/code&gt;に変えると記事が公開される.&lt;br&gt;
記事を更新したら, スクリプトを使って更新した情報をGitHub Pagesに反映させる.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ hugo new post/2019-08-07-create-blog-1.md
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim content/post/2019-08-07-create-blog-1.md
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ./deploy.sh &lt;span class="s2"&gt;&amp;#34;2019-08-07-create-blog-1.md&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="サンプルページから脱却する"&gt;サンプルページから脱却する
&lt;/h3&gt;&lt;p&gt;サンプルページのままだといらない記事があるので, 下書き設定(&lt;code&gt;draft: false&lt;/code&gt;)に変更する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim content/post/2015-01-04-first-post.md &lt;span class="c1"&gt;# 他の記事に対しても同様&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ./deploy.sh &lt;span class="s2"&gt;&amp;#34;サンプル記事を非公開にした&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;また, 日本語のフォントが気に食わないので&lt;code&gt;blog/themes/beautifulhugo/static/css/main.css&lt;/code&gt;をいじる.&lt;br&gt;
&lt;code&gt;font-family: 'Lora', 'Times New Roman', serif;&lt;/code&gt;となっている行を&lt;br&gt;
&lt;code&gt;font-family: 'arial', sans-serif;&lt;/code&gt;に変更する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim themes/beautifulhugo/static/css/main.css
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ./deploy.sh &lt;span class="s2"&gt;&amp;#34;フォントを変更した&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;注意すべきなのは, submoduleを編集しているためにこの変更をgitで管理できないこと.&lt;br&gt;
少し気持ち悪いので本当はBeautiful HugoをForkしてくるべき. あとで気が向いたらやる.&lt;/p&gt;
&lt;p&gt;アイコンも自分用に変更する.&lt;br&gt;
&lt;code&gt;blog/static/images/&lt;/code&gt;に&lt;code&gt;sotochan.jpg&lt;/code&gt;を配置して,&lt;br&gt;
&lt;code&gt;config.toml&lt;/code&gt;の&lt;code&gt;logo = &amp;quot;img/avatar-icon.png&amp;quot;&lt;/code&gt;となっている部分を&lt;br&gt;
&lt;code&gt;logo = &amp;quot;/images/sotochan.jpg&amp;quot;&lt;/code&gt;に書き換える.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mkdir static/images
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cp ~/Desktop/sotochan.jpg static/images
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim config.toml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ./deploy.sh &lt;span class="s2"&gt;&amp;#34;アイコンを変更した&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;トップページとaboutページを編集する.&lt;br&gt;
特にトップページに表示したいものも無いので&lt;code&gt;content/_index.md&lt;/code&gt;を削除する.&lt;br&gt;
また, &lt;code&gt;content/page/about.md&lt;/code&gt;を好きに編集する.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ rm content/_index.md
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim content/page/about.md
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以上でだいたいブログのセットアップは完了.&lt;br&gt;
あとは3日坊主にならないよう頻繁に書いていきたい.&lt;/p&gt;</description></item></channel></rss>