1078
946

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

リクルートライフスタイルAdvent Calendar 2016

Day 10

kubernetes初心者のための入門ハンズオン

Last updated at Posted at 2016-12-09

この記事はリクルートライフスタイル Advent Calendar 2016の10日目の記事です。

DEPRECATED! [2020/12/05追記]

この記事内のコマンドは現在のバージョンの挙動と一部異なっていたり、説明に不正確な部分があります。
例えば公式のチュートリアルなど、信頼できる情報を参照ください。
https://kubernetes.io/ja/docs/tutorials/kubernetes-basics/

2019/05/30追記

下記内容は若干の不正確を含みますので、軽く読み流して雰囲気を掴んでいただいたあとは
https://qiita.com/Kta-M/items/ce475c0063d3d3f36d5d
などご参照いただくとよいかと思います。

こんばんは

「sshするときの-p 443ってなんの数字ですか?」ぐらいの素人がインフラ周りを担当し8ヶ月、kubernetes始めました。
そんな初心者に送るkubernetes入門記事です。

なんでわざわざkubernetes?

一般のwebサイトはサーバーの上で動いているわけですが、このサーバーが1台だとこんな問題が起きます。

  • キャンペーンをやったら急にアクセスが集中して負荷に耐え切れず、webサイト全体がダウンしてしまった
  • サーバーのライブラリをアップデートしたら変なエラーが出るようになってしまった

ああ大変だ。こうなっては困るので、サーバーを複数台にする対策があります。冗長化と呼ばれます。
ラウンドロビンの話は飛ばしますが、最近だとAWSやGCPでロードバランサーと呼ばれるアクセス分配器的なものを用意して、いくつかのサーバーにアクセスをバラすのがナウいです。
クラウドサービスを使っていれば、オートスケーリングと呼ばれる機能で、サーバーの台数を自動で増減することができます。
しかしこの冗長化構成にも新たな要求が出てきます。

  • サーバーの台数を少なめにしておくと、急にアクセスが来た時にサーバー台数を増やすのが間に合わず、結局サービスが落ちてしまう
  • かといって多く用意しておくと、アクセスが少ない時にお金がもったいない
  • Immutable Infrastructureとはいうものの、デプロイの度にサーバー入れ替えるの時間かかる

ああ困った。そこにkubernetes(以下k8s)が現れます。 k8sはこれらの問題に対して以下のようなメリットを与えます。

  • サーバー台数と関係なく、複数のapplicationを起動できる(コンピュータ資源の最適化ができる)
  • 負荷に応じてapplicationごとに自動で数を増減できる
  • サーバーを入れ替えることなくapplicationのデプロイができる。軽いものならば数秒程度

k8sを使うには、通常はmasterと呼ばれる親機とnodeと呼ばれる子機サーバーを用意して、k8sをそれぞれインストールし、それぞれ通信設定…めんどくさいです。
しかし、 AWSのECSやGCPのGKEのようなk8sのマネージドサービス上で展開すれば、masterとnodeは数分で勝手に準備され、不調になったnodeは自動で入れ替わる、さらにnodeの数も増減できる、などいいことだらけ。

ということで長くなりましたが、ここからGKE上で実際にハンズオンをしていきましょう。

前準備

まずGCPのセットアップです。無料使用期間あるので、入門記事など参考に登録しましょう。gcloudとかkubectlとか含めてセットアップが終わったら次のコマンドを叩きます。

gcloud container clusters create k0 

コーヒーを淹れるくらいの時間で、上述のmasterとnode(defaultだと3台)が立ち上がります。nodeとはGCPでのVM、AWSでのinstanceに相当します。GKE上では基本的にmasterには触りません。

result
Creating cluster k0...done.
Created [https://container.googleapis.com/v1/projects/user/zones/asia-east1-a/clusters/k0].
kubeconfig entry generated for k0.
NAME  ZONE          MASTER_VERSION  MASTER_IP        MACHINE_TYPE   NODE_VERSION  NUM_NODES  STATUS
k0    asia-east1-a  1.4.6           104.199.249.239  n1-standard-1  1.4.6         3          RUNNING

1.イントロダクション

細かいことは飛ばして、とりあえず動かしましょう。

kubectl run nginx --image=nginx:1.11.3

何が起きたかというと、さっき立ち上げたnode内で、podが動き始めました。

podとは?

nodeの中で動いているdocker containerの集まり、みたいなイメージです。k8sでは、nodeの集合(nodes)のパワー全体をリソースとして、podがいくつも立ち上がります。
面白いのは、あるnodeにはpodAとpodBが1つずつ、あるnodeにはpodBが3つ、といったように、node全体としてpodsを共有している点です。

pod1つの中に、任意の数のdocker containerを詰め込むことが可能です。nginxとweb apllicationとredisとか。pod 1 つに対して内部IPが 1 つ割り当てられ、container間で共有できるvolumeも任意の数持てます。

引数で指定したのは、Docker Hub 公式のnginx containerです。つまり上のコマンドは「nginx imageを使ってpodを作れ」という意味になります。
ではnginxのpodがどうなってるか確認しましょう。

result
[user:~]$ kubectl get pods
NAME                    READY     STATUS    RESTARTS   AGE
nginx-527997929-1m6nj   1/1       Running   0          22s

kubectl get <name>nameの概要を見れます。無事作成できました。

でもこれだと、nodesの中でcontainerが動いてるだけなので外部からアクセスできません。外部アクセスさせるために次のコマンドを打ちます。

kubectl expose deployment nginx --port 80 --type LoadBalancer

これで、serviceとロードバランサーが作られました。

serviceとは?

pods(podの集合)に対して外部と通信を行うための通り道みたいなものです。serviceひとつにpodsがぶらさがって、serviceに来たアクセスをどれかのpodにいい感じで分配します(内部に賢いroutingがいます)。

今回はオプションに LoadBalancer を指定したので、GCP上に外部IPを持ったロードバランサーが作成され、その外部IPに対してのアクセスがserviceに来るようになります。

これで、さっき作成したnginx入りのpodが外部IPと紐付きました。serviceを確認してみましょう。

result
[user:~]$ kubectl get services
NAME         CLUSTER-IP      EXTERNAL-IP       PORT(S)   AGE
kubernetes   10.23.240.1     <none>            443/TCP   6m
nginx        10.23.248.197   104.198.112.131   80/TCP    1m

今回はnginxという名前でserviceが作成されました。一緒にでてくるkubernetesはmasterからnodeに通信する用のserviceです。
作成されたロードバランサーの外部IP 104.198.112.131にアクセスしてみましょう。

スクリーンショット 2016-12-08 16.10.10.png

表示されたらOKです。ちなみに今まで作成していたものの全体像はこんな感じです。

スクリーンショット 2016-12-08 16.10.10.png

2.カスタマイズしたpodとserviceを作る

さっきはdefaultのnginx imageを使いましたが、今度はカスタマイズして、nginx+webアプリの構成でpodを作ってみましょう。
サンプルを用意したので、利用するコードをgit cloneしてください。

git clone https://github.com/mihirat/advent.git
cd /path/to/advent/kubernetes
cd k8s

ここにあるdeployment.ymlがpodの設定、service.ymlがserviceの設定になります。
ちなみにpath/to/advent/kubernetes/docker というディレクトリに今回のdocker imageの設定があります、ご参考まで。本ハンズオンではDockerHubにあるものを使ってください。

deploymentとは?

podを管理するコントローラーであるReplication Controllerとpodの両方を一括で管理できるものです。k8sはアップデートが早いので、1年前の記事とかだとReplication Controllerとpodを別で作成していることが多いのですが、絶対にdeploymentを使った方が楽です。
お気づきかもしれませんが、イントロダクションの段階からずっとdeploymentを使っていました。
実はbetaですが、もう1年近くbetaみたいなので気にしなくていのかな…?

設定の中身を見ていきましょう。

deployment.yml
etc...
  strategy:
    type: RollingUpdate
...
      containers:
      - name: go-server
        image: mihirat/go-server
...
        readinessProbe:
          httpGet:
            # Path to probe; should be cheap, but representative of typical behavior
            path: /readiness.html
etc...

↑部分のRollingUpdateを使うと、containersimageで引っ張ってきたイメージが変わった場合に、ちょっとずつ古いimageのpodから更新してくれます。これで安全にdeployできそう。

service.yml
spec:
  selector:
    name: web-server

ここで対象podのlabelを指定しており、podのlabelの名前を対応させることで、serviceとpodが対応付けられます。

readinessProbeとは?死活監視の仕組みをざっと説明します。

死活監視の仕組み

podが生きてるかどうかを、いわゆるロードバランサーの仕組みと同じように内部で監視しています。
各nodeでkubeletという監視等するプロセスが走っており、「調子はどうだい?」とpodに定期的に呼びかけます。死んでた場合にはdeployment(replication controller)により入れ替え・増減されます。

サンプルでは、nginxの設定内部で /readiness.html にアクセスが来たら200を返すようにしてあるので、nginx自体が通常通り稼働していれば、状態がreadyとしてkubeletに認知されます。
これと別にlivenessProbeもありますが今は略。

3.実際に動かしてみる

これらを以下のコマンドで作成しましょう。

kubectl apply -f k8s/deployment.yml
kubectl apply -f k8s/service.yml

これで、deploymentと同時にpodが生成され、serviceが生成されます。作成したもろもろを細かく確認するコマンドとして

kubectl describe {pods|services|deployments} <name>

describegetより細かく確認するコマンドです。うまく作成できてるかserviceにアクセスし…おや…どこにアクセスすればいいのか?

service.yml
spec:
  selector:
    name: web-server
  type: LoadBalancer

イントロダクションではserviceをexposeしてロードバランサーと紐付けましたが、今回はserviceを作成したときにロードバランサーを同時に作っていたのでした。
さっきのようにserviceの外部IPを確認して、アクセスしてみましょう。

スクリーンショット 2016-12-08 16.22.11.png

無事にnginx経由でwebサーバーにアクセスできました!最終的に作成されたものはこんなイメージです。

スクリーンショット 2016-12-08 16.22.11.png

作成したものを消したいときには

kubectl delete <type> <name>

です。例えばkubectl delete pods --allとかやるとpodが全て消えます。deploymentが存在する限り、そのdeploymentが管理するpodは無限に蘇るので、二度とpodが立ち上がらないようにするときはkubectl delete deployments web-serverなどと打ちます。

まとめ

k8sの基本的な使い方について、ざっくり説明してみました。
今回はhttpで行いましたが、httpsも使えます。他にもIngressなど紹介できていない機能がたくさんあります。
省いた説明も大いにあるので、ぜひkubernetes本家のチュートリアルいろいろな入門コンテンツをご参考ください。

日本語の記事がまだまだ少ないので、何かの参考になれば幸いです。

1078
946
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1078
946

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?