CINXE.COM

kubernetes で Ruby on Rails を動かして kubernetes を解説する | Basicinc Enjoy Hacking!

<!DOCTYPE html><html lang="ja" data-scope-path="layouts/application"><head prefix="og: http://ogp.me/ns# article: http://ogp.me/ns/article#"><link crossorigin="" href="https://www.google-analytics.com/analytics.js" rel="preconnect" /><link rel="preload" href="/fonts/noto-sans-jp-v24-japanese-regular.woff2" as="font" type="font/woff2" crossorigin="anonymous"><link rel="preload" href="/fonts/noto-sans-jp-v24-japanese-700.woff2" as="font" type="font/woff2" crossorigin="anonymous"><!-- Global site tag (gtag.js) - Google Analytics --> <script async src="https://www.googletagmanager.com/gtag/js?id=UA-25666851-3"></script> <script> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'UA-25666851-3'); </script> <link rel="stylesheet" media="all" href="/assets/ress-d1ba3a251927ab1f2bcc841c9a810109355bcb4260a522a0f76452fdc2fe6095.css" /><link rel="stylesheet" media="all" href="/assets/scopes/layouts/application-dda4ec688c139c8f29c39a2a795bcf4af04c4326643549a37f5d8843fffaebab.css" /><link rel="stylesheet" media="all" href="/assets/scopes/articles/show-37905516c06229c8fde10714e660fc48bc7b6ce7881755707db8b0327ceb5bf1.css" /><link rel="stylesheet" media="all" href="/assets/scopes/partials/_viewer-3a78a10250bb498047a06b71271b62ea949e304d25b9781c4450cf998aa2640c.css" /><link rel="stylesheet" media="all" href="/assets/scopes/layouts/_header-db87b54171cc020758ab7d1494677f8f6c2e9c93b453e896af82e4814eaacc7c.css" /><link rel="stylesheet" media="all" href="/assets/scopes/layouts/_breadcrumbs-744a099ab0b9eb5c4bd45215617e267c7d7c404ddddce8810eead5335512e637.css" /><link rel="stylesheet" media="all" href="/assets/scopes/layouts/_footer-a06961717440c6d0183c582c7f21768011f334d368f51b614eabc87bb17b3bbf.css" /><script src="/packs/application-02365dbc4dc28919eee1.js" defer="defer"></script><link href="/icon.png" rel="icon" type="image/png" /><link href="/apple-touch-icon.png" rel="apple-touch-icon" type="image/png" /><link href="/feed" rel="alternate" title="RSS2.0" type="application/rss+xml" /><title>kubernetes で Ruby on Rails を動かして kubernetes を解説する | Basicinc Enjoy Hacking!</title><meta name="csrf-param" content="authenticity_token" /> <meta name="csrf-token" content="EPmycJaerR7Jg9vHcY2rgmb8uQ0KC2xGneR+JgQ2on2bOV6YT8LehWJ+K+GmJh3wRwvHe6tRgoM1ongWM4bHdw==" /><meta content="width=device-width,initial-scale=1" name="viewport" /><meta content="kubernetes で Ruby on Rails を動かして kubernetes を解説する | Basicinc Enjoy Hacking!" property="og:title" /><meta content="article" property="og:type" /><meta content="2019-03-07T13:00:07+09:00" property="article:published_time" /><meta content="tkhr0" property="article:author" /><meta content="Technology" property="article:section" /><meta content="https://tech.basicinc.jp/articles/154" property="og:url" /><meta content="https://tech.basicinc.jp/uploads/7db042ea4ea9f4d016851ebe1b1a3c39.png" property="og:image" /><meta content="image/png" property="og:image:type" /><meta content="1200" property="og:image:width" /><meta content="630" property="og:image:height" /><meta content="巷で話題の kubernetes ですが、とってもとってもとっつきにくいですよね そんな kubernetes ですが手元で動かすことができたので解説してみます (情報が間違ってたらごめんなさい! ) 目標はこちら kubernetes の後述する基本的な概念を雰囲気理解す..." property="og:description" /><meta content="ja_JP" property="og:locale" /><meta content="summary_large_image" name="twitter:card" /><meta content="@tkhr0" name="twitter:creator" /></head><body><header data-scope-path="layouts/_header"><div class="header-contents"><a class="root-link" href="/"><svg class="site-logo"><use xlink:href="/assets/icons-5bbe775037b55281ef0bc50d30a51f69c7c3914d399c7107e37f0702d98ae8a2.svg#logo"></use></svg><div class="site-title">Enjoy Hacking!</div></a><div class="site-desc">Basicinc エンジニアブログ</div></div></header><nav data-scope-path="layouts/_breadcrumbs"><ul class="breadcrumbs" itemscope="itemscope" itemtype="https://schema.org/BreadcrumbList"><span class="pretext">% cat </span> <li itemprop="itemListElement" itemscope="itemscope" itemtype="https://schema.org/ListItem"><a itemprop="item" href="/"><span itemprop="name">~</span></a><meta itemprop="position" content="1" /></li>/<li class="current" itemprop="itemListElement" itemscope="itemscope" itemtype="https://schema.org/ListItem"><span itemprop="name">kubernetesでRubyonRailsを動かしてkubernetesを解説する.md</span><meta itemprop="item" content="https://tech.basicinc.jp/articles/154" /><meta itemprop="position" content="2" /></li></ul></nav><div data-scope-path="articles/show"><article class="article"><h1 class="article-title">kubernetes で Ruby on Rails を動かして kubernetes を解説する</h1><div class="article-desc"><a class="article-author" href="/authors/5"><img class="article-author-avatar" src="https://tech.basicinc.jp/uploads/909284ed0c2d297ecacb5230440540ae.png" /><span class="article-author-name">tkhr0</span></a><div class="article-date-info"><time class="article-posted-date">Posted 2019-03-07</time></div></div><div class="article-body"><div data-scope-path="partials/_viewer"><p>巷で話題の kubernetes ですが、とってもとってもとっつきにくいですよね<br> そんな kubernetes ですが手元で動かすことができたので解説してみます<br> (情報が間違ってたらごめんなさい! <img draggable="false" title=":bow:" alt="🙇" src="https://twemoji.maxcdn.com/2/svg/1f647.svg" class="emoji" loading="lazy">)</p> <p>目標はこちら</p> <ul> <li>kubernetes の後述する基本的な概念を雰囲気理解すること</li> <li>ローカルのクラスタにデプロイして Ruby on Rails ( Rails ) の 「 Yay! 」のページを見ること</li> </ul> <p>コードはこちら<br> <a href="https://github.com/tkhr0/hello-rails-on-k8s">https://github.com/tkhr0/hello-rails-on-k8s</a></p> <p>早速行きましょう</p> <h2>今回構築する環境</h2> <p>図にするとこんな感じです</p> <p><img src="https://tech.basicinc.jp/uploads/79ea971a3fe4acef83bae5bab1e7eb6b.png" alt=""></p> <p>kubernetes 要素を抜くとこんな Ngix + Rails + MySQL のよくある形です</p> <p><img src="https://tech.basicinc.jp/uploads/2ba7220b349334e1bada446e528ee446.png" alt="構築する環境"></p> <p>http サーバとして Nginx を立てて、 Rails (Puma) にリバースプロキシします<br> DB には MySQL を用意して Rails とやりとりします</p> <p>ここに kubernetes 要素を加味してこうです</p> <p><img src="https://tech.basicinc.jp/uploads/857bb71f06dd3253eb6b9d75860d4e47.png" alt="完成形"></p> <p>これが完成形になります</p> <p>なんかいろいろでてきましたね<br> 次で解説していきます</p> <h2>kubernetes の基本的な概念を雰囲気理解する</h2> <p>そこで今回紹介する概念はこちら</p> <ol> <li>Container</li> <li>Pod</li> <li>ReplicaSet</li> <li>Deployment</li> <li>Service</li> <li>Node</li> <li>Label</li> </ol> <p>いっぱいありますね<br> 雰囲気をお伝えするためにざっくり説明します<br> ( kubernetes が管理する↑こういうやつをオブジェクトと呼びます)</p> <h3>Container</h3> <p>まずは Container です。<br> 図での黄色です<br> これは Docker コンテナのことです<br> 1 つの Container には 1 プロセスとすることが推奨されています<br> 直接 kubernetes の概念ではないですが、 kubernetes はこいつを取り扱うためのツールですね</p> <h3>Pod</h3> <p>そして Pod です<br> 図での明るい方の青です<br> これは Container をまとめる最小単位となります<br> 僕の中のイメージは AWS の EC2 インスタンスです<br> インスタンスの中にミドルウェアとしてアプリケーションが入ってるように、 Pod の中に Container としてアプリケーションが入っているイメージです</p> <p>ここで Pod は冗長化には向いていません<br> 例えば Nginx を 2つ立てる場合には Pod を 2つ用意する必要があります<br> それは手間ですよね</p> <p>それを解決するのが ReplicaSet です</p> <h3>ReplicaSet</h3> <p>図での緑色です<br> ReplicaSet は Pod をまとめて扱う役割があります<br> Pod を ReplicaSet 配下に置くことで ReplicaSet 単位で複製して群として扱うことができます</p> <h3>Deployment</h3> <p>次に Deployment です<br> 図でのねずみ色です<br> Deployment はアプリケーションのデプロイをしてくれます<br> Docker Image から Pod や ReplicaSet を生成して Node に配置します<br> また RollingUpdate 戦略が用いられるため、ダウンタイムを発生させずにデプロイすることができます</p> <h3>Service</h3> <p>そして Service です<br> 図での暗い方の青色です<br> Pod が外部とやりとりするために必要になるオブジェクトです<br> WAN からのリクエストを Pod に割り振ったり、 Pod から Pod への通信を仲介したりしてくれます<br> また Service がいることでサービスディスカバリを提供できます<br> ※ サービスディスカバリとは、サーバでネットワークの変更があってもクライアントからは同じようにアクセスし続けられる仕組みのこと。 DNS もひとつですね。</p> <h3>Node</h3> <p>次は先ほど出てきた Node です<br> 図でのシルバーです<br> Node は… Node です<br> 物理サーバとニアリーイコールなイメージです<br> うまく説明できませんが kubernetes が管理している領域を表します</p> <h3>Label</h3> <p>最後に Label です<br> Service, ReplicaSet, Pod などのオブジェクトは Label を用いてグルーピングをすることができます<br> リクエストの送信先や所属関係はこの Label によるグルーピングで表します<br> なので、逆に入れ子関係や親子関係のような概念は kubernetes では出てきません<br> 概念的にはすべてのオブジェクトは並列に並んでおり Label によってグルーピングがなされています</p> <p>kubernetes を構成する要素はこのようになっています<br> kubernetes はサーバを管理するための要素を一般化するためにたくさんの機能を持っています<br> それらを Pod や Deployment などの単位に区切ることで疎結合なシステムを提供しています<br> 要素数はたくさんありますが kubernetes なしでのサーバ環境と近いところがあるので少しづつ理解しましょう</p> <p>またここでは紹介しませんでしたが他にもいろいろな機能が提供されています<br> crontab のように定期的に動作を行う Job や環境ごとの設定の違いを吸収する ConfigMap など多数の要素があります<br> 実際に本番環境での運用をする場合には必要になってくるので一緒にググってみてください</p> <h2>ローカルで kubernetes を動かす</h2> <p>先ほどざっくりお伝えした雰囲気を携えて実際に kubernetes を動かしてみましょう</p> <p>手元の環境はこちらです</p> <pre><code>$ docker -v Docker version 18.06.1-ce, build e68fc7a $ kubectl version Client Version: version.Info{Major:"1", Minor:"13", GitVersion:"v1.13.2", GitCommit:"cff46ab41ff0bb44d8584413b598ad8360ec1def", GitTreeState:"clean", BuildDate:"2019-01-25T08:47:41Z", GoVersion:"go1.11.4", Compiler:"gc", Platform:"darwin/amd64"} Server Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.3", GitCommit:"2bba0127d85d5a46ab4b778548be28623b32d0b0", GitTreeState:"clean", BuildDate:"2018-05-21T09:05:37Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"linux/amd64"} </code></pre> <h3>下準備</h3> <p>まずはこちらのリポジトリをクローンしてください<br> <a href="https://github.com/tkhr0/hello-rails-on-k8s">https://github.com/tkhr0/hello-rails-on-k8s</a></p> <p>そしてローカルの kubernetes 環境を起動します<br> Docker Desktop for Mac 18.06.0-ce-mac70 CE から kubernetes が同梱されているのでそれを起動します</p> <p>Docker の設定画面から<br> <code>Kubernetes</code> &gt; <code>Enable Kubernetes</code> &gt; <code>Kubernetes</code><br> とクリックして kubernetes を起動します</p> <p><img src="https://tech.basicinc.jp/uploads/4483002989113e8def66a2031b78d0c6.png" alt="k8s 起動"></p> <p>Docker のバージョンが古い場合には minikube というツールで代替してください</p> <p>最後に <code>kubectl</code> というコマンドが必要になるのでマシンにインストールしてください<br> これは <code>docker</code> コマンドのように kubernetes エンジンとやりとりするためのコマンドです<br> こちらを参考にしてみてください<br> <a href="https://kubernetes.io/docs/tasks/tools/install-kubectl/">https://kubernetes.io/docs/tasks/tools/install-kubectl/</a></p> <p>mac &amp; Homebrew ならこのコマンドでインストールできます</p> <pre lang="bash" class="highlight-bash"><span class="nv">$ </span>brew <span class="nb">install </span>kubernetes-cli </pre> <h3>とりあえず動かす</h3> <p>とりあえず kubernetes にデプロイしてみましょう<br> クローンしたリポジトリ内で以下のコマンドを打ってみてください</p> <p>各種 Docker イメージの pull と build が走るので少し時間がかかります</p> <pre lang="bash" class="highlight-bash"><span class="nv">$ </span>docker build <span class="nt">-f</span> .docker/containers/app/Dockerfile <span class="nt">-t</span> hello-rails-on-k8s-app:latest <span class="nb">.</span> <span class="nv">$ </span>docker build <span class="nt">-f</span> .docker/containers/nginx/Dockerfile <span class="nt">-t</span> hello-rails-on-k8s-nginx:latest <span class="nb">.</span> <span class="nv">$ </span>kubectl apply <span class="nt">-f</span> .docker/kubernetes/webserver.yml <span class="nv">$ </span>kubectl apply <span class="nt">-f</span> .docker/kubernetes/dbserver.yml </pre> <p>最後に下記のコマンドを打ちます<br> kubernetes が管理するオブジェクトを確認できます</p> <pre lang="bash" class="highlight-bash"><span class="nv">$ </span>kubectl get all </pre> <p>こんな感じの結果が返ってきたら成功です</p> <pre><code>NAME READY STATUS RESTARTS AGE pod/dbserver-deployment-6dd6fbf959-hf52l 0/1 ErrImageNeverPull 0 4m pod/webserver-deployment-65d64cb4d8-x9vdt 1/2 ErrImageNeverPull 0 4m NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/dbserver-service ClusterIP 10.100.147.224 &lt;none&gt; 3306/TCP 4m service/kubernetes ClusterIP 10.96.0.1 &lt;none&gt; 443/TCP 109d service/webserver-service ClusterIP 10.106.16.206 &lt;none&gt; 84/TCP 4m NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE deployment.apps/dbserver-deployment 1 1 1 0 4m deployment.apps/webserver-deployment 1 1 1 0 4m NAME DESIRED CURRENT READY AGE replicaset.apps/dbserver-deployment-6dd6fbf959 1 1 0 4m replicaset.apps/webserver-deployment-65d64cb4d8 1 1 0 4m </code></pre> <p>Pod x2, Service x2, Deployment x2, ReplicaSet x2 が動いているのがわかります</p> <h2>いろいろイジる</h2> <p>kubernetes はオブジェクトの定義に基づいてオブジェクトを展開・管理します<br> その定義ファイルをみていじってみましょう</p> <h3>定義を見る</h3> <p>こちらが web サーバの Service, Deployment, ReplicaSet, Pod の定義です</p> <pre lang="yaml" class="highlight-yaml"><span class="c1"># Service の定義</span> <span class="na">apiVersion</span><span class="pi">:</span> <span class="s">v1</span> <span class="na">kind</span><span class="pi">:</span> <span class="s">Service</span> <span class="na">metadata</span><span class="pi">:</span> <span class="c1"># この Service の名前</span> <span class="na">name</span><span class="pi">:</span> <span class="s">webserver-service</span> <span class="na">spec</span><span class="pi">:</span> <span class="na">type</span><span class="pi">:</span> <span class="s">ClusterIP</span> <span class="c1"># Label がこれらにマッチした Pod にアクセスを流す</span> <span class="na">selector</span><span class="pi">:</span> <span class="na">app</span><span class="pi">:</span> <span class="s">hello-rails-on-k8s</span> <span class="na">server</span><span class="pi">:</span> <span class="s">web</span> <span class="c1"># ポートの指定</span> <span class="na">ports</span><span class="pi">:</span> <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">http</span> <span class="na">protocol</span><span class="pi">:</span> <span class="s">TCP</span> <span class="c1"># 受信するポート</span> <span class="na">port</span><span class="pi">:</span> <span class="m">84</span> <span class="c1"># 送信するポート</span> <span class="na">targetPort</span><span class="pi">:</span> <span class="s">http</span> <span class="nn">---</span> <span class="c1"># Deployment の定義</span> <span class="na">apiVersion</span><span class="pi">:</span> <span class="s">apps/v1</span> <span class="na">kind</span><span class="pi">:</span> <span class="s">Deployment</span> <span class="na">metadata</span><span class="pi">:</span> <span class="c1"># この Deployment の名前</span> <span class="na">name</span><span class="pi">:</span> <span class="s">webserver-deployment</span> <span class="c1"># この Deployment につけるラベル</span> <span class="na">labels</span><span class="pi">:</span> <span class="na">app</span><span class="pi">:</span> <span class="s">hello-rails-on-k8s</span> <span class="c1"># 管理する ReplicaSet の定義</span> <span class="na">spec</span><span class="pi">:</span> <span class="c1"># 展開するレプリカ数</span> <span class="na">replicas</span><span class="pi">:</span> <span class="m">1</span> <span class="c1"># Label がこれらにマッチした Pod をこの ReplicaSet の配下に置く</span> <span class="na">selector</span><span class="pi">:</span> <span class="na">matchLabels</span><span class="pi">:</span> <span class="na">app</span><span class="pi">:</span> <span class="s">hello-rails-on-k8s</span> <span class="na">server</span><span class="pi">:</span> <span class="s">web</span> <span class="c1"># 展開する Pod の定義</span> <span class="na">template</span><span class="pi">:</span> <span class="na">metadata</span><span class="pi">:</span> <span class="c1"># この Pod につける Label</span> <span class="na">labels</span><span class="pi">:</span> <span class="na">app</span><span class="pi">:</span> <span class="s">hello-rails-on-k8s</span> <span class="na">server</span><span class="pi">:</span> <span class="s">web</span> <span class="na">spec</span><span class="pi">:</span> <span class="na">volumes</span><span class="pi">:</span> <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">sockets</span> <span class="na">emptyDir</span><span class="pi">:</span> <span class="pi">{}</span> <span class="c1"># Container の定義</span> <span class="na">containers</span><span class="pi">:</span> <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">nginx</span> <span class="c1"># イメージの指定</span> <span class="na">image</span><span class="pi">:</span> <span class="s">hello-rails-on-k8s-nginx:latest</span> <span class="na">imagePullPolicy</span><span class="pi">:</span> <span class="s">Never</span> <span class="na">ports</span><span class="pi">:</span> <span class="c1"># Service から受けるポート</span> <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">http</span> <span class="na">containerPort</span><span class="pi">:</span> <span class="m">8080</span> <span class="na">volumeMounts</span><span class="pi">:</span> <span class="pi">-</span> <span class="na">mountPath</span><span class="pi">:</span> <span class="s">/sockets</span> <span class="na">name</span><span class="pi">:</span> <span class="s">sockets</span> <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">rails</span> <span class="c1"># イメージの指定</span> <span class="na">image</span><span class="pi">:</span> <span class="s">hello-rails-on-k8s-app:latest</span> <span class="na">imagePullPolicy</span><span class="pi">:</span> <span class="s">Never</span> <span class="na">env</span><span class="pi">:</span> <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">DB_HOST</span> <span class="c1"># Service にはドメインが割り振られる</span> <span class="na">value</span><span class="pi">:</span> <span class="s">dbserver-service.default.svc.cluster.local</span> <span class="na">volumeMounts</span><span class="pi">:</span> <span class="pi">-</span> <span class="na">mountPath</span><span class="pi">:</span> <span class="s">/sockets</span> <span class="na">name</span><span class="pi">:</span> <span class="s">sockets</span> </pre> <h3>Rails にアクセスしてみる</h3> <p>動作確認のために Rails にアクセスしてみましょう<br> と、言いたいところですが今はアクセスできません</p> <p>kubernetes のネットワークを司る Serivce の状況を見てみましょう</p> <pre lang="bash" class="highlight-bash"><span class="nv">$ </span>kubectl get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT<span class="o">(</span>S<span class="o">)</span> AGE dbserver-service ClusterIP 10.100.147.224 &lt;none&gt; 3306/TCP 18h kubernetes ClusterIP 10.96.0.1 &lt;none&gt; 443/TCP 110d webserver-service ClusterIP 10.107.232.16 &lt;none&gt; 84/TCP 7s </pre> <p>ここで <code>TYPE</code> 列に <code>ClusterIP</code> と記載があります<br> ClusterIP は kubernetes の中でのみ解決できる IP になります<br> そのため kubernetes の外、つまりローカルマシンからアクセスできる IP が存在しない状態です<br> <code>PORT(S)</code> 列をみるとポートを <code>EXPOSE</code> しているだけなのがわかります</p> <p>これを解決するためには <code>NodePort</code> という type を設定します<br> NodePort は kubernetes の外からもアクセスできる IP です</p> <p>ということで NodePort を設定してみましょう<br> <code>webserver-service</code> と <code>dbserver-service</code> の 2つの Service がありますが、 <code>webserver-service</code> のみに設定します<br> <code>webserver-service</code> は Nginx に繋がっていて <code>dbserver-service</code> は MySQL に繋がっています<br> MySQL を外に出す必要はないので <code>dbserver-service</code> は ClusterIP を使うべきです<br> なので <code>webserver-service</code> のみ設定します<br> ( <code>kubernetes</code> という Service もありますが、これは kubernetes が内部的に使用しているものです)</p> <p>さて <code>.docker/kubernetes/webserver.yml</code> を編集します<br> Service の定義の中で <code>.spec.type</code> の値を <code>ClusterIP</code> から <code>NodePort</code> に変更します</p> <p>そして下記のコマンドで変更を適用します</p> <pre lang="bash" class="highlight-bash"><span class="nv">$ </span>kubectl delete svc webserver-service service <span class="s2">"webserver-service"</span> deleted <span class="nv">$ </span>kubectl apply <span class="nt">-f</span> .docker/kubernetes/webserver.yml service/webserver-service created deployment.apps/webserver-deployment unchanged </pre> <p>変更を確認しましょう</p> <pre lang="bash" class="highlight-bash"><span class="nv">$ </span>kubectl get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT<span class="o">(</span>S<span class="o">)</span> AGE dbserver-service ClusterIP 10.100.147.224 &lt;none&gt; 3306/TCP 19h kubernetes ClusterIP 10.96.0.1 &lt;none&gt; 443/TCP 110d webserver-service NodePort 10.107.232.16 &lt;none&gt; 84:30956/TCP 20m </pre> <p><code>webserver-service</code> の <code>PORT(S)</code> 列が変わりました<br> <code>84:30956</code> となっているので <code>30956</code> へのアクセスを <code>84</code> へ流します</p> <p>実際に <code>http://localhost:30956/</code> にブラウザでアクセスしてみましょう<br> おなじみの <code>Yay! You're on Rails!</code> を見れるかと思います</p> <h3>冗長化してみる</h3> <p>ReplicaSet を 2つにすることで冗長化してみます</p> <p>まずは現状を見てみます</p> <pre lang="bash" class="highlight-bash"><span class="nv">$ </span>kubectl get pod NAME READY STATUS RESTARTS AGE dbserver-deployment-685f496464-97qk7 1/1 Running 0 1h webserver-deployment-5595df784c-sv5q9 2/2 Running 0 1h </pre> <p><code>webserver</code> で始まる Pod が 1つあります</p> <p>次に <code>.docker/kubernetes/webserver.yml</code> を編集します<br> ReplicaSet の設定の中で <code>.spec.replicas</code> の値を 1 から 2 に変更します<br> そして <code>kubectl apply</code> コマンドで変更を適用します</p> <p><code>$ kubectl apply -f .docker/kubernetes/webserver.yml</code></p> <p><code>kubectl get pod</code> コマンドで変更を確認します</p> <pre lang="bash" class="highlight-bash"><span class="nv">$ </span>kubectl get pod NAME READY STATUS RESTARTS AGE dbserver-deployment-685f496464-97qk7 1/1 Running 0 98m webserver-deployment-5595df784c-crgkx 2/2 Running 0 4s webserver-deployment-5595df784c-sv5q9 2/2 Running 0 93m </pre> <p><code>webserver</code> で始まる Pod が 2つになりました</p> <p>この状態で puma のアクセスログをみてみましょう</p> <pre lang="bash" class="highlight-bash"><span class="nv">$ </span>kubectl logs <span class="nt">-f</span> webserver-deployment-5595df784c-crgkx rails <span class="c"># 別のウィンドウで</span> <span class="nv">$ </span>kubectl logs <span class="nt">-f</span> webserver-deployment-5595df784c-sv5q9 rails </pre> <p>ブラウザでリロードしまくると kubernetes が各 Pod に対してロードバランシングするためそれぞれにアクセスがあることが確認できます</p> <h3>デプロイしてみる</h3> <p>Deployment を使って新しいバージョンのアプリケーションをデプロイしてみましょう</p> <p>タグを <code>hello-rails-on-k8s-app:v2</code> に変更してビルドします</p> <pre lang="bash" class="highlight-bash">docker build <span class="nt">-f</span> .docker/containers/app/Dockerfile <span class="nt">-t</span> hello-rails-on-k8s-app:v2 <span class="nb">.</span> </pre> <p><code>.docker/kubernetes/webserver.yml</code> を編集します<br> Deployment の設定の中で <code>.spec.template.spec.containers[1].image</code> の値を変更します<br> <code>hello-rails-on-k8s-app:latest</code> を <code>hello-rails-on-k8s-app:v2</code> にします</p> <p>まず、現状を確認するために <code>kubectl describe</code> コマンドを打ちます</p> <pre lang="bash" class="highlight-bash"><span class="nv">$ </span>kubectl get pod NAME READY STATUS RESTARTS AGE dbserver-deployment-6dd6fbf959-hf52l 0/1 ErrImageNeverPull 0 17h webserver-deployment-65d64cb4d8-gwmk5 2/2 Running 6 1h <span class="nv">$ </span>kubectl describe pod webserver-deployment-544cb4c74f-4qsds ~~ 略 ~~ rails: Container ID: docker://881c9508e1df9dfeb21df52e2293ac8f75fea5b15f6a1de0a18b7ec9dbbc32d9 Image: hello-rails-on-k8s-app:latest Image ID: docker://sha256:c482a73c4174c8e1005b8ffa58bea421ae27b4ca08be350bec31f52502e2b9fa ~~ 略 ~~ </pre> <p>rails のイメージには <code>hello-rails-on-k8s-app:latest</code> が使われています</p> <p>そして <code>kubectl apply</code> コマンドで変更を適用します…の前にひとつコマンドを打ちましょう</p> <pre lang="bash" class="highlight-bash"><span class="nv">$ </span>kubectl get pod <span class="nt">-w</span> NAME READY STATUS RESTARTS AGE dbserver-deployment-685f496464-97qk7 1/1 Running 0 98s webserver-deployment-65d64cb4d8-gwmk5 2/2 Running 0 67s </pre> <p>ログが流れてくるので別のウィンドウを開いて <code>kubectl apply</code> コマンドを打ちましょう</p> <p><code>$ kubectl apply -f .docker/kubernetes/webserver.yml</code></p> <p>そうすると <code>kubectl get pod -w</code> を打ったウィンドウで Pod の作成状況が流れてきます</p> <pre lang="bash" class="highlight-bash">webserver-deployment-5595df784c-sv5q9 0/2 Pending 0 0s webserver-deployment-5595df784c-sv5q9 0/2 Pending 0 0s webserver-deployment-5595df784c-sv5q9 0/2 ContainerCreating 0 0s webserver-deployment-5595df784c-sv5q9 2/2 Running 0 3s webserver-deployment-65d64cb4d8-gwmk5 2/2 Terminating 0 4m6s webserver-deployment-65d64cb4d8-gwmk5 0/2 Terminating 0 4m38s </pre> <p>webserver が 2つあって <code>Running</code> と <code>Terminating</code> だったりします<br> Deployment が RollingUpdate して新しいコンテナを展開して、展開できたら古いコンテナを削除する、という動きが見れますね</p> <p><code>kubectl describe</code> を打ちましょう</p> <pre lang="bash" class="highlight-bash">~~ 略 ~~ rails: Container ID: docker://651ad2790d7d103dbc24df0a84dbaa2e833a2180cdc384cc684090be4c20f668 Image: hello-rails-on-k8s-app:v2 Image ID: docker://sha256:2722376b4a713a3660ec74bf9febd63269dfa973f31a2dc10e48935b419952fe ~~ 略 ~~ </pre> <p>ちゃんと rails のイメージには <code>hello-rails-on-k8s-app:v2</code> が使われています</p> <p>Deployment にて、使用するイメージを指定して <code>apply</code> したら kubernetes がよしなにやってくれることがわかりました</p> <h3>オブジェクトを削除する</h3> <p><code>kubectl delete</code> コマンドできれいさっぱり削除できます</p> <pre lang="bash" class="highlight-bash"><span class="nv">$ </span>kubectl delete <span class="nt">-f</span> .docker/kubernetes/webserver.yml <span class="nv">$ </span>kubectl delete <span class="nt">-f</span> .docker/kubernetes/dbserver.yml </pre> <h2>まとめ</h2> <p>いかがでしたでしょうか?<br> この目標は達成できましたか?</p> <ul> <li>kubernetes の後述する基本的な概念を雰囲気理解すること</li> <li>ローカルのクラスタにデプロイして Ruby on Rails ( Rails ) の 「 Yay! 」のページを見ること</li> </ul> <p>kubernetes の入り口をざっと解説してみました<br> ですが、解説できなかったものもあります<br> なぜ ClusterIP が 2つあるのか、 socket をどうやって繋げているのか、定義ファイルをコメントで逃げた、などなど<br> また、 <a href="https://github.com/tkhr0/hello-rails-on-k8s">tkhr/hello-rails-onlk8s</a> のリポジトリでは fluentd と kibana を動かしていたり、 kubernetes のデプロイを helm で行っていたりします<br> それらについても触れたかったのですが、読みごたえがすごいことになってしまうので割愛しました</p> <p>もっといろいろできるのが kubernetes とのことです<br> なので僕もこれから勉強していきたいと思います<br> できる人教えてください</p> <h2>参考</h2> <ul> <li><a href="https://www.oreilly.co.jp/books/9784873118406/">O'Reilly Japan - 入門 Kubernetes</a></li> <li><a href="https://gihyo.jp/book/2018/978-4-297-10033-9">Docker/Kubernetes 実践コンテナ開発入門:書籍案内|技術評論社</a></li> </ul></div></div><div class="article-sns-share-buttons"><a rel="nofollow" target="_blank" class="pocket-share sns-share-button" href="http://getpocket.com/edit?title=kubernetes+%E3%81%A7+Ruby+on+Rails+%E3%82%92%E5%8B%95%E3%81%8B%E3%81%97%E3%81%A6+kubernetes+%E3%82%92%E8%A7%A3%E8%AA%AC%E3%81%99%E3%82%8B+by+tkhr0+%7C+Basicinc+Enjoy+Hacking%21&amp;url=https%3A%2F%2Ftech.basicinc.jp%2Farticles%2F154"><svg class="sns-icon pocket-icon"><use xlink:href="/assets/icons-5bbe775037b55281ef0bc50d30a51f69c7c3914d399c7107e37f0702d98ae8a2.svg#pocket"></use></svg></a><a rel="nofollow" target="_blank" class="hatena-share sns-share-button" href="http://b.hatena.ne.jp/add?mode=confirm&amp;title=kubernetes+%E3%81%A7+Ruby+on+Rails+%E3%82%92%E5%8B%95%E3%81%8B%E3%81%97%E3%81%A6+kubernetes+%E3%82%92%E8%A7%A3%E8%AA%AC%E3%81%99%E3%82%8B+by+tkhr0+%7C+Basicinc+Enjoy+Hacking%21&amp;url=https%3A%2F%2Ftech.basicinc.jp%2Farticles%2F154"><svg class="sns-icon hatena-icon"><use xlink:href="/assets/icons-5bbe775037b55281ef0bc50d30a51f69c7c3914d399c7107e37f0702d98ae8a2.svg#hatena"></use></svg></a><a rel="nofollow" target="_blank" class="twitter-share sns-share-button" href="https://twitter.com/share?text=kubernetes+%E3%81%A7+Ruby+on+Rails+%E3%82%92%E5%8B%95%E3%81%8B%E3%81%97%E3%81%A6+kubernetes+%E3%82%92%E8%A7%A3%E8%AA%AC%E3%81%99%E3%82%8B+by+tkhr0+%7C+Basicinc+Enjoy+Hacking%21&amp;url=https%3A%2F%2Ftech.basicinc.jp%2Farticles%2F154"><svg class="sns-icon twitter-icon"><use xlink:href="/assets/icons-5bbe775037b55281ef0bc50d30a51f69c7c3914d399c7107e37f0702d98ae8a2.svg#twitter"></use></svg></a><a rel="nofollow" target="_blank" class="facebook-share sns-share-button" href="http://www.facebook.com/share.php?u=https%3A%2F%2Ftech.basicinc.jp%2Farticles%2F154"><svg class="sns-icon facebook-icon"><use xlink:href="/assets/icons-5bbe775037b55281ef0bc50d30a51f69c7c3914d399c7107e37f0702d98ae8a2.svg#facebook"></use></svg></a></div></article></div><footer data-scope-path="layouts/_footer"><div class="footer-contents"><a class="root-link" href="/"><svg class="site-logo"><use xlink:href="/assets/icons-5bbe775037b55281ef0bc50d30a51f69c7c3914d399c7107e37f0702d98ae8a2.svg#logo"></use></svg><div class="site-title">Enjoy Hacking!</div></a><ul class="link-list"><li class="link-list-item"><a class="link" href="https://basicinc.jp/" rel="noopener" target="_blank">株式会社ベーシック</a></li><li class="link-list-item"><a class="link" href="https://basicinc.jp/enjoy-hacking" rel="noopener" target="_blank">エンジニア募集</a></li><li class="link-list-item"><a class="link" href="https://qiita.com/organizations/basicinc" rel="noopener" target="_blank">Qiita</a></li><li class="link-list-item"><a class="link" href="https://www.wantedly.com/companies/basicinc/projects" rel="noopener" target="_blank">Wantedly</a></li></ul></div></footer></body></html>

Pages: 1 2 3 4 5 6 7 8 9 10