LabHub

ブログ

CKA_2_core_concepts

한국어English日本語

本記事は https://www.udemy.com/course/certified-kubernetes-administrator-with-practice-tests の講座と https://kodekloud.com/ の内容を学習しながら記録したものです。

11 Cluster Architecture

Master NodeとWorker Nodeが存在します。 どのコンテナが存在し、どのように実行されているかは、ETCDというデータストアに保存されます。

Master NodeとWorker Nodeの関係は以下の図のように表現できます。

Master Node

Kube API Serverはすべての操作をオーケストレーションし、すべてを監視します。

アプリケーションはコンテナ形式です。DNSもコンテナです。Dockerは最も有名なコンテナランタイムエンジンですが、ランタイムエンジンが必ずしもDockerである必要はありません。

KubeletはWorker Nodeの船長のような存在です。

Kube Proxy Serverは内部サービス間の通信を支援します。

Master Node

12 Docker-vs-ContainerD

バージョン1でサポートされていたdockershimをバージョン2で廃止することが決定されました。 containerdがインストールされるとctlツールもインストールされます(ユーザーフレンドリーではなく、機能も限定的)。

ctr images pull docker.io/library/redis:alpine
ctr run ...

nerdctlはctrと異なり、DockerライクなCLIツールを提供します。

nerdctl run --name redis redis:alpine

crictlも存在し、Kubernetesプロジェクトで開発されています。 直接使用することはほとんどなく、主にデバッグツールとして使用されます。 kubeletは自身が作成していないコンテナを強制削除できるため、単独で使用する場合は注意が必要です。

13 ETCD for Beginners

etcdctl --version でバージョンを確認できます。通常バージョン2または3です。 Key-Valueストアです。

14 ETCD in Kubernetes

Nodes、Pods、Configs、Secrets、Accounts、Roles、Bindings、Othersに関するすべての情報がETCDに保存されます。 Kubernetesを手動インストールする場合、etcdも手動でインストールする必要があります。 advertise-client-urls のデフォルトポートは2379で、kube-apiserverがetcdに接続するために必要です。 kubeadmでインストールした場合、etcdデーモンがコンテナとして動作していることを確認できます。

sudo kubectl get pods -n kube-system
NAME                                     READY   STATUS    RESTARTS   AGE
coredns-5d78c9869d-2f2qt                 1/1     Running   0          38s
coredns-5d78c9869d-dn7b6                 1/1     Running   0          38s
etcd-docker-desktop                      1/1     Running   0          38s
kube-apiserver-docker-desktop            1/1     Running   0          38s
kube-controller-manager-docker-desktop   1/1     Running   0          39s
kube-proxy-24tjf                         1/1     Running   0          39s
kube-scheduler-docker-desktop            1/1     Running   0          42s
storage-provisioner                      1/1     Running   0          37s
vpnkit-controller                        1/1     Running   0          37s

高可用性(H/A)構成にすることで、複数のマスターetcdインスタンスを持つことができます。

バージョン2で提供されるコマンド:

etcdctl backup
etcdctl cluster-health
etcdctl mk
etcdctl mkdir
etcdctl set

16 Kube API Server

kubeapi server

kubeapi server2

kube-apiserverはさまざまなパラメータで実行されます。

kubeapi server2

kubeadmでインストールした場合、/etc/kubernetes/manifests/kube-apiserver.yaml でAPIサーバーのオプションを確認できます。

17 Kube Controller Manager

Controller Managerはノードのステータスを継続的に監視し、問題を解決します。5秒ごとにハートビートを送信します。

kubeapi server2

Kube-Controller-Managerにはさまざまなマネージャーが含まれています。

kubeadmでインストールした場合、/etc/kubernetes/manifests/kube-controller-manager.yaml でKube-Controller-Managerの設定値を確認できます。

18 Kube Scheduler

  1. Filter Nodes
  2. Rank Nodes

スケジューラを独自に作成することも可能です。

kubeapi server2

/etc/kubernetes/manifests/kube-scheduler.yaml で設定値を確認できます。

19 Kubelet

KubeletはWorker Nodeの船長のような存在です。

kubelet

20 Kube Proxy

各ノードに1つずつDaemonSetとして実行されます。サービス名からIPアドレスを解決します。

kubelet

kubectl get daemonset -n kube-system

21 Recap - Pods

アプリケーションはコンテナとして直接デプロイされるのではなく、Podという抽象化された単位でデプロイされます。

Dockerで以下のようにpython-appとhelperを管理するのは非常に手間がかかります。

kubelet

以下のコマンドでDocker Hubからイメージを取得できます。

$ kubectl run nginx --image nginx
$ kubectl run custom-nginx --image nginx --port=8080

22 Pods with YAML

KubernetesはYAMLファイルを通じてアプリケーションをデプロイします。

apiVersion: v1 | v1 | apps/v1 | apps/v1
kind: POD | Service | ReplicaSet | Deployment
metadata:
    name: myapp-pods
    labels:
        app: myapp
spec:

29 Replica Sets

Podの高可用性を確保するために、Replication Controllerを活用できます。Replication Controllerは常に指定された数以上のPodが動作していることを保証します。また、ユーザー増加に伴うリクエスト増加に対応するため、Pod数をスケールアップする際にも使用されます。

kubelet

Replication ControllerとReplica Setの2種類があり、区別する必要があります。Replication Controllerは古い技術であり、Replica Setに置き換えられつつあります。

Replication Controller

spec配下の replicas に起動したいPodの数を指定します。

rc-definition.yml
apiVersion: v1
kind: ReplicationController
metadata:
  name: nginx
spec:
  replicas: 3
  selector:
    app: nginx
  template:
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80

kubectl create -f rc-definition.yml コマンドでReplication Controllerを実行すると、以下のような結果が得られます。

$ kubectl create -f replication.yaml
replicationcontroller/nginx created

$ kubectl get replicationcontroller
NAME    DESIRED   CURRENT   READY   AGE
nginx   3         3         3       77s

$ kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
nginx-77b4fdf86c-vhbhl   1/1     Running   0          69d
nginx-9tq9x              1/1     Running   0          92s
nginx-s6p44              1/1     Running   0          92s
nginx-znx2w              1/1     Running   0          92s

Replica Set

ReplicaSet はReplication Controllerと似ていますが、selector フィールドがある点が異なります。apiVersionが apps/v1 であることも違いです。

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: frontend
  labels:
    app: guestbook
    tier: frontend
spec:
  # modify replicas according to your case
  replicas: 3
  selector:
    matchLabels:
      tier: frontend
  template:
    metadata:
      labels:
        tier: frontend
    spec:
      containers:
      - name: php-redis
        image: gcr.io/google-samples/hello-app:2.0
$ kubectl create -f replicaset-definition.yml
replicaset.apps/frontend created

$ kubectl get replicaset
NAME               DESIRED   CURRENT   READY   AGE
frontend           3         3         3       24s
nginx-77b4fdf86c   1         1         1       69d

ReplicaSetはPodを監視し、数が指定された数と一致しない場合、自動的にPod数を調整します。複数のPodがある場合、管理対象のPodを識別するためにラベルを付けて管理します。そのため、YAMLファイルで定義する際、ReplicaSetのselectorのラベルとtemplate内のラベルの名前を一致させる必要があります。同じラベル名のPodが既に存在し、Pod数も満たされている場合は新しいPodは作成されないため、ラベル名を指定する際には既に使用されているラベルかどうかを確認する必要があります。

kubelet

3つのレプリカを持つReplicaSet(上で作成した「frontend」)を6つにスケールアップしたい場合は、以下のようにします。

kubectl get replicaset frontend -o yaml で現在のfrontend ReplicaSetのYAML設定ファイルを取得し、replicasの部分を6に変更して保存した後、kubectl replace -f filename で適用できます。

2つ目の方法はscaleコマンドを使用する方法です。

$ kubectl scale --replicas=6  -f replicaset-definition.yml
replicaset.apps/frontend scaled

$ kubectl get replicaset
NAME               DESIRED   CURRENT   READY   AGE
frontend           6         6         6       14m
nginx-77b4fdf86c   1         1         1       69d

再び3に減らすには、ファイルではなくReplicaSet名を直接指定して以下のように実行できます。

$ kubectl scale --replicas=3 replicaset frontend
replicaset.apps/frontend scaled
$ kubectl get replicaset
NAME               DESIRED   CURRENT   READY   AGE
frontend           3         3         3       15m
nginx-77b4fdf86c   1         1         1       69d

32 Deployments

Deployments はReplicaSetと似ています。違いはkindフィールドに ReplicaSet ではなく Deployment を指定する点です。

Podを作成するたびにYAMLを記述するのは面倒です。こういった場合、kubectl runを使うと便利です。 例えば、nginxを実行するDeploymentを作成するYAMLファイルを生成するには、以下のように入力します。

$ kubectl create deployment --image=nginx nginx-deployment --dry-run=client -o yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: nginx-deployment
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-deployment
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx-deployment
    spec:
      containers:
      - image: nginx
        name: nginx
        resources: {}
status: {}

Create a deployment named webapp using the image kodekloud/webapp-color with 3 replicas.

example
$ kubectl create deployment webapp --image=kodekloud/webapp-color --replicas=3
$ kubectl create deployment redis-deploy --image=redis --replicas=2  --namespace=dev-ns

36 Services

外部ユーザーがPodで実行されているWebサービスにアクセスするにはどうすればよいでしょうか? 基本的に外部ネットワークから内部ネットワークに直接アクセスすることはできません。 ここで必要になるのがServiceです。KubernetesのServiceという概念は、Pods、ReplicaSet、Deploymentsと大きく異なるものではありません。Serviceの特徴は、外部からのリクエストを特定リソースのポートにフォワードする機能を提供することです(NodePort Service)。

Services

Services

Node Ports

NodePortは30000〜32767番のポートのみ使用可能です。

nodeport

service-definition.yml
apiVersion: v1
kind: Service
metadata:
  name: nodeport-service
spec:
  type: NodePort
  ports:
    - targetPort: 80
      port: 80
      nodePort: 30008
  selector:
      app: guestbook
      tier: frontend
$ kubectl create -f node-port-definition.yml
service/nodeport-service created

$ kubectl get services
NAME               TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
kubernetes         ClusterIP   10.96.0.1      <none>        443/TCP        127d
nginx              NodePort    10.110.82.18   <none>        80:32381/TCP   70d
nodeport-service   NodePort    10.98.44.253   <none>        80:30008/TCP   40s


$ get pods -o wide
NAME                     READY   STATUS    RESTARTS   AGE   IP           NODE     NOMINATED NODE   READINESS GATES
frontend-759fr           1/1     Running   0          39h   10.244.0.5   cubi04   <none>           <none>
frontend-98dvd           1/1     Running   0          39h   10.244.0.5   cubi02   <none>           <none>
frontend-xpwc5           1/1     Running   0          39h   10.244.0.6   cubi03   <none>           <none>
nginx-77b4fdf86c-wwbrb   1/1     Running   0          39h   10.244.0.3   cubi04   <none>           <none>

$ curl http://192.168.219.114:32381
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>

Services Cluster IP

Kubernetesでは、Podはいつでも別の場所に移動したり再作成されたりする可能性があるため、PodのIPアドレスに依存することはできません。サービス間の通信には、サービスごとに1つ割り当てられるCluster IP(ClusterIPと呼ばれる)を使用する必要があります。

Services

単一のPodに対するClusterIP Serviceの作成方法:

$ kubectl expose pod redis --type=ClusterIP --port=6379 --name=redis-service

Create a pod called httpd using the image httpd:alpine in the default namespace. Next, create a service of type ClusterIP by the same name (httpd). The target port for the service should be 80.

$ kubectl run httpd --image httpd:alpine --port=80 --expose=true
service/httpd created
pod/httpd created

Service LoadBalancer

NodePort Serviceを使用すると、外部から特定のポートを通じてPodにアクセスできますが、Podが10台のノードにまたがって作成されている場合、10個のIP:portの組み合わせが生じます。この場合、どれにアクセスすればよいのでしょうか?

Load Balancerを使用すれば、この問題を解決できます。

41 Namespaces

Kubernetesはkube-system、default、kube-publicの3つのNamespaceを自動的に作成します。本番環境で多くの人が使用する環境では、複数のNamespaceを使用することが推奨されます。

同じNamespace内ではサービス名で検索が可能ですが、異なるNamespaceのサービスにアクセスするには追加のポストフィックスが必要です。

kubelet

これは、Namespaceが追加されるとDNSエントリが追加されるためです。

kubelet

$ kubects get pods --namespace=kube-system

# Pod作成時に --namespace=dev を指定してNamespaceを指定できます。
$ kubectl create -f pod-definition.yml --namespace=dev


# または
# YAMLファイル内のmetadata:の下にnamespace: devを追加する方法もあります。

Namespaceの作成

apiVersion: v1
kind: Namespace
metadata:
  mame: dev
$ kubectl create -f namespace-dev.yml
$ kubectl create namespace dev

Namespaceの永続的な切り替え

kubectlはデフォルトでdefault Namespaceを使用し、毎回 --namespace=dev を付けるのは面倒です。 以下のようにコンテキストを目的のNamespaceに設定すれば、永続的に変更できます。

$ kubectl config set-context $(kubectl config current-context) --namespace=dev
$ kubectl get pods

# 他のNamespace(例:default)のPodを表示したい場合は、以下のようにします。
$ kubectl get pods --namespace=default

# すべてのNamespaceのPodを表示するには以下のようにします。
$ kubectl get pods --all-namespaces
NAMESPACE      NAME                             READY   STATUS             RESTARTS            AGE
default        frontend-759fr                   1/1     Running            0                   37h
default        frontend-98dvd                   1/1     Running            0                   37h
default        frontend-xpwc5                   1/1     Running            0                   37h
default        nginx-77b4fdf86c-wwbrb           1/1     Running            0                   37h
kube-flannel   kube-flannel-ds-fg8lc            0/1     CrashLoopBackOff   20310 (2m2s ago)    126d
kube-flannel   kube-flannel-ds-fvlfs            0/1     CrashLoopBackOff   20310 (66s ago)     126d
kube-flannel   kube-flannel-ds-q72cc            0/1     CrashLoopBackOff   20308 (4m29s ago)   126d
kube-flannel   kube-flannel-ds-smwgc            0/1     CrashLoopBackOff   20310 (98s ago)     126d
kube-system    coredns-5d78c9869d-fd4rg         1/1     Running            1 (125d ago)        126d
kube-system    coredns-5d78c9869d-zl7kh         1/1     Running            1 (125d ago)        126d
kube-system    etcd-cubi01                      1/1     Running            1 (125d ago)        126d
kube-system    kube-apiserver-cubi01            1/1     Running            1 (125d ago)        126d
kube-system    kube-controller-manager-cubi01   1/1     Running            1 (125d ago)        126d
kube-system    kube-proxy-f852g                 1/1     Running            1 (125d ago)        126d
kube-system    kube-proxy-ngt5z                 1/1     Running            1 (125d ago)        126d
kube-system    kube-proxy-tjtm6                 1/1     Running            1 (125d ago)        126d
kube-system    kube-proxy-wfldv                 1/1     Running            1 (125d ago)        126d
kube-system    kube-scheduler-cubi01            1/1     Running            1 (125d ago)        126d

Namespaceにリソースクォータを設定することもできます。

Compute-quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: compute-quota
  namespace: dev
spec:
  hard:
    pods: "10"
    requests.cpu: "4"
    requests.memory: 5Gi
    limits.cpu: "10"
    limits.memory: 10Gi

Imperative vs Declarative

目標に向かって一段階ずつ手続き的(Imperative)に定義する方法と、結果を宣言的(Declarative)に定義する方法があります。Kubernetesは両方をサポートしていますが、後者の方がはるかに便利で、履歴管理が容易なためミスが減ります。Imperativeな方法では、運用者が常に現在の状態を把握している必要があります。

ImperativeDeclarative

ただし、CKA試験ではImperativeな方法の方が速くて直感的な場合もあります。

ImperativeDeclarative

クイズ

Q1: 「CKA_2_core_concepts」の主なトピックは何ですか? CKA_2_core_concepts

Q2: Replication Controllerとは何ですか? spec配下の replicas に起動したいPodの数を指定します。 kubectl create -f rc-definition.yml コマンドでReplication Controllerを実行すると、以下のような結果が得られます。

Q3: Replica Setの核心的な概念を説明してください。 ReplicaSet はReplication Controllerと似ていますが、selector フィールドがある点が異なります。apiVersionが apps/v1 であることも違いです。 ReplicaSetはPodを監視し、数が指定された数と一致しない場合、自動的にPod数を調整します。複数のPodがある場合、管理対象のPodを識別するためにラベルを付けて管理します。そのため、YAMLファイルで定義する際、ReplicaSetのselectorのラベルとtemplate内のラベルの名前を一致させる必要があります。

Q4: Node Portsの主な特徴は何ですか? NodePortは30000〜32767番のポートのみ使用可能です。

Q5: Services Cluster IPはどのように機能しますか? Kubernetesでは、Podはいつでも別の場所に移動したり再作成されたりする可能性があるため、PodのIPアドレスに依存することはできません。サービス間の通信には、サービスごとに1つ割り当てられるCluster IP(ClusterIPと呼ばれる)を使用する必要があります。 単一のPodに対するClusterIP Serviceの作成方法: Create a pod called httpd using the image httpd:alpine in the default namespace.

コメント

まだコメントはありません。

ログインするとコメントできます