| ページ一覧 | ブログ | twitter |  書式 | 書式(表) |

MyMemoWiki

Kubernetes

提供: MyMemoWiki
2020年11月17日 (火) 08:44時点におけるPiroto (トーク | 投稿記録)による版 (→‎Kubectl)
ナビゲーションに移動 検索に移動

| Docker | Docker コマンド | Docker ネットワーク | WSL | MicroK8s |

Kubernetes

  • https://kubernetes.io/ja/
  • コンテナ化されたアプリケーションのデプロイ、スケーリングなどの管理を自動化するプラットフォーム(コンテナオーケストレーションエンジン)
  • https://knowledge.sakura.ad.jp/20955/
  • 信頼性が高くスケーラブルな分散システムを上手に構築してデプロイするために必要なソフトウェアを提供
  • 分散システムとは、異なるマシンで動作するAPIを実装する部品の集まり
  • マネージドKubernetesサービス(KaaS:Kubernates-as-a-Service)

チートシート

コンポーネント構成

Kubernetes component.png

宣言的なコードによる管理

  • 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
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

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を作る際に、コンテナが異なるマシンに配置されても正常に動作するかという点が判断基準

設定

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>
  • ダッシュボードに表示された

Kubernetes label.png

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

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>
  • ダッシュボードで確認

Kubernetes replicaset.png

Deployment

  • https://kubernetes.io/ja/docs/concepts/workloads/controllers/deployment/
  • 複数のReplicaSetを管理することで、ローリングアップデートやロールバックを実現するリソース
  • Kubernetesで最も推奨されるコンテナの起動方法
  • 1つのコンテナでもDeploymentを使用すべき
  • Deploymentは新しいバージョンのリリースを管理する仕組み
  • デプロイされたアプリケーションをバージョンをまたいで表現する
    • Pod単体では自動で再起動されないし、ReplicaSetでは、ローリングアップデートが利用できない
    • PodもReplicaSetも変更されないコンテナイメージを取り扱うために作られている
  • フロー
    1. 新しいReplicaSetを作成
    2. 新しいReplicaSetのPod数を徐々に増やす
    3. 古いReplicaSetのPod数を徐々に減らす
    4. 上記を繰り返す
    5. 古い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
  • ダッシュボード

Kubernetes deployment.png

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

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)

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デーモンの再利用によるローカルイメージの使用

$ 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

https://hub.docker.com/

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をブラウザー上でコピーアンドペースト

Kubernetes quick start 01.png

  • 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