Kubernetes
ナビゲーションに移動
検索に移動
| Docker | Docker コマンド | Docker ネットワーク | WSL | MicroK8s | Multipass |
目次
Kubernetes
- https://kubernetes.io/ja/
- コンテナ化されたアプリケーションのデプロイ、スケーリングなどの管理を自動化するプラットフォーム(コンテナオーケストレーションエンジン)
- https://knowledge.sakura.ad.jp/20955/
- 信頼性が高くスケーラブルな分散システムを上手に構築してデプロイするために必要なソフトウェアを提供
- 分散システムとは、異なるマシンで動作するAPIを実装する部品の集まり
- マネージドKubernetesサービス(KaaS:Kubernates-as-a-Service)
- Microsoft:Azure Container Service
- Google:Google Kubernetes Engine
チートシート
コンポーネント構成
- https://kubernetes.io/docs/concepts/overview/components/
- https://www.slideshare.net/yokawasa/istio-114360124 から引用
宣言的なコードによる管理
- 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クラスターは以下の2種類のリソースで構成
- マスターがクラスターを管理する、マスターはクラスターの管理を担当
- ノードがアプリケーションを動かすワーカーとなる、ノードは、Kubernetesクラスターのワーカーマシンとして機能するVMまたは物理マシン
Kubelet
- 各ノードにはKubeletがあり、これはノードを管理し、Kubernetesマスターと通信するためのエージェント
デプロイ
Kubernetesにアプリケーションをデプロイするときは、
- マスターにアプリケーションコンテナを起動するように指示
- マスターはコンテナがクラスターのノードで実行されるようにスケジュール
- ノードは、マスターが公開しているKubernetes APIを使用してマスターと通信
- エンドユーザーは、Kubernetes 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
Service | 内容 |
---|---|
ClusterIP | |
ExternalIP (ClusterIPの一種) | |
NodePort | |
LoadBalancer | |
Headless (None) | |
ExternalName | |
None-Selector |
- Ingress
KubernetesクラスタのネットワークとService
Kubernetesが構成するネットワーク
- Pod内には複数のコンテナを内包できるが、同じPodであれば、同一IPが割り振られている
- 同一Podコンテナへ通信を行う場合は、localhostあてに通信を行い、Podのコンテナから別Podコンテナへ通信を行う場合には、PodのIPアドレス宛に通信を行う
- Kubernetesクラスタは、クラスタを構成するとノードにPodのための内部ネットワークを自動的に構成する
- 基本的にはノードごとに異なるネットワークセグメントを互いに通信できるよう構成する
- このような内部ネットワークが自動構成されるため、PodはServiceを利用しなくてもPod間通信を行うことが可能
Serviceを利用することによるメリット
- Podあてトラフィックのロードバランシング
- サービスディスカバリとクラスタ内DNS
- これらは、上記のどのService Typeからも利用できる
Pod宛トラフィックのロードバランシング
- Serviceは、複数のPodにロードバランシングを行う
- Serviceを利用すると、各PodのIPを毎回調べたり、宛先を設定するなど独自に実現しなくても、自動的に構成することができる
- Serviceは、ロードバランシングのエンドポイントも提供する
- 外部ロードバランサーが払い出す仮想IP(Virtual IPアドレス)、クラスタ内のみで利用可能な仮想IPアドレス(ClusterIP)など
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
MicroK8s
Kubectl
Namespace
- Kubernetesは、同一の物理クラスター上で複数の仮想クラスターの動作をサポートします。 この仮想クラスターをNamespaceと呼びます
- 作成:kubectl create namespace <名称>
- 削除:kubectl delete namespace <名称>
$ kubectl create namespace sample namespace/sample created $ kubectl get namespaces NAME STATUS AGE kube-system Active 66d kube-public Active 66d kube-node-lease Active 66d default Active 66d sample Active 4s
Pod
- https://kubernetes.io/ja/docs/concepts/workloads/pods/
- 同じ実行環境上で動くアプリケーションコンテナとストレージボリュームの集まりのこと
- 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>
- ダッシュボードに表示された
Podの削除
$ kubectl delete -f sample-pod.yaml pod "sample-pod" deleted
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
- https://kubernetes.io/ja/docs/concepts/workloads/controllers/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
- https://kubernetes.io/ja/docs/concepts/workloads/controllers/deployment/
- 複数のReplicaSetを管理することで、ローリングアップデートやロールバックを実現するリソース
- Kubernetesで最も推奨されるコンテナの起動方法
- 1つのコンテナでもDeploymentを使用すべき
- Deploymentは新しいバージョンのリリースを管理する仕組み
- デプロイされたアプリケーションをバージョンをまたいで表現する
- Pod単体では自動で再起動されないし、ReplicaSetでは、ローリングアップデートが利用できない
- PodもReplicaSetも変更されないコンテナイメージを取り扱うために作られている
- フロー
- 新しいReplicaSetを作成
- 新しいReplicaSetのPod数を徐々に増やす
- 古いReplicaSetのPod数を徐々に減らす
- 上記を繰り返す
- 古いReplicaSetのレプリカ数を0で保つ
apiVersion: apps/v1 kind: Deployment metadata: name: sample-deploy 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-deploy.yaml deployment.apps/sample-rs created
- 確認(Pod)
$ kubectl get pod --output wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES sample-deploy-5cc5cfccd7-6vq65 1/1 Running 0 33s 172.17.0.6 minikube <none> <none> sample-deploy-5cc5cfccd7-qjtbx 1/1 Running 0 33s 172.17.0.7 minikube <none> <none> sample-deploy-5cc5cfccd7-szcx5 1/1 Running 0 33s 172.17.0.3 minikube <none> <none>
- 確認(ReplicaSet)
$ kubectl get replicaset --output wide NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR sample-deploy-5cc5cfccd7 3 3 3 2m34s nginx-container nginx:1.19 app=sample-app,pod-template-hash=5cc5cfccd7
- ダッシュボード
DaemonSet
- https://kubernetes.io/ja/docs/concepts/workloads/controllers/daemonset/
- ReplicaSetでは、Podの数が一致するとも確実に配置されるとも保証されない
- DaemonSetは、ReplicaSetの特殊な形、各ノードにPodを一つづつ配置するリソース
- 各ノード上で必ず動作させたいプロセスのために利用することが多い
apiVersion: apps/v1 kind: DaemonSet metadata: name: sample-ds spec: selector: matchLabels: app: sample-app template: metadata: labels: app: sample-app spec: containers: - name: nginx-container image: nginx:1.19
- 作成
$ kubectl apply -f sample-ds.yaml daemonset.apps/sample-ds created
- 確認
$ kubectl get daemonset --output wide NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE CONTAINERS IMAGES SELECTOR sample-ds 1 1 1 1 1 <none> 98s nginx-container nginx:1.19 app=sample-app
StatefulSet
- https://kubernetes.io/ja/docs/concepts/workloads/controllers/statefulset/
- データベースなどステートフルなワークロードに対応するためのリソース
- ReplicaSetの特殊な形
- 作成されるPodのサフィックスは数字のインデックスが付与
- データを永続化する仕組みを持つ
- Pod名が変わらない
apiVersion: apps/v1 kind: StatefulSet metadata: name: web spec: selector: matchLabels: app: sample-app serviceName: sample-stateful replicas: 3 template: metadata: labels: app: sample-app spec: terminationGracePeriodSeconds: 10 containers: - name: nginx image: nginx:1.19 ports: - containerPort: 80 name: web volumeMounts: - name: www mountPath: /usr/share/nginx/html volumeClaimTemplates: - metadata: name: www spec: accessModes: - ReadWriteOnce resources: requests: storage: 1G
- 作成
$ kubectl apply -f sample-stateful.yaml statefulset.apps/web created
- 確認
$ kubectl get statefulset --output wide NAME READY AGE CONTAINERS IMAGES web 0/3 2m19s nginx nginx:1.19
running "VolumeBinding" filter plugin for pod "web-0": pod has unbound immediate PersistentVolumeClaims
- https://qiita.com/silverbirder/items/d3522237b28703a9adb6
- PersistentVolumeは、データを永続的に保存しておく場所のリソース。マネージドサービスを利用すると、デフォルトでPresistentVolumeが用意されている
- PersistentVolumeClaimsは、「PresistentVolumeを使わせて」というリソース
- PresistentVolumeのnameを指定し、applyすることで、初めてマウントができる
$ kubectl get pv No resources found in default namespace.
永続ボリューム(PersistentVolume)
- https://kubernetes.io/ja/docs/concepts/storage/persistent-volumes/
- ストレージが何から提供されているか、どのように消費されているかをユーザーと管理者から抽象化するAPIを提供
PersistentVolume(PV)
- ストレージクラスを使って管理者もしくは動的にプロビジョニングされるクラスターのストレージの一部
- Nodeと同じようにクラスターリソースの一部
- PVを使う個別のPodとは独立したライフサイクルを持っている
PersistentVolumeClaim(PVC)
- ユーザーによって要求されるストレージ
- Podと似ています。PodはNodeリソースを消費し、PVCはPVリソースを消費します
- クレームは特定のサイズやアクセスモード(例えば、1ノードからのみ読み書きマウントができるモードや、複数ノードから読み込み専用マウントができるモードなどです)を要求することができます
実例
index.htmlをノード上に生成
$ minikube ssh $ sudo mkdir /mnt/data $ sudo sh -c "echo 'Hello from kubernetes storage' > /mnt/data/index.html" $ cat /mnt/data/index.html Hello from kubernetes storage
PersistentVolumeの生成
- ホストパスのPersistentVolumeを作成
- Kubernetesは単一クラスターで、ホストパスを開発とテストでサポートする
- ホストパスPersistentVolumeは、ファイルやディレクトリをネットワークアタッチストレージをエミュレートしたものとして使用する
- プロダクションのクラスターでは、ホストパスは使用すべきでなく、クラスタ管理者により、用意されたネットワークリソース(Google Compute Engine persistent disk) などを使用する
- クラスタ管理者は、StorageClassesも動的プロビジョニングに使用することができる
- ホストパスPersistentVolumeの例
apiVersion: v1 kind: PersistentVolume metadata: name: sample-pv labels: type: local spec: storageClassName: manual capacity: storage: 1Gi accessModes: - ReadWriteOnce hostPath: path: "/mnt/data"
- 生成
$ kubectl apply -f sample-pv.yaml persistentvolume/sample-pv created
- 確認
$ kubectl get pv --output wide NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE sample-pv 1Gi RWO Retain Available manual 12s Filesystem
PersistentVolumeClaimの作成
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: sample-pvc spec: storageClassName: manual accessModes: - ReadWriteOnce resources: requests: storage: 1Gi
- 生成
$ kubectl apply -f sample-pvc.yaml persistentvolumeclaim/sample-pvc created
- 確認
$ kubectl get pvc --output wide NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE sample-pvc Bound sample-pv 1Gi RWO manual 52s Filesystem
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
Tips
クイックスタート
piroto@jinmu:~$ kubectl get node NAME STATUS ROLES AGE VERSION minikube Ready master 14m v1.18.3 piroto@jinmu:~$ kubectl create deployment hello-minikube --image=k8s.gcr.io/echoserver:1.10 deployment.apps/hello-minikube created piroto@jinmu:~$ kubectl get pod NAME READY STATUS RESTARTS AGE hello-minikube-64b64df8c9-42s98 0/1 ContainerCreating 0 11s piroto@jinmu:~$ kubectl expose deployment hello-minikube --type=NodePort --port=8080 service/hello-minikube exposed piroto@jinmu:~$ minikube service hello-minikube --url http://192.168.39.238:30523
- ローカル環境のクラスターについて詳細を確認するには、出力から得たURLをブラウザー上でコピーアンドペースト
- Service,Deploymentの削除、クラスター停止、クラスター削除
piroto@jinmu:~$ kubectl delete services hello-minikube service "hello-minikube" deleted piroto@jinmu:~$ kubectl delete deployment hello-minikube deployment.apps "hello-minikube" deleted piroto@jinmu:~$ minikube stop ノード "minikube" を停止しています... 1台のノードが停止しました。 piroto@jinmu:~$ minikube delete kvm2 の「minikube」を削除しています... クラスタ "minikube" の全てのトレースを削除しました。
NodeでHello World
© 2006 矢木浩人