こちらの記事は、Jonathan Natanael Siahaan 氏により2019年 10月に公開された『 Step by Step Introduction to Basic Concept of Kubernetes 』の和訳です。
本記事は原著者から許可を得た上で記事を公開しています。
Kubernetesを聞いたことがありますか?
興味があることは間違いないはずです。
だからこそこの記事を開いたのでしょう。
この記事では、Kubernetesの基本概念とその使い方について説明します。
最終的には、Minikube上で動くKubernetesを使用してdockerコンテナを動かします。
クラウドの有料アカウントは必要ありません。
Kubernetesとは何か?
Kubernetesは、Googleが作成したオープンソースのプラットフォーム/ツールです。
GO-Langで書かれています。
そのため、現在KubernetesはApache 2.0ライセンスの下でのオープンソースプロジェクトとなっています。
業界では、Kubernetesは「K8s」としても知られています。
Kubernetesを使うと、プライベート、パブリック、およびハイブリッドクラウド環境で任意のLinuxコンテナを動かすことができます。
Kubernetesは、ロードバランサー、サービスディスカバリー、ロールベースアクセス制御(RBAC)などの周辺機能も提供します。
(訳注)サービスディスカバリーとは、サービスとIPを紐づける機構のこと。これによりコンテナの作成・削除に伴ってIPが変わっても通信が可能となる。
なぜKubernetesが必要なのか?
答えは、コンテナの管理を支援するためです。
多くのコンテナを使用しマイクロサービスパターンで本番環境を運用する場合、多くのことを確認する必要があります。
ヘルスチェック、バージョン管理、スケーリング、ロールバック機構など。
これら全てが正常であることを確認するのは非常にイライラするでしょう。
Kubernetesは、コンテナを大規模にデプロイするために必要なオーケストレーションおよび管理機能を提供します。
Kubernetesのオーケストレーション機能を使用すると、複数のコンテナにまたがるアプリケーションサービスを構築し、クラスター全体でそのコンテナのスケジューリング、コンテナのスケーリング、そしてコンテナの状態を管理し続けることができます。
一言で言えば、Kubernetesは多くの部下(コンテナ)を持つマネージャーのようなものです。
マネージャーのすることは、部下が実施する必要のあることを、できるように取り計らうことです。
Kubernetesを使用する前に、新しいマイクロサービスをデプロイするためのインフラを用意する必要があります。
これには数日から数週間かかるでしょう。
Kubernetesが無かったら、大規模なチームはデプロイフローを手動でスクリプト化しなければならないでしょう。
Kubernetesがあると、デプロイスクリプトを手動で作成する必要が無くなり、DevOpsに費やす時間とリソースが減ります。
Kubernetesの主な機能:
- 水平スケーリング
- 自動スケーリング
- ヘルスチェック&自己修復
- ロードバランサー
- サービスディスカバリー
- 自動ロールバック&ロールアウト
- カナリアデプロイ
(訳注)一部のユーザにのみ展開する手法のこと。
Kubernetesはどう動いているのか?
公式ドキュメントを読んでKubernetesを始めると、用語が多く出てきて圧倒されるかもしれません。
概念をより深く理解するには、概要が必要な場合があります。
ここでは、Kubernetesアーキテクチャの完全な概要図を示します。
お役に立てば幸いです。
デプロイの流れ:
DevOps -> API Server -> Scheduler -> Cluster ->Nodes -> Kubelet -> Container Engine -> Pod内にコンテナ作成
アプリユーザーのリクエストの流れ:
App user -> Kube proxy -> Pod -> Container(ここでアプリが動きます)
Kubernetesのアーキテクチャ図
図を見るとわかるように、理解できない用語が多くあります。一つづつ説明します。
Master
Masterは、クラスターを制御する要素です。
Masterには3つの要素があります。
- API Server: RESTfulインターフェイスを通じてKubernetesの機能を提供し、クラスターの状態を保持するアプリケーション。
-
Scheduler: Schedulerは新しいPod要求を受けつけるためにAPI Serverを監視します。
Nodeと通信して新しいPodを作成し、リソースを割り当てたり制約を課しながらNodeにタスクを割り当てます。 -
Controller Manager: Controllerを動かすMaster上の要素。
Node controller、Endpoint Controller、Namespace Controllerなどが含まれます。
Slave(Node)
この機構は、要求され割り当てられたタスクを実行します。
KubernetesのMasterがそれらを制御します。Node内には4つの要素があります。
-
Pod: 全てのコンテナはPod内で動きます。
Podは、内部にあるコンテナからネットワークとストレージを抽象化します。
アプリはここで動きます。 -
Kubelet: KubeletはNodeをクラスターに登録し、Schedulerからのタスク割り当てを監視し、新しいPodをインスタンス化し、Masterに報告します。
(訳注)原文では「Kubectl registering ...」とあり、Kubectlが出てきていますが、誤記と思われるため、「Kubelet registering ...」と解釈し翻訳しています。なお、KubectlはKubernetesのCLIツールです。 - Container Engine: コンテナの管理、イメージのプル、コンテナの停止、コンテナの起動、コンテナの削除などを担当します。
-
Kube Proxy: アプリユーザーのリクエストを適切なPodに転送します。
退屈だと思うので、ここでは詳細な概念は説明しませ ん。
この記事はもっとざっくりで楽しいはずです。
詳細については、公式ドキュメントをご覧ください。
こちらをクリックしてください。
DockerとKubernetesのハンズオン
そろそろ手を動かしてみましょう。
このセクションでは、Github上の既存のdockerプロジェクトを使用し、Kubernetesに焦点を当てます。
Minikubeを使用します。
Minikubeは、Kubernetesをローカルで簡単に動かせるツールです。
-
Minkubeのインストール
このMinikube公式インストールドキュメントに従って実施してみてください。 -
以下の手順に従ってください
Minikubeを起動してクラスターを作成します
minikube start
ローカルの作業ディレクトリ内にこのリポジトリをクローンします
git clone https://github.com/buildkite/nodejs-docker-example.git
ご自身のDockerクライアントがMinikubeのDockerデーモンを指すようにします
eval $(minikube docker-env)
上記でクローンしたリポジトリのディレクトリに移動します。
cd nodejs-docker-example
このコマンドを使用してDockerイメージを作成し、ローカルで動かせることを確認します。
docker build -t example-node-app .
Dockerイメージが正常に作成されたことを確認します。
docker images
example-node-app
という名前の既存の イメージを使ってKubernetes Deploymentを作成しましょう。そのイメージは簡易なNodeのHTTPサーバーで、3000番ポートで公開します。
ファイルを作成し、deployment-script.yaml という名前にします。
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: kubernetes-deployment
namespace: default
labels:
app: node-app
spec:
replicas: 1
selector:
matchLabels:
app: node-app
template:
metadata:
labels:
app: node-app
spec:
containers:
- name: node-app-container
image: example-node-app
resources: {}
imagePullPolicy: IfNotPresent
restartPolicy: Always
terminationGracePeriodSeconds: 30
terminationGracePeriodSeconds: 30
それから
kubectl apply -f deployment-script.yaml
これでnode-app Podが起動し、node-appコンテナ がPod内で動きますが、公開Service経由でアクセスするには、Podが立ち上がるまで待つ必要があります。
Podが立ち上がっているかどうかを確認します:
kubectl get pod
Podが立ち上がって、動いています
NAME READY STATUS RESTARTS AGE
node-app-3383150820-vctvh 1/1 Running 0 13s
喜ぶのはまだ早いです。
ここで終わりではありません。
Podにアクセスするには、サービスプロキシが必要です。
ロードバランサーサービスを作成し、targetPort(宛先ポート):3000、port(ユーザーへの公開ポート):8000とします。
下記内容でnode-app-service.yaml
というファイルを作成します。
kind: Service
apiVersion: v1
metadata:
name: node-app-service
namespace: default
labels:
app: node-service
spec:
ports:
- protocol: TCP
port: 8000
targetPort: 3000
selector:
app: node-app
type: LoadBalancer
sessionAffinity: None
externalTrafficPolicy: Cluster
status:
loadBalancer: {}
実行:
kubectl apply -f node-app-service.yaml
サービスに関する情報を取得するには:
kubectl get service
これが表示されます:
NAME Type EXTERNAL-IP PORT(S) AGE
node-app-service LoadBalancer <pending> 8000:31386/TCP 36m
サービスを作成した後、クラウドインフラを使っている場合は、ロードバランサーを作成して、そのIPアドレスをServiceオブジェクトに書き込むのには時間がかかります。
さて、時間が経っても 外部IP がまだ保留になっているのはなぜでしょう?
ロードバランサーサービス をサポートしない環境でKubernetesが動いている場合、ロードバランサーは作成されません。
その場合、サービスに付与できるIPが必要です。
Minikube IPを使用できます。
minikube ip
表示されたMinikube IPをコピーし、EXTERNAL-IPサービスに付与します
kubectl patch svc node-app-service -p '{"spec": {"type": "LoadBalancer", "externalIPs":["YOUR_MINIKUBE_IP"]}}'
サービスに関する情報の表示:
kubectl get service
結果:
NAME Type EXTERNAL-IP PORT(S) AGE
node-app-service LoadBalancer 192.168.99.100 8000:31386/TCP 36m
これで、そのIPアドレスでサービスにアクセスするか、Webブラウザーでアクセスできます。
curl 192.168.99.100:8000
補足
Kubernetesクラスターを表示するインタラクティブなUIが必要ですか?
ダッシュボードUIはデフォルトでは入っていません。入れるには:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta4/aio/deploy/recommended.yaml
デフォルトでは、Kubernetesダッシュボードのユーザーは権限が制限されています。
このセクションでは、管理者レベルの権限でダッシュボードに安全に接続するのに使用する、eks-admin
というサービスアカウントとクラスタロールバインディングを作成します。
下記内容でeks-admin-service-account.yaml
というファイルを作成します。
このマニフェストは、eks-admin
というサービスアカウントとクラスターロールバインディングを定義しています。
apiVersion: v1
kind: ServiceAccount
metadata:
name: eks-admin
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: eks-admin
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: eks-admin
namespace: kube-system
サービスアカウントとクラスターロールバインディングをクラスターに適用します。
kubectl apply -f eks-admin-service-account.yaml
eks-admin
サービスアカウントの認証トークンが必要です。
出力結果から<authentication_token>
の値をコピーします。このトークンを使用して、ダッシュボードに接続します。
kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep eks-admin | awk '{print $1}')
出力結果:
Name: eks-admin-token-b5zv4
Namespace: kube-system
Labels: <none>
Annotations: kubernetes.io/service-account.name=eks-admin kubernetes.io/service-account.uid=bcfe66ac-39be-11e8-97e8-026dce96b6e8
Type: kubernetes.io/service-account-token
Data
====
ca.crt: 1025 bytes
namespace: 11 bytes
token: <authentication_token>
kubectlコマンドラインツールで次のコマンドを実行して、ダッシュボードにアクセスできます。
kubectl proxy
Tokenを選択し、前のコマンド出力結果の<authentication_token>
の値をTokenフィールドに貼り付けて、SIGN INを選択します。
参考文献
Kubernetes Documentation
Amazon EKS
やったね、これで終わりです🤗
楽しんでいただけましたでしょうか。
下にコメントをください。
問題が発生した場合は、コメントを残してください。対応いたします😉
このリポジトリhttps://github.com/contentful/the-example-app.nodejsを作成した方に感謝します。この記事の中でサンプルアプリとして使用することができました。
また別の記事でお会いしましょう!
関連記事
翻訳協力
Original Author: Jonathan Natanael Siahaan
Thank you for letting us share your knowledge!
この記事は以下の方々のご協力により公開する事が出来ました。
改めて感謝致します。
選定担当: yumika tomita
翻訳担当: @satosansato3
監査担当: @nyorochan
公開担当: asuma yamada
ご意見・ご感想をお待ちしております
今回の記事は、いかがだったでしょうか?
・こうしたら良かった、もっとこうして欲しい、こうした方が良いのではないか
・こういったところが良かった
などなど、率直なご意見を募集しております。
いただいたお声は、今後の記事の質向上に役立たせていただきますので、お気軽にコメント欄にてご投稿ください。
みなさまのメッセージをお待ちしております。