はじめに
こんにちは。ラクマでサーバーサイドエンジニアをやっているYuです。 このあいだ半年ぶりに出社したら、強いノスタルジーを感じてしまいました。
業務時間の10%を委員会活動に使えるのですが、私は半年以上KubernetesなどのCNCFのプロジェクトを触っていました。 今回は、そこで学んだ内容をもとにKubernetesについてお話したいと思います。Kubernetesという言葉を聞いたことはあるけれども触ったことはない、ぐらいの方をターゲットにしています。
目次
- Kubernetesについて
- Kubernetesを触ってみる
Kubernetesについて
Kubernetesとは?
公式ドキュメントをみると、以下のようにあります。
Kubernetesは、宣言的な構成管理と自動化を促進し、コンテナ化されたワークロードやサービスを管理するための、ポータブルで拡張性のあるオープンソースのプラットフォームです。 https://kubernetes.io/ja/docs/concepts/overview/what-is-kubernetes/
これはちょっと抽象的です。私は以下のように考えます。
- コンテナ実行環境
- PodをはじめとしたリソースをRestAPIで操作できる
- 宣言した理想状態を保つように、オートリカバリやオートスケールが行われる
コンテナ実行環境
これはほとんどの人が納得できることと思います。
PodをはじめとしたリソースをRestAPIで操作できる
Podとは、ネットワークとストレージを共有し、密接に結合したコンテナのグループのことです。 KubernetesのAPIによって、Podを含むインフラのリソースをRestAPIで操作することができます。 なので、操作がわかりやすく、使いやすいです。
宣言した理想状態を保つように、オートリカバリやオートスケールが行われる
Kubernetesでは、マニフェストファイルというものを書きます。 そのマニフェストファイルに宣言されている状態を保つようにオートリカバリやオートスケールが行われます。
Kubernetesの構成
次に中身をみてみましょう。
Khtan66 - 投稿者自身による作品, CC 表示-継承 4.0, https://commons.wikimedia.org/w/index.php?curid=53571935による上半分の緑色がコントロールプレーン、下半分の青色がデータプレーンになります。 開発者はコントロールプレーンに向けてRestAPIを叩き、データプレーンのリソースが操作されます。 たとえば、nginxのPodを3つ作りたいとAPIを叩けば、データプレーン上にnginxのPodが3つ作成されます。
Podには内部IPアドレスが割り当てられます。 Podは作られたり壊されたりとせわしなく変化するので、適切にPodにアクセスするためには、抽象化が必要になります。 その抽象化を担うのがServiceです。以下の図がわかりやすいです。
Marvin The Paranoid - 投稿者自身による作品, CC 表示-継承 4.0, https://commons.wikimedia.org/w/index.php?curid=75140812による
PodへのアクセスはService Xによって抽象化されていることがわかります(PodへのアクセスはすべてService Xを経由しています)。
Kubernetesを触ってみる
それでは少し触ってみたいと思います。 minikubeというローカル環境用のクラスタを使いたいと思います。 動作確認しているバージョンは以下になります。
minikube: v1.12.3 kubectl-client-version: v1.18.3 kubectl-server-version: v1.18.3
環境構築については、公式ドキュメントを参照してください。 kubernetes.io
環境構築ができたら、はじめましょう。minikubeを起動しておいてください。
$ minikube start
先ほど、マニフェストファイルというものを書きます、と話していました。 まずはこれを作ってみましょう。ターミナルで以下を実行してください。
$ kubectl create deployment hello-minikube --image=k8s.gcr.io/echoserver:1.10 –dry-run –o yaml > deployment.yml
このコマンドの意味はこうです。
- createします
- deploymentを(deploymentは同一のPodを複数集めたものとお考えください)
- hello-minikubeという名前で
- k8s.gcr.io/echoserver:1.10というDockerイメージから
- dry runしてyamlファイルにアウトプットします
これでマニフェストファイルができました。中身は以下のようになっているはずです。(バージョンによって多少内容は異なります)
apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null labels: app: hello-minikube name: hello-minikube spec: replicas: 1 selector: matchLabels: app: hello-minikube strategy: {} template: metadata: creationTimestamp: null labels: app: hello-minikube spec: containers: - image: k8s.gcr.io/echoserver:1.10 name: echoserver resources: {} status: {}
なんとなく、コマンドの内容とマニフェストの内容の関係性を確認できると思います。
今回はせっかくなので、replicas: 3
にしておきましょう。これでPodが3つ作成されるようになります。
... spec: replicas: 3 selector: ...
これでdeployment(Podの集合)のマニフェストファイルは完成です。まずはこれをデプロイしてみましょう。
$ kubectl apply -f deployment.yml
確かにデプロイできていることは以下で確認できます。
$ kubectl get pods NAME READY STATUS RESTARTS AGE hello-minikube-64b64df8c9-4dxpc 1/1 Running 0 4s hello-minikube-64b64df8c9-jgmch 1/1 Running 0 4s hello-minikube-64b64df8c9-nhc67 1/1 Running 0 4s
次に、このPodを公開するためのServiceを作成しましょう。先ほどと同様に以下コマンドを実行してください。
kubectl expose deployment hello-minikube --type=LoadBalancer --port=8080 –dry-run –o yaml > service.yml
type=LoadBalancer
とありますが、これはPodをKubernetesクラスタの外部に公開するときに使うServiceになります。
これでマニフェストファイルができました。中身は以下のようになっているはずです。(バージョンによって多少内容は異なります)
apiVersion: v1 kind: Service metadata: creationTimestamp: null labels: app: hello-minikube name: hello-minikube spec: ports: - port: 8080 protocol: TCP targetPort: 8080 selector: app: hello-minikube type: LoadBalancer status: loadBalancer: {}
では、以下のコマンドを実行してServiceもデプロイしましょう。
$ kubectl apply -f service.yml
確かにデプロイできていることは以下で確認できます。
$ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE hello-minikube LoadBalancer 10.99.50.109 <pending> 8080:30182/TCP 11s
それでは最後に、デプロイしたPodにアクセスしてみましょう。以下を実行してください。 ブラウザが開き、Pod内のechoサーバーへのアクセスができるはずです。
$ minikube service hello-minikube
おまけ
せっかくなので少し遊んでみましょう。
以下スクリプトを実行してみると、3つのPodへアクセスがロードバランシングされていることを確認できます。
(実行時の第一引数にminikube service
コマンドで表示されたURIを渡してください。例: http://127.0.0.1:58183
)
#!/bin/sh URL=$1; while true; do sleep 1; curl -s $URL | grep Hostname done
このスクリプトを実行したまま、Podを削除してみると、Pod数を3に維持しながらロードバランシングされていることも確認できます。 Podの削除は以下のコマンドです。
$ kubect delete pods <PodのNAME>