반응형

 

작성일: 2024년 3월 11일

 

여담 1:
이전에는 kubeadm 명령 도구를 이용해서 kubernetes cluster를 구축했었는데,
오늘은 만사가 귀찮아서 kubespray를 이용해서 kubernetes cluster를 구축해보기로 했다.
kubespray를 이용하면 containerd, CNI, MetalLB 같은 패키지를 직접 설치하지 않아도 되니까 시간이 많이 절약된다.
Ubuntu 22.04 OS가 설치되어 있다고 가정하면, 대략 아래 절차를 따라했을 때 30분 정도 시간이 소요되는 것 같다.

 

여담 2:
아래 작업을 3가지 CPU 스펙으로 진행해봤는데, 저사양 CPU에서는 kubespray를 수행하는 중간에 실패한다.
특히 kubespray를 실행하는 노드(예를 들어 master-a 노드)의 CPU 스펙이 중요하다.
내가 테스트했던 CPU 스펙과 성공/실패 여부를 정리해보면;
CPU 스펙 Kubespray 동작 결과
Intel(R) Xeon(R) E-2278G CPU @ 3.40GHz (16 쓰레드) K8S 클러스터 구성 성공
Intel(R) Xeon(R) E-2124G CPU @ 3.40GHz (4 쓰레드) K8S 클러스터 구성 실패
Intel(R) Core(TM) i7-11700 @ 2.50GHz (16 쓰레드) K8S 클러스터 구성 성공

 

.

.

.

 

Kubernetes cluster 구축 환경 및 Network 구성 정보  [ K8S 클러스터 설계 ]

주의:
아래 예시는 kubespray를 실행할 장비를 별도로 만들지 않았는데, 금전적으로 여유가 있거나 이미 HW가 넉넉히 있는 경우라면
kubespray 실행용 장비를 따로 가지고 있으면 좋다.
Master node: 3개 (Ubuntu 22.04)
  - CPU: 2 core
  - MEM: 8GB
  - OS: Ubuntu 22.04

Worker node: 3개 (Ubuntu 22.04)
  - CPU: 4 core
  - MEM: 16GB
  - OS: Ubuntu 22.04

##
## 참고: CPU, MEM가 적어서 master-a 장비에서 kubespray를 실행하겠다.  
##      만약, HW 제원이 넉넉하다면 kubespray를 실행할 전용 장비가 있으면 좋다.  
##

Network 구성:
  - master-a: 10.10.1.11
  - master-b: 10.10.1.12
  - master-c: 10.10.1.13
  - worker-a: 10.10.1.101
  - worker-b: 10.10.1.102
  - worker-c: 10.10.1.103

 

 

OS & 접속 계정 설정

Master node 및 Worker node로 사용할 6개의 Ubuntu 22.04 서버를 설치한다.

아래 2가지 중에서 편한 방법으로 구성하면 된다.
  - 물리 장비에 OS를 설치하거나 VM에 OS를 설치. (실제로 상용 서비스를 할 것이라면, 이 방법을 권장)
  - 단순히 학습을 목적으로 Kubernetes cluster를 설치한다면, VM에 OS를 설치하는 것을 권장.

 

[ 작업 대상 장비: master-a 노드 ]
'master-a' 에서 아래와 같이 Private key, Public key를 생성하고
이렇게 생성한 Public key를 모든 kubernetes node에 복사한다.

## 이 명령은 master-a 노드에서 수행해야 한다.

$ ssh-keygen 

Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
... 생략 ...

$ ssh-copy-id  sejong@master-a
...

$ ssh-copy-id  sejong@master-b
...

$ ssh-copy-id  sejong@master-c
...

$ ssh-copy-id  sejong@worker-a
...

$ ssh-copy-id  sejong@worker-b
...

$ ssh-copy-id  sejong@worker-c
...

 

 

[ 작업 대상 장비: 모든 노드 ]

Password 없이 Root 권한을 얻기 위해 각 노드에서 아래와 같이 작업을 수행한다. (Ansible이 동작하기 위해 필요한 작업)
$ sudo -
$ echo "sejong ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers

 

 

[ 작업 대상 장비: 모든 노드 ]

각 노드의 Firewall 기능이 disable되어 있는지 확인한다.
$ ufw status
Status: inactive
 
 

[ 작업 대상 장비: 모든 노드 ]

각 노드의 /etc/hosts 파일에 아래의 내용을 추가한다.
$ cat /etc/hosts

... 중간 생략 ...

10.10.1.11 master-a
10.10.1.12 master-b
10.10.1.13 master-c

10.10.1.101 worker-a
10.10.1.102 worker-b
10.10.1.103 worker-c

... 중간 생략 ...
 

Kubespray 실행을 위한 준비 작업

[ 작업 대상 장비: master-a 노드 ]

$ sudo -s

$ apt update

$ apt install python3-pip

$ git clone https://github.com/kubernetes-sigs/kubespray.git

$ cd kubespray

$ pip3 install -r requirements.txt

$ cd inventory

$ cp -Rp sample/ mycluster


$ cat hosts.yaml

all:
  hosts:
    master-a:
      ansible_host: master-a
    master-b:
      ansible_host: master-b
    master-c:
      ansible_host: master-c
    worker-a:
      ansible_host: worker-a
    worker-b:
      ansible_host: worker-b
    worker-c:
      ansible_host: worker-c      
  children:
    kube_control_plane:
      hosts:
        master-a:
        master-b:
        master-c:
    kube_node:
      hosts:
        worker-a:
        worker-b:
        worker-c:
    etcd:
      hosts:
        master-a:
        master-b:
        master-c:
    k8s_cluster:
      children:
        kube_control_plane:
        kube_node:
        calico_rr:
    calico_rr:
      hosts: {}


$ cat  ./group_vars/k8s_cluster/k8s-cluster.yml

... 중간 생략 ...

## Kube cluster를 구축하고 나서, MetalLB를 설치할 때 strict_arp 설정이 필요하다.
## 따라서 MetalLB를 설치하려는 경우라면, 아래 설정을 꼭 'true'로 변경해야 한다.
kube_proxy_strict_arp: true
... 중간 생략 ...
container_manager: containerd
... 중간 생략 ...
kubernetes_audit: true
... 중간 생략 ...

$

 

 

Kubespray 실행하기 (Kubernetes Cluster 생성하기)

[ 작업 대상 장비: master-a 노드 ]

##
## kubespray 소스 폴더의 최상위 폴더로 이동 후 아래 명령을 실행
## (참고) root 계정, 일반 계정 어떤 것으로 ansible-playbook 명령을 실행해도 괜찮다.
##       단, 위에서 public key를 모든 노드에 복사(ssh-copy-id)할 때 어떤 계정의 public key를
##       사용했느냐에 따라 동일한 계정으로 아래 명령을 수행하면 된다.
##

$ ansible-playbook -v -i inventory/mycluster/hosts.yaml --become --become-user=root cluster.yml

... 중간 생략 ...

TASK [network_plugin/calico : Set calico_pool_conf] *****************************************************************************************************************************************
ok: [master-a] => {"ansible_facts": {"calico_pool_conf": {"apiVersion": "projectcalico.org/v3", "kind": "IPPool", "metadata": {"creationTimestamp": "2024-03-08T15:06:52Z", "name": "default-pool", "resourceVersion": "4122", "uid": "ffb5f2e0-85f1-4f3b-9c9d-55fe86be8c97"}, "spec": {"allowedUses": ["Workload", "Tunnel"], "blockSize": 26, "cidr": "10.233.64.0/18", "ipipMode": "Never", "natOutgoing": true, "nodeSelector": "all()", "vxlanMode": "Always"}}}, "changed": false}
Friday 08 March 2024  15:29:07 +0000 (0:00:00.054)       0:19:02.007 **********

TASK [network_plugin/calico : Check if inventory match current cluster configuration] *******************************************************************************************************
ok: [master-a] => {
    "changed": false,
    "msg": "All assertions passed"
}
Friday 08 March 2024  15:29:07 +0000 (0:00:00.060)       0:19:02.067 **********
Friday 08 March 2024  15:29:07 +0000 (0:00:00.037)       0:19:02.104 **********
Friday 08 March 2024  15:29:07 +0000 (0:00:00.045)       0:19:02.150 **********

PLAY RECAP **********************************************************************************************************************************************************************************
master-a                   : ok=676  changed=35   unreachable=0    failed=0    skipped=1164 rescued=0    ignored=2
master-b                   : ok=580  changed=25   unreachable=0    failed=0    skipped=1046 rescued=0    ignored=1
master-c                   : ok=582  changed=25   unreachable=0    failed=0    skipped=1044 rescued=0    ignored=1
worker-a                   : ok=419  changed=8    unreachable=0    failed=0    skipped=695  rescued=0    ignored=1
worker-b                   : ok=419  changed=8    unreachable=0    failed=0    skipped=691  rescued=0    ignored=1
worker-c                   : ok=419  changed=8    unreachable=0    failed=0    skipped=691  rescued=0    ignored=1

Friday 08 March 2024  15:29:07 +0000 (0:00:00.309)       0:19:02.459 **********
===============================================================================
kubernetes/kubeadm : Restart all kube-proxy pods to ensure that they load the new configmap ----------------------------------------------------------------------------------------- 71.14s
network_plugin/calico : Check if calico ready --------------------------------------------------------------------------------------------------------------------------------------- 69.41s
kubernetes-apps/ansible : Kubernetes Apps | Start Resources ------------------------------------------------------------------------------------------------------------------------- 65.75s
network_plugin/calico : Calico | Create Calico Kubernetes datastore resources ------------------------------------------------------------------------------------------------------- 41.63s
kubernetes/control-plane : Upload certificates so they are fresh and not expired ---------------------------------------------------------------------------------------------------- 35.07s
etcd : Configure | Wait for etcd cluster to be healthy ------------------------------------------------------------------------------------------------------------------------------ 29.78s
kubernetes/preinstall : Preinstall | restart kube-apiserver crio/containerd --------------------------------------------------------------------------------------------------------- 27.93s
policy_controller/calico : Start of Calico kube controllers ------------------------------------------------------------------------------------------------------------------------- 26.35s
etcd : Reload etcd ------------------------------------------------------------------------------------------------------------------------------------------------------------------ 21.45s
kubernetes/preinstall : Preinstall | restart kube-controller-manager crio/containerd ------------------------------------------------------------------------------------------------ 20.39s
network_plugin/calico : Calico | Configure calico network pool ---------------------------------------------------------------------------------------------------------------------- 15.41s
network_plugin/calico : Start Calico resources -------------------------------------------------------------------------------------------------------------------------------------- 14.03s
kubernetes/control-plane : Create kubeadm token for joining nodes with 24h expiration (default) ------------------------------------------------------------------------------------- 13.13s
etcd : Wait for etcd up ------------------------------------------------------------------------------------------------------------------------------------------------------------- 12.82s
container-engine/runc : Download_file | Download item ------------------------------------------------------------------------------------------------------------------------------- 12.65s
container-engine/crictl : Download_file | Download item ----------------------------------------------------------------------------------------------------------------------------- 12.60s
container-engine/containerd : Download_file | Download item ------------------------------------------------------------------------------------------------------------------------- 12.17s
kubernetes/control-plane : Check which kube-control nodes are already members of the cluster ---------------------------------------------------------------------------------------- 11.68s
container-engine/nerdctl : Download_file | Download item ---------------------------------------------------------------------------------------------------------------------------- 11.57s
etcd : Backup etcd v2 data ---------------------------------------------------------------------------------------------------------------------------------------------------------- 11.29s

$

 

[ 참고 ]
가끔 위 ansible-playbook 명령이 실패하는 경우가 있다.
그럴 때는 동일하게 한번 더 실행하면 해결되는 경우가 많다. (특히, CPU와 Memory 성능이 낮은 경우)

 

위 Ansible playbook이 정상적으로 수행되었다면,
아래와 같이 root 계정 권한으로 kubectl 명령을 수행해본다.

 

$ sudo -s

$ kubectl get node -o wide

NAME       STATUS   ROLES           AGE   VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION       CONTAINER-RUNTIME
master-a   Ready    control-plane   35m   v1.29.2   172.17.1.11    <none>        Ubuntu 22.04.4 LTS   5.15.0-100-generic   containerd://1.7.13
master-b   Ready    control-plane   34m   v1.29.2   172.17.1.12    <none>        Ubuntu 22.04.4 LTS   5.15.0-100-generic   containerd://1.7.13
master-c   Ready    control-plane   33m   v1.29.2   172.17.1.13    <none>        Ubuntu 22.04.4 LTS   5.15.0-100-generic   containerd://1.7.13
worker-a   Ready    <none>          31m   v1.29.2   172.17.1.101   <none>        Ubuntu 22.04.4 LTS   5.15.0-100-generic   containerd://1.7.13
worker-b   Ready    <none>          31m   v1.29.2   172.17.1.102   <none>        Ubuntu 22.04.4 LTS   5.15.0-100-generic   containerd://1.7.13
worker-c   Ready    <none>          31m   v1.29.2   172.17.1.103   <none>        Ubuntu 22.04.4 LTS   5.15.0-100-generic   containerd://1.7.13


$ kubectl get pod -A

NAMESPACE     NAME                                      READY   STATUS              RESTARTS         AGE
kube-system   calico-kube-controllers-648dffd99-l9pnt   1/1     Running             0                12m
kube-system   calico-node-4q5q9                         1/1     Running             11 (18m ago)     31m
kube-system   calico-node-98pdw                         1/1     Running             14 (5m52s ago)   31m
kube-system   calico-node-nrn9h                         1/1     Running             12 (7m57s ago)   31m
kube-system   calico-node-wgpvw                         1/1     Running             11 (18m ago)     31m
kube-system   coredns-69db55dd76-zkfqn                  1/1     Running             0                10m
kube-system   dns-autoscaler-6f4b597d8c-rt9nk           1/1     Running             0                10m
kube-system   kube-apiserver-master-a                   1/1     Running             4 (18m ago)      37m
kube-system   kube-apiserver-master-b                   1/1     Running             4 (18m ago)      36m
kube-system   kube-apiserver-master-c                   1/1     Running             4 (16m ago)      35m
kube-system   kube-controller-manager-master-a          1/1     Running             8 (6m27s ago)    37m
kube-system   kube-controller-manager-master-c          1/1     Running             10 (7m48s ago)   35m
kube-system   kube-proxy-hgt5x                          1/1     Running             0                15m
kube-system   kube-proxy-j26c8                          1/1     Running             0                15m
kube-system   kube-proxy-ldlb7                          1/1     Running             0                13m
kube-system   kube-proxy-trhgl                          1/1     Running             0                15m
kube-system   kube-proxy-vh6qt                          1/1     Running             0                15m
kube-system   kube-proxy-wv48f                          1/1     Running             0                13m
kube-system   kube-scheduler-master-a                   1/1     Running             7 (10m ago)      37m
kube-system   kube-scheduler-master-b                   1/1     Running             7 (6m15s ago)    36m
kube-system   kube-scheduler-master-c                   1/1     Running             7 (11m ago)      35m
kube-system   nginx-proxy-worker-a                      1/1     Running             0                34m
kube-system   nginx-proxy-worker-b                      1/1     Running             0                34m
kube-system   nginx-proxy-worker-c                      1/1     Running             0                32m
kube-system   nodelocaldns-42f6z                        1/1     Running             0                10m
kube-system   nodelocaldns-5nqjw                        1/1     Running             0                10m
kube-system   nodelocaldns-dsg5w                        1/1     Running             0                10m
kube-system   nodelocaldns-dz9tm                        1/1     Running             0                10m
kube-system   nodelocaldns-mxjxz                        1/1     Running             0                10m
kube-system   nodelocaldns-zqb6h                        1/1     Running             0                10m

$ kubectl get svc -A

NAMESPACE     NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE
default       kubernetes   ClusterIP   10.233.0.1   <none>        443/TCP                  37m
kube-system   coredns      ClusterIP   10.233.0.3   <none>        53/UDP,53/TCP,9153/TCP   12m
$

 

 

 

Kubespray ansible playbook은 11분 42초가 소요되었는데,

조금 더 최신 컴퓨터로 ansible playbook을 실행했다면 10분 이내에 모든 cluster 구축이 완료되지 않을까...

 

[ 참고: 이번 테스트에 사용했던 HW 1 사양 ]

$ lshw -short

H/W path           Device           Class          Description
==============================================================
... 중간 생략 ...
/0/3b                               memory         64GiB System Memory
/0/52                               processor      11th Gen Intel(R) Core(TM) i7-11700 @ 2.50GHz
/0/100/1/0                          display        GA102 [GeForce RTX 3080 Ti]
/0/100/6/0         /dev/nvme0       storage        Samsung SSD 980 PRO 1TB
... 중간 생략 ...

 

[ 참고: 이번 테스트에 사용했던 HW 2 사양 ]

$  lshw -short

H/W path          Device     Class          Description
=======================================================
/0/3a                      memory         64GiB System Memory
/0/3a/0                    memory         32GiB SODIMM DDR4 Synchronous 3200 MHz (0.3 ns)
/0/3a/2                    memory         32GiB SODIMM DDR4 Synchronous 3200 MHz (0.3 ns)
/0/48                      processor      Intel(R) Xeon(R) E-2278G CPU @ 3.40GHz
... 중간 생략 ...

 


 

예제 Pod, Service를 배포하기

아래 글에 간단하게 Pod, Service 리소스를 생성하는 예제 코드 및 명령이 있다.

https://andrewpage.tistory.com/68

 

 


 

 

 

Troubleshooting, Q&A

 

Kubernetes cluster 초기화 하기

$ ansible-playbook -v -i inventory/mycluster/hosts.yaml --become --become-user=root reset.yml

 

Kubernetes cluster 를 upgrade 하기

Upgrade 시나리오가 다양하기 때문에 아래 글을 자세히 읽고 Upgrade를 수행하는 것을 권장한다.

https://github.com/kubernetes-sigs/kubespray/blob/master/docs/upgrades.md

 

Kubernetes node를 추가, 대체하기 (Join new node, Replace node)

Kubernetes node에 대한 operation이 다양하기 때문에 아래 글을 자세히 읽고 node 관리하는 것을 권장한다.

https://github.com/kubernetes-sigs/kubespray/blob/master/docs/nodes.md

 

 

 

 

 

블로그 작성자: sejong.jeonjo@gmail.com

 

 

+ Recent posts