2023年3月25日土曜日

Kubernetes構築手順③ (マニフェストファイルを使ってDockerコンテナをデプロイ)

前回、前々回において、Kubernetesのコントロールプレーンの構築とワーカーノードを追加する手順を記載した。

本記事では、構築したKubernetes環境にマニフェストファイルを使ってDockerコンテナをデプロイする手順を記載する。

環境

以下に今回構築する各種ソフトウェアのバージョンを記載する。

  • ホストOS : AlmaLinux 8.6
  • Docker : 23.0.1
  • cri-dockerd: 0.3.1-dev
  • Kubernetes: v1.26.2

今回の構成の概要図を以下に記載する。

マニフェストファイルの準備

マニフェストファイルは、Pod用とサービスリソース用の2種類を作成する。マニフェストファイルの記載方法の説明は、過去minikubeで検証した際に説明をしているので、参考にしていただきたい。

1. Pod用マニフェストファイル

検証用のPodのコンテナイメージは、minikubeでも確認用途で使用していたkicbase/echo-serverを使用する。コントロールプレーン含め、3台のノードにPodが配置されることを確認するため、replicas: 3を設定した。

deployment-hello.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-k8s-deployment
  labels:
    app: hello-k8s-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hello-k8s
  template:
    metadata:
      labels:
        app: hello-k8s
    spec:
      containers:
      - name: hello-k8s
        image: kicbase/echo-server:1.0
        imagePullPolicy: Always

2. サービスリソース用マニフェストファイル

サービスリソースのタイプはNodePortを選択し、各ノードのIPアドレスにアクセスした際に、Podに接続を振り分けるよう設定する。

service-hello.yml

apiVersion: v1
kind: Service
metadata:
  name: hello-k8s-service
  labels:
    app: hello-k8s-service
spec:
  selector:
    app: hello-k8s
  ports:
    - port: 8080
  type: NodePort

Dockerコンテナをデプロイ

1. Podをデプロイ

作成したマニフェストファイルをkubectl applyコマンドで展開する。

# kubectl apply -f deployment-hello.yml
deployment.apps/hello-k8s-deployment created

問題なければ、以下のように3台のPodが展開される。NODEの項目を確認すると、各Podは別々のノードで起動していることがわかる。

# kubectl get pod -o=wide
NAME                                    READY   STATUS    RESTARTS   AGE   IP           NODE        NOMINATED NODE   READINESS GATES
hello-k8s-deployment-6c69965bcb-24qkv   1/1     Running   0          12s   10.244.0.6   t1051kube   <none>           <none>
hello-k8s-deployment-6c69965bcb-4bp74   1/1     Running   0          12s   10.244.2.4   t1053kube   <none>           <none>
hello-k8s-deployment-6c69965bcb-fkbpr   1/1     Running   0          12s   10.244.1.4   t1052kube   <none>           <none>

2. サービスリソースをデプロイ

サービスリソースも同様にkubectl applyコマンドで展開する。

# kubectl apply -f service-hello.yml
service/hello-k8s-service created

問題なければ、サービスリソースは以下の通り表示される。今回はPORTの項目 に記載されている31595ポートが接続用のポート番号となる。

# kubectl get service
NAME                TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
hello-k8s-service   NodePort    10.102.109.11   <none>        8080:31595/TCP   31s
kubernetes          ClusterIP   10.96.0.1       <none>        443/TCP          24h

3. デプロイしたPodへ接続確認

それでは実際にサービスリソース経由でPodにアクセスをしてみよう。

接続先URLは以下の通り。今回はNodePortの設定となるため、接続先は任意のノードの物理IPアドレスとなる。ポート番号は、先ほど確認した31595ポートとなる。

  • http://[任意のノードの物理IPアドレス]:31595

試しにブラウザからノード#3に接続すると以下の通り表示された。

最上部にアクセス先のPodが表示されるており、hello-k8s-deployment-6c69965bcb-4bp74となっている。このことから、ノード#2で起動しているPodであり、たとえノード#3の物理IPアドレスにアクセスしたとしても、実際にアクセスするPodは同一ノードのものとは限らず、任意のPodが選ばれていることがわかる。

以上で、Kubernetes環境にマニフェストファイルを使ってDockerコンテナをデプロイする手順は完了となる。

2023年3月18日土曜日

Kubernetes構築手順② (ワーカーノードを追加)

前回、Kubernetesのコントロールプレーンを構築する手順を記載した。

本記事では、作成したKubernetesクラスターにワーカーノードを追加する手順を記載する。

環境

以下に今回構築する各種ソフトウェアのバージョンを記載する。

  • ホストOS : AlmaLinux 8.6
  • Docker : 23.0.1
  • cri-dockerd: 0.3.1-dev
  • Kubernetes: v1.26.2

今回の構成の概要図を以下に記載する。

ワーカーノードの構築

ワーカーノードの構築は、kubeadmコマンドを実行する直前までは、コントロールプレーンと同様の作業が必要となる。前回記事を参考にあらかじめ以下作業を実施しておこう。

Kubernetesクラスターへ参加

1. Tokenを確認

ワーカーノードをKubernetesクラスターへの参加させるため、kubeadm joinコマンドを実行する必要があるが、この際にコントロールプレーンが持つTokenの情報が必要となる。Tokenは、Kubernetesクラスターを作成した際に表示されるものとなる。

# kubeadm init --pod-network-cidr=10.244.0.0/16 --cri-socket=unix:///var/run/cri-dockerd.sock
[init] Using Kubernetes version: v1.26.2

~(中略)~

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 192.168.11.51:6443 --token bexxee.xx866gxx91sxxa69 \
        --discovery-token-ca-cert-hash sha256:06d8e3077c71a3f7af2xx8d6b389d43673xx9a8axxa5d003ed8dccb356a42f80

もし、クラスター作成時の情報が不明だったり、Tokenの有効期限が切れた場合は、以下コマンドを実行することでTokenを作成し表示させることができる。

# kubeadm token create --print-join-command
kubeadm join 192.168.11.51:6443 --token berssm.biqyhxls0jsdxxxx --discovery-token-ca-cert-hash sha256:c65f49b8ad89d2a2ee1790695a4d7fd0d5583e7f8a7e3a900e04cf5c2356xxxx

# kubeadm token list
TOKEN                     TTL         EXPIRES                USAGES                   DESCRIPTION                                                EXTRA GROUPS
3b4zsz.26fm7d17lb1jxxxx   3h          2023-03-04T23:54:16Z   authentication,signing   The default bootstrap token generated by 'kubeadm init'.   system:bootstrappers:kubeadm:default-node-token
berssm.biqyhxls0jsdxxxx   23h         2023-03-05T20:46:09Z   authentication,signing   <none>                                                     system:bootstrappers:kubeadm:default-node-token
[root@t1051kube ~]#

2. kubeadmコマンド実行

それではワーカーノードとしてKubernetesクラスターに参加させてみよう。

今回はCRIにcri-dockerdを用いるため、確認したTokenのコマンドに、--cri-socket=unix:///var/run/cri-dockerd.sockのオプションを追加し、kubeadm joinコマンドを実行する。
※なお、本作業はインターネット接続できない状態であっても、特にプロキシ設定などは行わずに実施できる。

# kubeadm join 192.168.11.51:6443 --token berssm.biqyhxls0jsdxxxx \
        --discovery-token-ca-cert-hash sha256:c65f49b8ad89d2a2ee1790695a4d7fd0d5583e7f8a7e3a900e04cf5c2356xxxx \
        --cri-socket=unix:///var/run/cri-dockerd.sock
[preflight] Running pre-flight checks
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...

This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

3. Kubernetesクラスター状態確認

Kubernetesの管理はkubectlコマンドを使って実施するが、そのままでは使用できないので、環境変数で設定ファイルのパスを指定しておく。

# export KUBECONFIG=/etc/kubernetes/kubelet.conf

それでは、kubectlコマンドを使って、PodとNodeの状態を確認してみよう。以下の通り、kube-flannel-dskube-proxyのPodが各Nodeで起動しており、参加したワーカーノードはReadyとなっていれば成功となる。

# kubectl get pod -A -o=wide
NAMESPACE      NAME                                READY   STATUS    RESTARTS   AGE     IP              NODE        NOMINATED NODE   READINESS GATES
kube-flannel   kube-flannel-ds-8s4cq               1/1     Running   0          21h     192.168.11.51   t1051kube   <none>           <none>
kube-flannel   kube-flannel-ds-sfkg7               1/1     Running   0          4m40s   192.168.11.52   t1052kube   <none>           <none>
kube-system    coredns-787d4945fb-cf2sf            1/1     Running   0          21h     10.244.0.2      t1051kube   <none>           <none>
kube-system    coredns-787d4945fb-wkp86            1/1     Running   0          21h     10.244.0.3      t1051kube   <none>           <none>
kube-system    etcd-t1051kube                      1/1     Running   0          21h     192.168.11.51   t1051kube   <none>           <none>
kube-system    kube-apiserver-t1051kube            1/1     Running   0          21h     192.168.11.51   t1051kube   <none>           <none>
kube-system    kube-controller-manager-t1051kube   1/1     Running   0          21h     192.168.11.51   t1051kube   <none>           <none>
kube-system    kube-proxy-lscpc                    1/1     Running   0          21h     192.168.11.51   t1051kube   <none>           <none>
kube-system    kube-proxy-vz4v8                    1/1     Running   0          4m40s   192.168.11.52   t1052kube   <none>           <none>
kube-system    kube-scheduler-t1051kube            1/1     Running   0          21h     192.168.11.51   t1051kube   <none>           <none>

# kubectl get node
NAME        STATUS   ROLES           AGE     VERSION
t1051kube   Ready    control-plane   21h     v1.26.2
t1052kube   Ready    <none>          4m43s   v1.26.2

最終的に1台のコントロールプレーンと2台のワーカーノードを追加いした場合は、以下のような状態となる。

# kubectl get pod -A -o=wide
NAMESPACE      NAME                                READY   STATUS    RESTARTS   AGE     IP              NODE        NOMINATED NODE   READINESS GATES
kube-flannel   kube-flannel-ds-8s4cq               1/1     Running   0          21h     192.168.11.51   t1051kube   <none>           <none>
kube-flannel   kube-flannel-ds-mrpsm               1/1     Running   0          3m13s   192.168.11.53   t1053kube   <none>           <none>
kube-flannel   kube-flannel-ds-sfkg7               1/1     Running   0          11m     192.168.11.52   t1052kube   <none>           <none>
kube-system    coredns-787d4945fb-cf2sf            1/1     Running   0          21h     10.244.0.2      t1051kube   <none>           <none>
kube-system    coredns-787d4945fb-wkp86            1/1     Running   0          21h     10.244.0.3      t1051kube   <none>           <none>
kube-system    etcd-t1051kube                      1/1     Running   0          21h     192.168.11.51   t1051kube   <none>           <none>
kube-system    kube-apiserver-t1051kube            1/1     Running   0          21h     192.168.11.51   t1051kube   <none>           <none>
kube-system    kube-controller-manager-t1051kube   1/1     Running   0          21h     192.168.11.51   t1051kube   <none>           <none>
kube-system    kube-proxy-jfg8b                    1/1     Running   0          3m13s   192.168.11.53   t1053kube   <none>           <none>
kube-system    kube-proxy-lscpc                    1/1     Running   0          21h     192.168.11.51   t1051kube   <none>           <none>
kube-system    kube-proxy-vz4v8                    1/1     Running   0          11m     192.168.11.52   t1052kube   <none>           <none>
kube-system    kube-scheduler-t1051kube            1/1     Running   0          21h     192.168.11.51   t1051kube   <none>           <none>

# kubectl get node
NAME        STATUS   ROLES           AGE     VERSION
t1051kube   Ready    control-plane   21h     v1.26.2
t1052kube   Ready    <none>          11m     v1.26.2
t1053kube   Ready    <none>          3m18s   v1.26.2

参考:コントロールプレーンにおいても管理用Pod「以外」を起動させる設定 (taintの解除)

初期設定時は、コントロールプレーンにおいては管理用Podのみ起動できる設定が入っている。これは「taint (汚れ、汚染という意味)」と呼ばれる設定において制御されている。

検証用途などにおいては、コントロールプレーンにおいても管理用Pod「以外」を起動したい場合は、以下コマンドでtaintを解除する。
※今回は説明しないが、Pod側の設定で「toleration (耐える、黙認という意味)」という対となる設定をすることでも対処できる。

# kubectl describe node t1051kube | grep Taints
Taints:             node-role.kubernetes.io/control-plane:NoSchedule

# kubectl taint node t1051kube node-role.kubernetes.io/control-plane:NoSchedule-
node/t1051kube untainted

# kubectl describe node t1051kube | grep Taints
Taints:             <none>

もし、taintの設定を戻したい場合は以下コマンドを実行する。

# kubectl taint node t1051kube node-role.kubernetes.io/control-plane:NoSchedule
node/t1051kube tainted

以上で、Kubernetesクラスターにワーカーノードを追加する手順は完了となる。次回は、本環境に実際にDockerコンテナをPodとしてデプロイし、外部からアクセスできることを確認する。

2023年3月4日土曜日

minikubeを使ってマルチノード構成のKubernetesクラスターを作成する

minikubeは通常1ノード構成のシンプルなKubernetesクラスターを構成する。ただし、その場合は冗長構成が取れず、ノード障害時の動作確認などが取れず検証内容が限定されてしまう。

minikubeは起動時に展開するノード数を指定することで、マルチノード構成を取ることができる。本記事では、minikubeを使ってマルチノード構成のKubernetesクラスターを作成する手順を記載する。

★minikubeに関する以前の記事はこちら。

環境

以下に今回構築する各種ソフトウェアのバージョンを記載する。

  • ホストOS : AlmaLinux 8.6 (GUI環境を含めインストールする)
  • ホストDocker : 20.10.21
  • minikube : 1.28.0

minikubeのマルチノード構成では、PodをPullする際にDockerレジストリが必要となる。今回Dockerコンテナレジストリとして、Harborを用いる。Harborについては、以下記事を参照いただきたい。

以下にminikubeの環境の構成概要図を記載する。

minikubeマルチノード構成手順

1. minikubeをマルチノード構成で起動

minikubeをマルチノード構成で起動させる場合は、nodeのオプションで構成するノード数を指定すればよい。今回は3ノード構成で起動させることにする。

また、コンテナレジストリへは通常HTTPSでなければ接続できない。今回、接続先のHarborはHTTPのみ通信可能な設定となっていることから、一度minikube環境を削除し、minikubeを再度起動させる際にinsecure-registryのオプションを指定し接続できるよう設定を行う。

$ minikube delete
$ minikube start --nodes=3 --insecure-registry=192.168.11.54

ノードを確認すると、minikube-m02とminikube-m03という名前のノードが構成されていることがわかる。

$ kubectl get node -o=wide
NAME           STATUS   ROLES           AGE    VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION              CONTAINER-RUNTIME
minikube       Ready    control-plane   162m   v1.25.3   192.168.49.2   <none>        Ubuntu 20.04.5 LTS   4.18.0-372.9.1.el8.x86_64   docker://20.10.20
minikube-m02   Ready    <none>          161m   v1.25.3   192.168.49.3   <none>        Ubuntu 20.04.5 LTS   4.18.0-372.9.1.el8.x86_64   docker://20.10.20
minikube-m03   Ready    <none>          161m   v1.25.3   192.168.49.4   <none>        Ubuntu 20.04.5 LTS   4.18.0-372.9.1.el8.x86_64   docker://20.10.20

2. namespaceの作成

今回のPodやServiceリソースを作成するためのnamespaceとして、「mynamespace」を作成する。

$ kubectl create namespace mynamespace
namespace/mynamespace created

$ kubectl get namespace
NAME              STATUS   AGE
default           Active   63d
kube-node-lease   Active   63d
kube-public       Active   63d
kube-system       Active   63d
mynamespace       Active   6s

3. マニフェストファイルを適用しPodを作成

使用するマニフェストファイルは、以下記事で作成したマニフェストファイルを使用する。

マルチノード構成となってもPodの作成手順は特に変わらず、kubectl applyでマニフェストファイルを指定すればよい。

$ kubectl apply -f ./deployment_squid_harbor.yml 
deployment.apps/almalinux-squid-deployment created

Podの作成状況を確認すると以下の通り。Podがどのノードで動いているか確認する場合、kubectl get podのオプションに-o=wideを指定する。今回は3つのPodがminikube、minikube-m02、minikube-m03の3つのノードに分散して配置されていることがわかる。

$ kubectl get pod -o=wide -n=mynamespace
NAME                               READY   STATUS    RESTARTS   AGE   IP           NODE           NOMINATED NODE   READINESS GATES
almalinux-squid-76666ccf5c-86pft   1/1     Running   0          28s   10.244.2.2   minikube-m03   <none>           <none>
almalinux-squid-76666ccf5c-pfr7g   1/1     Running   0          28s   10.244.1.2   minikube-m02   <none>           <none>
almalinux-squid-76666ccf5c-sqtwj   1/1     Running   0          28s   10.244.0.3   minikube       <none>           <none>

4. Serviceリソースの作成

Pod作成と同じくkubectl applyを実行し、Serviceリソースを作成する。

$ kubectl apply -f ./service_squid_harbor.yml 
service/almalinux-squid-service created

Serviceリソースの作成状況を確認すると以下の通り。今回はNodePortとなるので、ノードのIPアドレスに対して30717/TCPでServiceリソースに接続することができる。

$ kubectl get service -n=mynamespace
NAME                      TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
almalinux-squid-service   NodePort   10.98.28.180   <none>        8080:30717/TCP   13s

マルチノード構成時のNodePort宛ての通信について

マルチノード構成では複数ノードがそれぞれIPアドレスを持つが、NodePortを設定した場合、接続先のIPアドレスはどのノードのIPアドレスになるだろう。

実は、どのノードのIPアドレスでも問題なく接続できる。確認のため、Podの数を3→2に減らした場合であっても、Podが動作していないNodeのIPアドレスからPodに接続できることを確認してみよう。

1. Podの起動数を変更

Podの起動数は、マニフェストファイルのreplicasで指定されているが、kubectl scaleコマンドでも変更可能となる。

$ kubectl get deploy -n=mynamespace
NAME              READY   UP-TO-DATE   AVAILABLE   AGE
almalinux-squid   3/3     3            3           21m

$ kubectl scale deploy almalinux-squid --replicas=2 -n=mynamespace
deployment.apps/almalinux-squid scaled

$ kubectl get deploy -n=mynamespace
NAME              READY   UP-TO-DATE   AVAILABLE   AGE
almalinux-squid   2/2     2            2           22m

変更後のPodの状態を確認すると、minikube-m02のノードからPodが削除されていることがわかる。

$ kubectl get pod -o=wide -n=mynamespace
NAME                               READY   STATUS    RESTARTS   AGE   IP           NODE           NOMINATED NODE   READINESS GATES
almalinux-squid-76666ccf5c-86pft   1/1     Running   0          22m   10.244.2.2   minikube-m03   <none>           <none>
almalinux-squid-76666ccf5c-sqtwj   1/1     Running   0          22m   10.244.0.3   minikube       <none>           <none>

2. 動作確認

2台となったPodに対して、今回はcurlコマンドにてアクセスをしてみよう。以下の通り、どのノードのIPアドレスに対してアクセスしたとしても、Squidのコンテナ(Server: squid/4.15)から応答が返ってきていることがわかる。
400 Bad Requestとなっているが、これは直接プロキシのURLにアクセスしているため。

$ curl -I http://192.168.49.2:30717
HTTP/1.1 400 Bad Request
Server: squid/4.15
Mime-Version: 1.0
Date: Sun, 29 Jan 2023 08:05:05 GMT
Content-Type: text/html;charset=utf-8
Content-Length: 3539
X-Squid-Error: ERR_INVALID_URL 0
Vary: Accept-Language
Content-Language: en
X-Cache: MISS from almalinux-squid-76666ccf5c-sqtwj
X-Cache-Lookup: NONE from almalinux-squid-76666ccf5c-sqtwj:8080
Via: 1.1 almalinux-squid-76666ccf5c-sqtwj (squid/4.15)
Connection: close

$ curl -I http://192.168.49.3:30717
HTTP/1.1 400 Bad Request
Server: squid/4.15
Mime-Version: 1.0
Date: Sun, 29 Jan 2023 08:04:41 GMT
Content-Type: text/html;charset=utf-8
Content-Length: 3541
X-Squid-Error: ERR_INVALID_URL 0
Vary: Accept-Language
Content-Language: en
X-Cache: MISS from almalinux-squid-76666ccf5c-86pft
X-Cache-Lookup: NONE from almalinux-squid-76666ccf5c-86pft:8080
Via: 1.1 almalinux-squid-76666ccf5c-86pft (squid/4.15)
Connection: close

$ curl -I http://192.168.49.4:30717
HTTP/1.1 400 Bad Request
Server: squid/4.15
Mime-Version: 1.0
Date: Sun, 29 Jan 2023 08:04:44 GMT
Content-Type: text/html;charset=utf-8
Content-Length: 3541
X-Squid-Error: ERR_INVALID_URL 0
Vary: Accept-Language
Content-Language: en
X-Cache: MISS from almalinux-squid-76666ccf5c-sqtwj
X-Cache-Lookup: NONE from almalinux-squid-76666ccf5c-sqtwj:8080
Via: 1.1 almalinux-squid-76666ccf5c-sqtwj (squid/4.15)
Connection: close

以上で、minikubeを使ってマルチノード構成のKubernetesクラスターを作成する手順は完了となる。

人気の投稿