Featured image of post Kubernetes完全に理解したい 4章

Kubernetes完全に理解したい 4章

完全に理解したい

Kubernetes完全ガイドをまじめに読み始めたのでちょっとずつまとめていきたい.
1~3章はDockerのおさらいだったりKubernetesとは?みたいな話だったので割愛.


読んだもの

重要そうなところとかよく使いそうなところだけまとめる.

読んだことのまとめ

  • Kubernetesには役割の異なるたくさんのリソースがある.
  • Namespaceによりクラスタを仮想的に分離できる.
  • リソースに関する操作はKubernetes APIを通じて行う. CLIならkubectlでいろいろ操作できる.

Kubernetesリソースの種類

Kubernetesのリソースはだいたい5種類に分けられるらしい.

Workloads

コンテナを実行する部分に関わるリソース. 基本的にPodと各種Controllerで構成される.
重要そうなものだけ以下にまとめる.

リソース概要
PodKubernetesの最小単位
ReplicaSetPodのレプリカを複数維持する
DeploymentReplicaSetを複数管理する
DaemonSetNodePodを1台ずつ維持する
StatefulSetステートフルなDeploymentPodを管理する
Job回数制限付きのPodの処理を行う
CronJobJobのスケジューリングを行う

Discovery & LB

コンテナの通信に関わるリソース.

リソース概要
Service複数のPodで構成されるアプリケーションを外部に公開するL4レベルのLB
Ingress外部からServiceへのアクセスを可能にするL7レベルのLB

Config & Storage

コンテナの設定ファイルや機密情報, 永続化ボリュームに関するリソース.

リソース概要
SecretPodで扱うパスワードや鍵などの機密情報を管理する
ConfigMapPodで扱う設定情報を管理する
PersistentVolumeClaimPersistentVolume(後述)を管理する

Cluster

クラスタ自体の挙動に関するリソース.

リソース概要
NodeMasterによって管理されるワーカーマシン
Namespaceクラスタを仮想的に分離させる
PersistentVolumePodから利用できる永続化ボリューム
ResourceQuotaNamespaceごとに使用できるリソースの数に制限をかける
ServiceAccountNamespaceに紐付いたユーザ情報
RoleNamespaceレベルで許可される操作の情報
ClusterRoleクラスタレベルで許可される操作の情報
RoleBindingNamespaceレベルでユーザ情報とRoleを紐付けて権限管理を行う
ClusterRoleBindingクラスタレベルでユーザ情報とClusterRoleを紐付けて権限管理を行う
NetworkPolicyクラスタ内のPod同士の通信を制限する

Metadata

クラスタ内の他のリソースを操作するためのリソース.

リソース概要
LimitRangeNamespaceレベルでPodが使用できるCPUやメモリの制限を行う
HorizontalPodAutoscalerDeploymentまたはReplicaSetのオートスケーリングを行う
PodDisruptionBudgetNode更新処理の際に維持するPodの数を設定する
CustomRessourceDefinition独自のリソースを作ってKubernetesを拡張する

Namespaceによる仮想クラスタ分離

クラスタ作成時にデフォルトで作成されるNamespaceは3つ.

  • kube-system
    • クラスタの各種コンポーネントやアドオンといったシステムがデプロイされる
  • kube-public
    • 全ユーザが使用可能なConfigMapなどの情報が配置される
  • default
    • ユーザーがデフォルトで使用し, 任意のリソースが作成される
# Namespaceの一覧を表示
$ kubectl get namespaces
NAME          STATUS   AGE
default       Active   90m
kube-public   Active   90m
kube-system   Active   90m

kubectl

kubectlMasterkube-apiserverと通信を行うCLIツール.
Kubernetes API自体はRESTfulであるから代わりに各言語のクライアントライブラリを使うこともできる.

# ローカルからAPIにアクセスするためにproxyを別ターミナルで起動
$ kubectl proxy
Starting to serve on 127.0.0.1:8001

# APIを直接叩いてNamespaceの一覧を表示
# $(kubectl get namespaces)と同じ情報を取得できる
$ curl 127.0.0.1:8001/api/v1/namespaces
{
  "kind": "NamespaceList",
  "apiVersion": "v1",
  "metadata": {
    "selfLink": "/api/v1/namespaces",
    "resourceVersion": "23058"
  },
  "items": [
    {
      "metadata": {
        "name": "default",
        "selfLink": "/api/v1/namespaces/default",
        "uid": "...",
        "resourceVersion": "25",
        "creationTimestamp": "2019-12-16T12:29:50Z"
      },
      "spec": {
        "finalizers": [
          "kubernetes"
        ]
      },
      "status": {
        "phase": "Active"
      }
    },
    {
      "metadata": {
        "name": "kube-public",
        "selfLink": "/api/v1/namespaces/kube-public",
        "uid": "...",
        "resourceVersion": "35",
        "creationTimestamp": "2019-12-16T12:29:50Z"
      },
      "spec": {
        "finalizers": [
          "kubernetes"
        ]
      },
      "status": {
        "phase": "Active"
      }
    },
    {
      "metadata": {
        "name": "kube-system",
        "selfLink": "/api/v1/namespaces/kube-system",
        "uid": "...",
        "resourceVersion": "166",
        "creationTimestamp": "2019-12-16T12:29:50Z",
        "annotations": {
          "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"Namespace\",\"metadata\":{\"annotations\":{},\"name\":\"kube-system\",\"namespace\":\"\"}}\n"
        }
      },
      "spec": {
        "finalizers": [
          "kubernetes"
        ]
      },
      "status": {
        "phase": "Active"
      }
    }
  ]
}

上の例ではcurlで認証情報を渡すのが面倒なのでproxyを使用したが,
本来kubectlkube-apiserverと通信するために必要な認証情報はkubeconfig(~/.kube/config)に記述する.
各種サービスを使用してクラスタを構築した場合はデフォルトで記述されていることが多い.

# kubeconfigを確認
$ cat ~/.kube/config
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: ...
    server: https://34.83.155.176
  name: gke_uzimihsr-01_us-west1-a_uzimihsr-k8s-perfect-guide
- cluster:
    certificate-authority: /Users/uzimihsr/.minikube/ca.crt
    server: https://192.168.99.110:8443
  name: minikube
contexts:
- context:
    cluster: gke_uzimihsr-01_us-west1-a_uzimihsr-k8s-perfect-guide
    user: gke_uzimihsr-01_us-west1-a_uzimihsr-k8s-perfect-guide
  name: gke_uzimihsr-01_us-west1-a_uzimihsr-k8s-perfect-guide
- context:
    cluster: minikube
    user: minikube
  name: minikube
current-context: gke_uzimihsr-01_us-west1-a_uzimihsr-k8s-perfect-guide
kind: Config
preferences: {}
users:
- name: gke_uzimihsr-01_us-west1-a_uzimihsr-k8s-perfect-guide
  user:
    auth-provider:
      config:
        access-token: ...
        cmd-args: config config-helper --format=json
        cmd-path: /Users/uzimihsr/google-cloud-sdk/bin/gcloud
        expiry: 2019-12-16T14:59:54Z
        expiry-key: '{.credential.token_expiry}'
        token-key: '{.credential.access_token}'
      name: gcp
- name: minikube
  user:
    client-certificate: /Users/uzimihsr/.minikube/client.crt
    client-key: /Users/uzimihsr/.minikube/client.key

kubectlではkubeconfigContextを切り替えることで異なるクラスタへ接続することができる.

# Contextの一覧を表示
# GKE用のContextを使用している
$ kubectl config get-contexts
CURRENT   NAME                                                    CLUSTER                                                 AUTHINFO                                                NAMESPACE
*         gke_uzimihsr-01_us-west1-a_uzimihsr-k8s-perfect-guide   gke_uzimihsr-01_us-west1-a_uzimihsr-k8s-perfect-guide   gke_uzimihsr-01_us-west1-a_uzimihsr-k8s-perfect-guide
          minikube                                                minikube                                                minikube

# 使用するContextを変更
$ kubectl config use-context minikube
Switched to context "minikube".

# 現在のContextを確認
$ kubectl config current-context
minikube

kubectlとマニフェストファイルを使ってリソースの操作をすることができる.

# リソース(Pod)の作成
$ kubectl apply -f sample-pod.yaml
pod/sample-pod created

# Podの一覧表示
$ kubectl get pods
NAME         READY   STATUS    RESTARTS   AGE
sample-pod   1/1     Running   0          18s

# リソースの削除
$ kubectl delete -f sample-pod.yaml
pod "sample-pod" deleted

sample-pod.yaml

リソースにKey-Value形式のラベルをつけることで, 管理がしやすくなる.
ReplicaSetServiceではこのラベルを使用してPodの管理を行っている.

# Pod(sample-label)はlabel1(Key)=val1(Value)とlabel2=val2の2つのラベルを持つ
$ kubectl describe pod sample-label
...
Labels:             label1=val1
                    label2=val2
...

# Podの一覧表示
$ kubectl get pods
NAME           READY   STATUS    RESTARTS   AGE
sample-label   1/1     Running   0          59s
sample-pod     1/1     Running   0          29s

# ラベル(label1=val1)で絞り込む
$ kubectl get pods -l label1=val1
NAME           READY   STATUS    RESTARTS   AGE
sample-label   1/1     Running   0          5m55s

# ラベルのValueを表示させる
$ kubectl get pods -L label1 -L label2
NAME           READY   STATUS    RESTARTS   AGE     LABEL1   LABEL2
sample-label   1/1     Running   0          7m41s   val1     val2
sample-pod     1/1     Running   0          7m11s

sample-label.yaml

kubectl getはオプションを付けることで出力形式を指定することができる.

# 詳細な情報を付与して一覧表示
$ kubectl get pods -o wide
NAME           READY   STATUS    RESTARTS   AGE   IP         NODE                                                  NOMINATED NODE   READINESS GATES
sample-label   1/1     Running   0          11m   10.4.2.4   gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-0dgf   <none>           <none>
sample-pod     1/1     Running   0          10m   10.4.2.5   gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-0dgf   <none>           <none>

# YAML形式でPod(sample-pod)の情報を出力
$ kubectl get pod sample-pod -o yaml
apiVersion: v1
kind: Pod
...
status:
  ...
  hostIP: 10.138.0.5
  ...
...

# 表示項目を指定して一覧表示
# Podのmetadata.nameの値をNAME, status.hostIPの値をNodeIPとして表示
$ kubectl get pods -o custom-columns="NAME:{.metadata.name},NodeIP:{.status.hostIP}"
NAME           NodeIP
sample-label   10.138.0.5
sample-pod     10.138.0.5

kubectl topでCPUやメモリの使用量を確認できる.

# NodeのCPU, メモリ使用量を確認
$ kubectl top nodes
NAME                                                  CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-0dgf   51m          5%     674Mi           25%
gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-n2mf   117m         12%    786Mi           29%
gke-uzimihsr-k8s-perfect-default-pool-e0d8f087-wk64   37m          3%     651Mi           24%

# PodのCPU, メモリ使用量をコンテナ情報つきで確認
$ kubectl top pods --containers
POD            NAME              CPU(cores)   MEMORY(bytes)
sample-label   nginx-container   0m           1Mi
sample-pod     nginx-container   0m           1Mi

kubectl execPod上でコマンドを実行することができる.

# Podのコンテナでshを起動
$ kubectl exec -it sample-pod -c nginx-container /bin/sh
# Ctrl+Dまたはexitコマンドで終了

# コマンドに引数がある場合は--の後に指定する
$ kubectl exec -it sample-pod -c nginx-container -- /bin/sh -c "ls --all --classify | grep media"
media/

kubectl logsPodのログが確認できる.

# コンテナを指定してPodのログを確認
$ kubectl logs sample-pod -c nginx-container
...

# 全コンテナのログを垂れ流す
$ kubectl logs -f sample-pod --all-containers
...

# 期間を指定して出力
# 1時間前から10件分のログをタイムスタンプ付きで表示
$ kubectl logs --since=1h --tail=10 --timestamps=true sample-pod
...

kubectl cpPodとローカルマシンでファイルのコピーができる.

# Podの/etc/hostnameをローカルにコピー
$ kubectl cp sample-pod:/etc/hostname ./
$ cat ./hostname
sample-pod

# ローカルのファイルをPodの/tmp/newfileにコピー
$ kubectl cp ./hostname sample-pod:/tmp/newfile
$ kubectl exec -it sample-pod -- /bin/sh -c "cat /tmp/newfile"
sample-pod

kubectl port-forwardでポート転送ができる.

# localhostの8888番ポートをPodの80番ポートに転送
$ kubectl port-forward sample-pod 8888:80
Forwarding from 127.0.0.1:8888 -> 80
Forwarding from [::1]:8888 -> 80
# 確認できたらCtrl+Cで終了

# 別ターミナルで疎通確認
$ curl -I localhost:8888
HTTP/1.1 200 OK
Server: nginx/1.12.2
...

おまけ

おててしまってお上品に座るそとちゃん