Kubernetes
目次
- 1 Kubernetes
- 2 基礎
- 3 Workloadsリソース
- 4 Discovery & LBリソース
- 5 Config & Storage リソース
- 6 Cluster リソース
- 7 Metadataリソース
- 8 minikube
- 9 Kubectl
- 10 Pod
- 11 ReplicaSet
- 12 Deployment
- 13 Docker
Kubernetes
| Docker |
- コンテナ化されたアプリケーションのデプロイ、スケーリングなどの管理を自動化するプラットフォーム(コンテナオーケストレーションエンジン)
- https://knowledge.sakura.ad.jp/20955/
- 信頼性が高くスケーラブルな分散システムを上手に構築してデプロイするために必要なソフトウェアを提供
- 分散システムとは、異なるマシンで動作するAPIを実装する部品の集まり
- マネージドKubernetesサービス(KaaS:Kubernates-as-a-Service)
- Microsoft:Azure Container Service
- Google:Google Kubernetes Engine
宣言的なコードによる管理
- YAMLやJSONの宣言的なマニフェストで、コンテナやリソースを管理できる
スケーリング/オートスケーリング
- コンテナクラスタを形成して、複数のKubernetes Nodeを管理できる
スケジューリング
- コンテナを Kubernetes Nodeにデプロイする際に、どのNodeに配置するかを決定するスケジューリングというステップがある
- コンテナのワークロードの特徴、Kubernetes Nodeの性能差を意識してスケジューリングを行うことができる
リソース管理
- コンテナ配置に特別指定がない場合、自動スケジューリングが行われるため、管理する必要がない
- オートスケール機能により、Kubernetesクラスタの、Kubernetes Nodeの増減も自動で行われる
セルフヒーリング
- 標準でコンテナのプロセス管理を行っており、プロセス停止を検知すると、再度コンテナのスケジュールを行うことで自動的にコンテナを再デプロイする
- プロセス監視以外にも、HTTP・TCPや、シェルスクリプトによるヘルスチェックも可能
サービスディスカバリーとロードバランシング
- ロードバランシング機能(Service)を持っており、事前に指定した条件に合致するコンテナ群に対してルーティングを行う機能を提供する
- コンテナスケール時や、障害時のサービスへの追加、切り離しも自動で行うため、エンドポイント管理をKubernetesに任せることが可能
- コンテナを使用したシステム構築では、マイクロサービスアーキテクチャ採用が一般的、マイクロサービスが相互参照するために、サービスディスカバリー機能が有用
- マイクロサービスを定義されたマニフェストを元にシステム全体を連携させることが可能
データ管理
- バックエンドのデータ管理にetcdを利用している
基礎
- Kubernetes は、Kubernetes Master と Kubernetes Node の2種類のノードからから成り立っている
- Kubernetes Master は、APIエンドポイントの提供コンテナのスケジューリング、コンテナのスケーリングなどを担う
- Kubernetes Node は、Docker ホストに相当し実際にコンテナが稼働するノード
- Kubernetes クラスタを操作するには、kubectl と YAML か JSON 形式のマニフェストファイルを用いて、Kuebrnetes Masterにリソースの登録を行う
- kubectlは、マニフェストファイルの情報を元にKubernetes MasterのAPIにリクエストを送り、Kubernetesの操作を行う
- Kubernetes の API は一般的な RESTful API として実装されている
Kubernetes とリソース
- Kubernetesでは、リソースを登録することで、コンテナの実行やロードバランサの作成が非同期に行われる
Workloadsリソース
- クラスタ上にコンテナを起動するために利用する
- 内部的に利用されているものをのぞき、直接操作するものとしては、以下のリソースがある
- Pod
- ReplicationController
- ReplicaSet
- Deployment
- DaemonSet
- StatefulSet
- Job
- CronJob
Pod
- Workloadsリソースの最小単位
- 一つ以上のコンテナから構成され、ネットワーク的に隔離されておらず、IPアドレスを共有する
- 2つのコンテナが入ったPodを作成した場合、同一IPアドレスを持ち、お互い、localhostで通信できる
- 多くの場合は、1つのPodに1つのコンテナを含めるが、補助するサブコンテナを複数含めることもある
Discovery & LBリソース
- コンテナサービスディスカバリやクラスタの外部からもアクセス可能なエンドポイントなどを提供する
- 利用者が直接利用するものとしては、Service と Ingress があり、Serviceは複数タイプが用意されている
- Service
- ClusterIP
- ExternalIP (ClusterIPの一種)
- NodePort
- LoadBalancer
- Headless (None)
- ExternalName
- None-Selector
- Ingress
Config & Storage リソース
- 設定や機密データをコンテナに埋め込んだり、永続ボリュームを提供する
- Secret と ConfigMap は Key-Value のデータ構造を持ち保存データが機密か一般化によって使い分ける
- Secret
- ConfigMap
- PersistentVolumeClaim
Cluster リソース
- クラスタ自体の振る舞いを定義
- Node
- Namespace
- PersistentVolume
- ResourceQuote
- ServiceAccount
- Role
- ClusterRole
- RoleBinding
- ClusterRoleBinding
- NetworkPolicy
Metadataリソース
- クラスタ内の他のリソースの動作を制御する
- LimitRange
- HorizontalPodAutoscaler
- PodDisruptionBudget
- CustomResourceDefinition
minikube
- https://github.com/kubernetes/minikube
- ローカル開発や学習、テスト用のシンプルなKubernetesシュミレータ
- シングルノードクラスタで、インストールには、ローカルマシンにハイパーバイザーがインストールされていること
- VT-x/AMD-v 仮想化がBIOSで有効化されていること。
- Minikubeを使用してローカル環境でKubernetesを動かす
インストール
Ubuntu + 仮想環境
入手
$ curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 $ sudo +x minkube
インストール
$ sudo install minikube /usr/local/bin
利用
ローカルクラスタの作成
- ローカル仮想マシンを作成
- Kubernetesを設定
- kubectlを設定
> minikube start
- VirtualBox
- Ubuntu+KVM
停止
> minikube stop
クラスタを削除
> minikube delete
ダッシュボード
$ minikube dashboard
Kubernetes Deploymentを作る
- 単純なHTTPサーバーであるechoserverという既存のイメージを使用して、Kubernetes Deploymentを作る
- --portを使用して8080番ポートで公開
$ kubectl create deployment hello-minikube --image=k8s.gcr.io/echoserver:1.10 deployment.apps/hello-minikube created
Deploymentに接続するために、Serviceとして公開
$ kubectl expose deployment hello-minikube --type=NodePort --port=8080 service/hello-minikube exposed
Podが起動しているか確認
$ kubectl get pod NAME READY STATUS RESTARTS AGE hello-minikube-64b64df8c9-jzm5v 1/1 Running 0 11m
公開サービスのURLを確認
$ minikube service hello-minikube --url http://192.168.39.214:31429
クラスタのステータス
- Serverとクライアントのバージョン
$ kubectl version Client Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.8", GitCommit:"9f2892aab98fe339f3bd70e3c470144299398ace", GitTreeState:"clean", BuildDate:"2020-08-13T16:12:48Z", GoVersion:"go1.13.15", Compiler:"gc", Platform:"linux/amd64"} Server Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.3", GitCommit:"2e7996e3e2712684bc73f0dec0200d64eec7fe40", GitTreeState:"clean", BuildDate:"2020-05-20T12:43:34Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}
- クラスタを構成しているコンポーネントを確認
$ kubectl get componentstatus NAME STATUS MESSAGE ERROR controller-manager Healthy ok scheduler Healthy ok etcd-0 Healthy {"health":"true"}
ワーカーノードの表示
- クラスタ上の全のノードを表示
$ kubectl get nodes NAME STATUS ROLES AGE VERSION minikube Ready master 3h13m v1.18.3
ノードの詳細情報
- kubectl describe nodes [ノード名]
基本情報が最初に表示される
Name: minikube Roles: master Labels: beta.kubernetes.io/arch=amd64 beta.kubernetes.io/os=linux kubernetes.io/arch=amd64 kubernetes.io/hostname=minikube kubernetes.io/os=linux node-role.kubernetes.io/master= Annotations: kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.sock node.alpha.kubernetes.io/ttl: 0 volumes.kubernetes.io/controller-managed-attach-detach: true CreationTimestamp: Mon, 05 Aug 2019 23:17:24 +0900 Taints: <none> Unschedulable: false
ノード上で動いているオペレーションの情報が表示される
- それぞれのノードが十分なディスクとメモリを持っているか
- Kubernatesマスターに対して正常であるか
Conditions: Type Status LastHeartbeatTime LastTransitionTime Reason Message ---- ------ ----------------- ------------------ ------ ------- MemoryPressure False Tue, 13 Aug 2019 01:01:05 +0900 Mon, 05 Aug 2019 23:17:15 +0900 KubeletHasSufficientMemory kubelet has sufficient memory available DiskPressure False Tue, 13 Aug 2019 01:01:05 +0900 Mon, 05 Aug 2019 23:17:15 +0900 KubeletHasNoDiskPressure kubelet has no disk pressure PIDPressure False Tue, 13 Aug 2019 01:01:05 +0900 Mon, 05 Aug 2019 23:17:15 +0900 KubeletHasSufficientPID kubelet has sufficient PID available Ready True Tue, 13 Aug 2019 01:01:05 +0900 Mon, 05 Aug 2019 23:17:15 +0900 KubeletReady kubelet is posting ready status Addresses: InternalIP: 10.0.2.15 Hostname: minikube
マシンのキャパシティ情報の表示
Capacity: cpu: 2 ephemeral-storage: 17784772Ki hugepages-2Mi: 0 memory: 2038624Ki pods: 110 Allocatable: cpu: 2 ephemeral-storage: 16390445849 hugepages-2Mi: 0 memory: 1936224Ki pods: 110
ノード上のソフトウェアバージョンの表示
System Info: Machine ID: 7ec5a55cfdc14693866eccf4e9a1228f System UUID: 2C88347D-32CC-4F26-9AEE-1FED259A233C Boot ID: 1da81daa-4519-4f04-afe0-64efecedd7e7 Kernel Version: 4.15.0 OS Image: Buildroot 2018.05.3 Operating System: linux Architecture: amd64 Container Runtime Version: docker://18.9.6 Kubelet Version: v1.15.0 Kube-Proxy Version: v1.15.0
ノード上で動いているPod情報の表示
Non-terminated Pods: (9 in total) Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits AGE --------- ---- ------------ ---------- --------------- ------------- --- kube-system coredns-5c98db65d4-j24hp 100m (5%) 0 (0%) 70Mi (3%) 170Mi (8%) 7d1h kube-system coredns-5c98db65d4-phtm8 100m (5%) 0 (0%) 70Mi (3%) 170Mi (8%) 7d1h kube-system etcd-minikube 0 (0%) 0 (0%) 0 (0%) 0 (0%) 7d1h kube-system kube-addon-manager-minikube 5m (0%) 0 (0%) 50Mi (2%) 0 (0%) 7d1h kube-system kube-apiserver-minikube 250m (12%) 0 (0%) 0 (0%) 0 (0%) 7d1h kube-system kube-controller-manager-minikube 200m (10%) 0 (0%) 0 (0%) 0 (0%) 7d1h kube-system kube-proxy-wrgp5 0 (0%) 0 (0%) 0 (0%) 0 (0%) 7d1h kube-system kube-scheduler-minikube 100m (5%) 0 (0%) 0 (0%) 0 (0%) 7d1h kube-system storage-provisioner 0 (0%) 0 (0%) 0 (0%) 0 (0%) 7d1h Allocated resources: (Total limits may be over 100 percent, i.e., overcommitted.) Resource Requests Limits -------- -------- ------ cpu 755m (37%) 0 (0%) memory 190Mi (10%) 340Mi (17%) ephemeral-storage 0 (0%) 0 (0%) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal NodeHasSufficientMemory 7d1h (x8 over 7d1h) kubelet, minikube Node minikube status is now: NodeHasSufficientMemory Normal NodeHasNoDiskPressure 7d1h (x8 over 7d1h) kubelet, minikube Node minikube status is now: NodeHasNoDiskPressure Normal NodeHasSufficientPID 7d1h (x7 over 7d1h) kubelet, minikube Node minikube status is now: NodeHasSufficientPID Normal Starting 7d1h kube-proxy, minikube Starting kube-proxy. Normal Starting 12m kubelet, minikube Starting kubelet. Normal NodeHasSufficientMemory 12m (x8 over 12m) kubelet, minikube Node minikube status is now: NodeHasSufficientMemory Normal NodeHasNoDiskPressure 12m (x8 over 12m) kubelet, minikube Node minikube status is now: NodeHasNoDiskPressure Normal NodeHasSufficientPID 12m (x7 over 12m) kubelet, minikube Node minikube status is now: NodeHasSufficientPID Normal NodeAllocatableEnforced 12m kubelet, minikube Updated Node Allocatable limit across pods Normal Starting 11m kube-proxy, minikube Starting kube-proxy
クラスタのコンポーネント
- Kubernetesクラスタを構成する多くのコンポーネントが、Kubernetes自体を使ってデプロイされる
- kube-system Namesspace内で動作
Kubernetes proxy
- クラスタ内のロードバランスされたServiceにネットワークトラフィックをルーティング
- クラスタ内の各ノードで動いている必要がある
- DaemonSetというAPIオブジェクトが多くのクラスタではノードでプロキシを動作させるために利用される
Namespace
- クラスタ内のオブジェクトを構造化
- kubectlはデフォルトではdefaultというNamespaceとやり取り
- --namespace で指定できる
Context
- デフォルトのNamespaceを恒久的に変更したい場合
- $HOME/.kube/config に保存される
Kubernetes APIオブジェクトの参照
- Kubernetes上にあるものは、すべてRESTFulリソースであらわされる
- Kubernetes API
- Kubernetes API Reference
Kubectl
- 公式なクライアントは、kubectl
- kubectlを使用してクラスターと対話できるようになります
- Kubernetes APIと連携するコマンドラインツール
- minikube から利用する場合
> minikube kubectl version
kubectlコマンド
- Kubernetesでは、クラスタの操作は全て、Kubernetes Masterの APIを介して行われる
- 手動で操作する場合には、CLIツールの kubectl を利用するのが一般的
- Kubectl が Kubernetes Master と通信するには、接続先サーバー情報や認証情報が必要となる
- デフォルトでは、~/.kube/config に書かれている情報を使用して接続を行う
kubectlインストール
$ curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl $ sudo chmod +x ./kubectl $ sudo install kubectl /usr/local/bin
Pod
- 同じ実行環境上で動くアプリケーションコンテナとストレージボリュームの集まりのこと
- Kubernetesクラスタ上では、コンテナではなくPodがデプロイの最小単位
- 1つのPodないのコンテナは全て同じマシン上に配置される
- 同じPod内のアプリケーションは、ネイティブなプロセス間通信チャネルで通信できるが、異なるPodのアプリケーションからは分離されている
Pod単位で考える
- WordPressとMySQLを同じPodに入れれば良いと考えるのはアンチパターンの1つ
- それぞれ別マシンで通信できればよく、WordPressとDBが同じ単位としてスケールする可能性も低い
- WordPress自体はステートレスなため、負荷が増大した場合、WordPressのPodを増やしてスケールさせれば良い
- 通常は、Podを作る際に、コンテナが異なるマシンに配置されても正常に動作するかという点が判断基準
設定
- 設定を行う箇所は、clusters,contexts,users
- YAML もしくは JSONフォーマット
- 直接編集するだけでなく、kubectlから変更も可能
- https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#pod-v1-core
apiVersion: v1 clusters: - cluster: certificate-authority: /home/piroto/.minikube/ca.crt server: https://192.168.39.214:8443 name: minikube contexts: - context: cluster: minikube user: minikube name: minikube current-context: minikube kind: Config preferences: {} users: - name: minikube user: client-certificate: /home/piroto/.minikube/profiles/minikube/client.crt client-key: /home/piroto/.minikube/profiles/minikube/client.key
マニフェストとリソースの作成
- sample-pod.yaml
apiVersion: v1 kind: Pod metadata: name: sample-pod spec: containers: - name: nginx-container image: nginx:1.12
実行
- apply コマンドを利用すると、存在しなければ生成、更新があれば更新、変更なければ何もしないという挙動
$ kubectl create -f sample-pod.yaml pod/sample-pod created
- 確認
$ kubectl get pod NAME READY STATUS RESTARTS AGE sample-pod 1/1 Running 0 42s
$ kubectl apply -f sample-pod.yaml pod/sample-pod configured
アノテーションとラベル
- 各リソースに対してアノテーションとラベルというメタデータを付与することができる
名称 | 概要 |
---|---|
アノテーション | システムコンポーネントが使用するメタデータ.アノテーションを元に処理するシステムコンポーネントが存在しない場合は単なるメモ |
ラベル | リソース管理に利用するメターデータ.リソースを分別するための情報 |
- ユーザーがアノテーションを付与せず作成したリソースでも、下記のように様々なアノテーションが付与される
$ kubectl get deployments -o yaml hello-minikube apiVersion: apps/v1 kind: Deployment metadata: annotations: deployment.kubernetes.io/revision: "1" creationTimestamp: "2020-08-22T08:02:54Z" :
- アノテーションとラベルをマニフェストに追記
apiVersion: v1 kind: Pod metadata: name: sample-pod annotations: annotation1: val1 annotation2: val2 labels: label1: lab1 label2: lab2 spec: containers: - name: nginx-container image: nginx:1.19
- 表示の拡張
$ kubectl get pod --output wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES sample-pod 1/1 Running 2 24h 172.17.0.3 minikube <none> <none>
- ダッシュボードに表示された
2つのコンテナを内包したPod
- マニフェスト sample-2pod.yaml
apiVersion: v1 kind: Pod metadata: name: sample-2pod spec: containers: - name: nginx-container image: nginx:1.19 - name: radis-container image: redis:6.0.7
- 適用
$ kubectl apply -f sample-2pod.yaml pod/sample-2pod created
- 結果確認
$ kubectl get pod --output wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES sample-2pod 2/2 Running 0 7m40s 172.17.0.6 minikube <none> <none> sample-pod 1/1 Running 2 2d 172.17.0.3 minikube <none> <none>
コンテナへのログインとコマンド実行
- -t 疑似端末(TTY)を生成し、-i 標準入力をコンテナに渡す
- /bin/bashコマンドを実行する
$ kubectl exec sample-pod -i -t -- /bin/bash root@sample-pod:/#
ReplicaSet
- Podのレプリカを作成するリソース
- レプリカ数=3でスケールさせたReplicaSet
apiVersion: apps/v1 kind: ReplicaSet metadata: name: sample-rs spec: replicas: 3 selector: matchLabels: app: sample-app template: metadata: labels: app: sample-app spec: containers: - name: nginx-container image: nginx:1.19 ports: - containerPort: 80
*作成
$ kubectl apply -f sample-rs.yaml replicaset.apps/sample-rs created
- 確認
- Podが3つ起動していることが確認できる
$ kubectl get pods --output wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES sample-2pod 2/2 Running 0 26h 172.17.0.6 minikube <none> <none> sample-pod 1/1 Running 2 3d2h 172.17.0.3 minikube <none> <none> sample-rs-9gxzs 1/1 Running 0 3m14s 172.17.0.7 minikube <none> <none> sample-rs-nsn86 1/1 Running 0 3m14s 172.17.0.9 minikube <none> <none> sample-rs-wcjsv 1/1 Running 0 3m14s 172.17.0.8 minikube <none> <none>
- ダッシュボードで確認
Deployment
- 複数のReplicaSetを管理することで、ローリングアップデートやロールバックを実現するリソース
- フロー
- 新しいReplicaSetを作成
- 新しいReplicaSetのPod数を徐々に増やす
- 古いReplicaSetのPod数を徐々に減らす
- 上記を繰り返す
- 古いReplicaSetのレプリカ数を0で保つ
Docker
Dockerデーモンの再利用によるローカルイメージの使用
- Dockerデーモンの再利用によるローカルイメージの使用
- Mac/LinuxのホストでDockerデーモンを操作できるようにするには、minikube docker-envを実行
- MinikubeのVM内のDockerデーモンと通信しているホストのMac/LinuxマシンのコマンドラインでDockerを使用できるようになる
$ minikube docker-env export DOCKER_TLS_VERIFY="1" export DOCKER_HOST="tcp://192.168.39.214:2376" export DOCKER_CERT_PATH="/home/piroto/.minikube/certs" export MINIKUBE_ACTIVE_DOCKERD="minikube" # To point your shell to minikube's docker-daemon, run: # eval $(minikube -p minikube docker-env)
$ docker ps Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.40/containers/json: dial unix /var/run/docker.sock: connect: permission denied
$ sudo groupadd docker $ sudo gpasswd -a `id -un` docker $ sudo chgrp docker /var/run/docker.sock
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
© 2006 矢木浩人