작성일: 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
...
[ 작업 대상 장비: 모든 노드 ]
$ sudo -
$ echo "sejong ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
[ 작업 대상 장비: 모든 노드 ]
$ ufw status
Status: inactive
[ 작업 대상 장비: 모든 노드 ]
$ 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
'kubernetes' 카테고리의 다른 글
Kubernetes 스터디 자료 모음 (0) | 2023.08.24 |
---|---|
kubernetes에서 특정 StorageClass를 default로 선택되도록 설정 (0) | 2023.08.23 |
Kubernetes 관련 영상 모음 (Use Case, 데브시스터즈, 설치, 배포, CI/CD, etc) (0) | 2023.03.17 |
Ceph 문제/이슈 해결하기 - overall HEALTH_WARN 1 mgr modules have recently crashed (0) | 2023.03.06 |
Kubernetes, Ceph Storage 환경에서 PV Snapshot 방식 백업 (0) | 2023.02.22 |