2020年5月17日日曜日

Kubernete(クバネティス、クーべネティス)とは。Kuberneteをローカルで動かしてみる。

前提

以下のLinux環境を使用。Windows環境の人はminikubeインストールのページに一応Windowsに入れる方法も書いてあるので確認してください。

  • OS: ubuntu 18.04.2 LTS

Kubernetesとはなにか?

Kubernetesはコンテナオーケストレーションのツールです。Googleによって開発されました。Kubernetesはコンテナ化されたワークロード・サービスを運営するためのプラットフォームツールとも言えます。Wikipediaもわかりやすいので見るといいかも。
Kubernetesとはポータブルで拡張の容易なオープンソースのプラットフォームです。コンテナ化されたワークロード・サービスを運営するためのもので、宣言的な設定とオートメーションの両方を使用します。Kubernetesは大規模で、早い成長を見せているエコシステムが備わっています。Kubernetesのサービス・サポート・ツール等は広く利用可能です。
-- Kubernetes https://kubernetes.io/docs/concepts/overview/what-is-kubernetes/

公式のチュートリアル

もしminikubeをインストールしたくなければ、Google公式のチュートリアルがオンラインで利用可能です。こちらからどうぞ。ただし英語版です。日本語版は探したけど2020年5月現在見つからなかったです。

Minikube

さて別にオンラインのチュートリアルは使いたくない、もしくはすでにチュートリアル実行済みで、ローカルで実際にKubernetesを体験したい場合はどうすればいいでしょうか。そんなときに使うのがMinikubeです。Minikubeは公式ページで以下のように説明されています。
MinikubeはKubernetesをローカルで簡単に実行するためのツールです。MinikubeはシングルノードのKubernetesを仮想マシン内で動かします。MinikubeはKubernetesをローカルで試してみたいユーザー、または日々の開発に利用したいユーザーが使うことを意図しています。
-- Kubernetes https://kubernetes.io/docs/setup/learning-environment/minikube/

「Docker(+コンテナ)」と「Vagrant」を比較

私はVagrantで作る仮想マシンが(簡単に作れるので)好きなのですが、最近はDockerで環境を作るプロジェクトのほうが多くなりました。理由は簡単でDockerで仮想マシンを作るほうが本番デプロイや運用が楽だからです。(以前の私みたいに)「え?どっちも仮想環境を作るためのものでしょ?何が違うの?」という考えの人もいると思います。確かにどちらも仮想環境を作るためのものですがその目的が違います。これはKubernetesのコンテナの理解にも関わるので説明します。

まずVagrantは開発時に使う仮想マシンを作成するためのものです。その目的は「本番環境と大体同じ環境を仮想的に開発用マシンのなかに作る」です。要は本番環境とそっくりな環境を開発者のPCの中に作りたいわけですね。そうやって仮想環境を作り、そのなかで動かしながら開発することで本番デプロイ時に環境差異によって起こる問題を最小限にしようとします。

対してDockerは開発環境でも本番環境でも両方で使うことを意図しています。まずDockerというベースの上で動くコンテナ単位で開発します。例えばApacheもしくはNginx用コンテナ、アプリ用コンテナ、DB(MySQLとか)用コンテナ、というように1コンテナ1プロセスで開発します。開発が終わったら本番環境のDockerでこれらのコンテナを動かすだけです。このように1つの目的で複数コンテナを束ねて使うことをコンテナのオーケストレーションといい、通常はDocker-compose(もしくはKubernetes)を使って実現します。

開発・本番どちらの環境でもDocker上の仮想環境(コンテナ)で動かすことで、環境差異を最小限にしますし、さらにデプロイも開発で使用したDocker imageをDockerhubを経由しそのまま本番環境で使うだけなので簡単にできます。さらに作成したコンテナを別の(Dockerを利用する)プロジェクトで使うなんてことも可能です。この意味でポータブルな環境だということもできます。

ときどきDockerを開発環境でのみ使うプロジェクトもありますが、それはDockerのほうがAnsible+Vagrantより軽いから、あるいは単純にDockerよくわかんないけど話題だから使ってみようぜ等の理由から使っているのでしょう。

「Kubernetes」,「Docker-compose」,「Docker Swarm」を比較

Kubernetesは複数ホスト間でコンテナを起動、互いに接続するためのもので、それらコンテナがクラスターという単位で管理されます。それぞれのノードは仮想マシンもしくは物理的なマシンであり、クラスタ内でワーカーマシンとして機能します。詳しくはこの説明(ただし英語)を参照

平たく言えば、単一ホストで複数コンテナのオーケストレーションをするのが「Docker-compose」です。複数ホスト間で複数コンテナのオーケストレーションをするのが「Docker Swarm」もしくは「Kubernetes」になります。
以下のスタックオーバーフローが参考になると思います。
What's the difference between docker compose and kubernetes? - stackoverflow

minikubeを使ってみよう

minikubeをインストール

Kubernetes公式のこのページに詳しくわかりやすくminikubeインストール方法が書いてあります。

minikubeとkubectlを使ってみる

このコマンドを実行するとminikubeを起動することができます。ただし「前提」でもいいましたが、筆者はLinux(Ubuntu)環境で実行しているためご注意。
$ minikube start
すると以下のような起動メッセージが表示されます。
さあ「kubectl」をローカルで使用するための準備が整いました。ちなみにKubectlというのはKubernetesクラスターをコントロールするためのコマンドラインツールです。

試しにnginxサービスを作ってみる

kubectlで試しにコンテナイメージ「nginx:1.7.9」を利用してKubernetesクラスターにnginxをデプロイしてみましょう。
最初にマスターノードが動いていることを確認します。
$ kubectl get all 
NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   3d7h
動いていることが確認できたらローカル環境のどこかにyamlファイルを作成、以下のように書きます。これらはデプロイとデプロイされるサービス(nginx)を定義するものです。

nginx_deploy.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    name: nginx
spec:
  selector:
    matchLabels:
      name: nginx
  replicas: 2 # tells deployment to run 2 pods matching the template
  template:
    metadata:
      labels:
        name: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80
nginx_service.yml
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    name: nginx
spec:
  type: NodePort
  ports:
    - port: 80
      nodePort: 30080
      name: http
  selector:
    name: nginx
書き終わったら保存して以下のコマンドを実行します。
$ cd (yamlファイルを保存したディレクトリ)
$ kubectl apply -f ./nginx_deploy.yml  -f ./nginx_service.yml

nginxが動いているかブラウザから確認

minikube IPを以下のコマンドで確認しましょう。
$ minikube ip
192.168.99.100
以下のコマンドでポートナンバーを確認します
$ kubectl describe service/nginx
Name:                     nginx
Namespace:                default
Labels:                   name=nginx
Annotations:              kubectl.kubernetes.io/last-applied-configuration:
                            {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"name":"nginx"},"name":"nginx","namespace":"default"},"spec":{"...
Selector:                 name=nginx
Type:                     NodePort
IP:                       10.111.250.254
Port:                     http  80/TCP
TargetPort:               80/TCP
NodePort:                 http  30080/TCP ####ポートナンバーここ!!!!!!!####
Endpoints:                172.17.0.4:80,172.17.0.5:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>
上記で確認したIPアドレス+ポートナンバーをブラウザに打ち込みます。すると以下のような画面がでてnginxが(yamlで指定したクラスタ内で)起動していることが確認できます。
確認ができたらデプロイとサービスを以下のコマンドで削除することができます。
$ kubectl delete service/nginx deployment.apps/nginx-deployment
$ kubectl get all