Overview
Kubespray 도구를 사용하여 현 최신버전(2022-05-10 기준) Kubernetes Cluster를 구성해본다.
아래의 글을 참고하길 바란다.
2024.02.02 - [Container Orchestration/Kubernetes] - Kubernetes 클러스터 구축하기(kubespray 2024v.)
기본 스펙 및 구성
버전
- OS : Debian 11.3 Bullseye
- kubernetes : v1.23.6
- CRI(Container Runtime Interface) : containerd v1.5.11
서버구성
서버 유형 | Hostname | OS | CPU | 메모리 | IP | 계정 |
가상머신 | k8s-master | Debian Bullseye |
4 Cores |
4G | 192.168.xxx.238 (/24) |
root, user |
가상머신 | k8s-node1 | Debian Bullseye |
4 Cores |
4G | 192.168.xxx.239 (/24) |
root, user |
가상머신 | k8s-node1 | Debian Bullseye |
4 Cores |
4G | 192.168.xxx.240 (/24) |
root, user |
kubespray Requirements
Ansible의 명령어를 실행하기 위해 Ansible v 2.9와 Python netaddr 라이브러리가 머신에 설치되어 있어야 한다
Ansible 플레이북을 실행하기 위해 2.11 (혹은 그 이상) 버전의 Jinja가 필요하다
타겟 서버들은 docker 이미지를 풀(pull) 하기 위해 반드시 인터넷에 접속할 수 있어야 한다. 아니라면, 추가적인 설정을 해야 한다 (오프라인 환경 확인하기)
타겟 서버들의 IPv4 포워딩이 활성화되어야 한다
SSH 키가 인벤토리의 모든 서버들에 복사되어야 한다
방화벽은 kubespray에 의해 관리되지 않는다. 사용자는 필요에 따라 적절한 규칙을 구현해야 한다. 디플로이먼트 과정에서의 문제를 방지하려면 방화벽을 비활성화해야 한다
kubespray가 루트가 아닌 사용자 계정에서 실행되었다면, 타겟 서버에서 알맞은 권한 확대 방법이 설정되어야 하며, ansible_become 플래그나 커맨드 파라미터들, --become 또는 -b 가 명시되어야 한다
VM 생성(KVM)
2022.05.03 - [Container Orchestration/Kubernetes] - Kubernetes 클러스터 구축하기(kubeadm)
VM 생성하는 방법은 위와 같으니 동일한 내용은 생성하도록 하겠다.
기본 패키지 설치 후 QCOW2 타입 디크스를 생성해주었다.
Shell을 이용해 가상머신을 생성해보도록 하겠다.
리눅스 가상머신 생성 및 설정
$ vi k8s.sh
virt-install --virt-type kvm --name k8s-master \
--ram 4096 \
--cpu=host \
--vcpus=4 \
--os-type=debian \
--os-variant=debianwheezy \
--disk path=/data/dong/disk/k8s-master.qcow2,format=qcow2,bus=virtio \
--cdrom=/data/dong/iso/debian-11.3.0-amd64-netinst.iso \
--network bridge=mgmt,model=virtio --graphics vnc,listen=0.0.0.0 \
$ sudo chmod 777 k8s.sh
./k8s.sh
// 쉘을 이용해서 나머지 k8s-node1, k8s-node2 도 생성해준다.
네트워크 설정을 진행해준다.
# The primary network interface
auto ens3
iface ens3 inet static
address 192.168.xx.238/24
gateway 192.168.xx.11
// k8s-master : 238 k8s-node1 : 239 k8s-node2 : 240
$ ifup ens3
// 3대 전부 동일하게 진행
사전설정
아래 설정은 마스터와 노드 모든 머신에서 수행되어야 하며 서로의 머신은 ssh키를 공유하여 passwd없이 ssh접속이 가능해야한다.
패키지 업데이트 및 hosts파일 업데이트.
# apt update && apt upgrade
# vi /etc/hosts
...
192.168.xx.238 k8s-master
192.168.xx.239 k8s-node1
192.168.xx.240 k8s-node2
swap 비활성화
# swapoff -a
# vi /etc/fstab
# swap was on /dev/vda1 during installation
#UUID=
CRI(Container Runtime Interface) 설치
CRI 설치도 모든 머신(마스터와 노드)에서 커맨드를 수행한다.
모듈 로드
# modprobe overlay
# modprobe br_netfilter
# echo br_netfilter >> /etc/modules
- overlay : 오버레이 파일시스템을 위한 모듈
- br_netfilter : 브릿지 방화벽을 위한 모듈
- br_netfilter 모듈은 리부팅시 자동으로 load되지 않아 /etc/modules 파일에 추가하였다.
커널 파라미터 설정
# cat > /etc/sysctl.d/99-kubernetes-cri.conf <<EOF
> net.ipv4.ip_forward = 1
> EOF
# # sysctl --system
* Applying /usr/lib/sysctl.d/50-pid-max.conf ...
kernel.pid_max = 4194304
* Applying /etc/sysctl.d/99-kubernetes-cri.conf ...
net.ipv4.ip_forward = 1
* Applying /etc/sysctl.d/99-sysctl.conf ...
* Applying /usr/lib/sysctl.d/protect-links.conf ...
fs.protected_fifos = 1
fs.protected_hardlinks = 1
fs.protected_regular = 2
fs.protected_symlinks = 1
* Applying /etc/sysctl.conf ...
- Parameter net.bridge.bridge-nf-call-iptables과
- net.bridge.bridge-nf-call-ip6tables인 Bridge
- 방화벽 관련 kernel para는 br_netfilter module이 load되면서 on되므로 추가하지 않는다.
필수 패키지 설치
# apt install -y apt-transport-https \
ca-certificates \
curl \
software-properties-common
Install Ansible
이제부터 이어지는 과정은 kubespray를 실행 할 머신에서만 진행한다.
python pip으로 ansible version을 확인한다.
# pip search ansible
ERROR: XMLRPC request failed [code: -32500]
RuntimeError: PyPI's XMLRPC API is currently disabled due to unmanageable load and will be deprecated in the near future. See https://status.python.org/ for more information.
사이트에 문제가 있는 것 같다. 일단 python pip로 설치를 진행한다.
# pip install ansible
# pip list
ansible 5.7.0
ansible-core 2.12.5
Jinja2 3.1.2
python-netaddr 설치
# apt install python3-netaddr
Kubespray 실행
모든 조건을 충족시켰으니 이제 kubespray를 가져온다.
# apt install git
# git clone https://github.com/kubernetes-sigs/kubespray.git
Cloning into 'kubespray'...
remote: Enumerating objects: 60881, done.
remote: Total 60881 (delta 0), reused 0 (delta 0), pack-reused 60881
Receiving objects: 100% (60881/60881), 17.55 MiB | 6.98 MiB/s, done.
Resolving deltas: 100% (34395/34395), done.
# ls -l
total 4
drwxr-xr-x 15 root root 4096 May 3 14:22 kubespray
inventory 생성기를 실행한다.
# cd kubespray
~/kubespray# python3 contrib/inventory_builder/inventory.py help
Traceback (most recent call last):
File "/root/kubespray/contrib/inventory_builder/inventory.py", line 40, in <module>
from ruamel.yaml import YAML
ModuleNotFoundError: No module named 'ruamel'
사용하기 위한 요구사항이 존재한다. (python3 기반이므로 pip3로 install 해야함)
~/kubespray# cd contrib/inventory_builder/
~/kubespray/contrib/inventory_builder# pip3 install -r requirements.txt
Collecting configparser>=3.3.0
Downloading configparser-5.2.0-py3-none-any.whl (19 kB)
Collecting ruamel.yaml>=0.15.88
Downloading ruamel.yaml-0.17.21-py3-none-any.whl (109 kB)
|████████████████████████████████| 109 kB 16.9 MB/s
Collecting ipaddress
Downloading ipaddress-1.0.23-py2.py3-none-any.whl (18 kB)
Collecting ruamel.yaml.clib>=0.2.6
Downloading ruamel.yaml.clib-0.2.6-cp39-cp39-manylinux1_x86_64.whl (539 kB)
|████████████████████████████████| 539 kB 26.3 MB/s
Installing collected packages: ruamel.yaml.clib, ruamel.yaml, ipaddress, configparser
Successfully installed configparser-5.2.0 ipaddress-1.0.23 ruamel.yaml-0.17.21 ruamel.yaml.clib-0.2.6
~/kubespray/contrib/inventory_builder# python3 inventory.py
DEBUG: Adding group all
DEBUG: Adding group kube_control_plane
DEBUG: Adding group kube_node
DEBUG: Adding group etcd
DEBUG: Adding group k8s_cluster
DEBUG: Adding group calico_rr
Usage: inventory.py ip1 [ip2 ...]
Examples: inventory.py 10.10.1.3 10.10.1.4 10.10.1.5
Available commands:
help - Display this message
print_cfg - Write inventory file to stdout
print_ips - Write a space-delimited list of IPs from "all" group
print_hostnames - Write a space-delimited list of Hostnames from "all" group
add - Adds specified hosts into an already existing inventory
Advanced usage:
Create new or overwrite old inventory file: inventory.py 10.10.1.5
Add another host after initial creation: inventory.py add 10.10.1.6
Add range of hosts: inventory.py 10.10.1.3-10.10.1.5
Add hosts with different ip and access ip: inventory.py 10.0.0.1,192.168.10.1 10.0.0.2,192.168.10.2 10.0.0.3,192.168.10.3
Add hosts with a specific hostname, ip, and optional access ip: first,10.0.0.1,192.168.10.1 second,10.0.0.2 last,10.0.0.3
Delete a host: inventory.py -10.10.1.3
Delete a host by id: inventory.py -node1
Configurable env vars:
DEBUG Enable debug printing. Default: True
CONFIG_FILE File to write config to Default: ./inventory/sample/hosts.yaml
HOST_PREFIX Host prefix for generated hosts. Default: node
KUBE_CONTROL_HOSTS Set the number of kube-control-planes. Default: 2
SCALE_THRESHOLD Separate ETCD role if # of nodes >= 50
MASSIVE_SCALE_THRESHOLD Separate K8s control-plane and ETCD if # of nodes >= 200
sample inventory를 복사한다.
~/kubespray/contrib/inventory_builder# cd ../../
~/kubespray# cp -r inventory/sample inventory/test
`inventory.ini`를 수정한다.
~/kubespray/inventory/test# vi inventory.ini
# ## Configure 'ip' variable to bind kubernetes services on a
# ## different ip than the default iface
# ## We should set etcd_member_name for etcd cluster. The node that is not a etcd member do not need to set the value, or can set the empty string value.
[all]
k8s-master ip=192.168.xxx.238
k8s-node1 ip=192.168.xxx.239
k8s-node2 ip=192.168.xxx.240
[kube-master]
k8s-master
[etcd]
k8s-master
[kube-node]
k8s-master
k8s-node1
k8s-node2
[k8s-cluster:children]
kube-master
kube-node
`inventory.ini`의 수정이 완료되었다면 이제 설치를 진행한다.
~/kubespray/inventory/test# cd ../../
~/kubespray# ansible-playbook -i inventory/test/inventory.ini cluster.yml -b -v
설치가 완료되었다.
# kubectl get node
// 명령어가 안먹는다??
Containerd 설치
# curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add -
# add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/debian \
$(lsb_release -cs) stable"
# apt update && apt install -y containerd.io
$ containerd --version
containerd github.com/containerd/containerd v1.6.3 f830866066ed06e71bad64871bccfd34daf6309c
Kubeadm, Kubectl
쿠버네티스를 구성하기 위해 필수 패키지를 설치한다.
2022.05.03 - [Container Orchestration/Kubernetes] - Kubernetes 클러스터 구축하기(kubeadm)
위의 방법과 동일하다.
https://www.whatwant.com/entry/Kubespray
위의 사이트를 보고 다시 진행해보도록 하자.
root로 진행하였는데 유저로 다시 진행해보려고 한다.
그리고 kubespray 실행하는 것부터 다시 진행해보려고 한다.
Kubespray 실행
git clone 으로 kubespray 다운로드
user@k8s-master:~$ sudo git clone https://github.com/kubernetes-sigs/kubespray.git
'kubespray'에 복제합니다...
remote: Enumerating objects: 60888, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 60888 (delta 0), reused 1 (delta 0), pack-reused 60887
오브젝트를 받는 중: 100% (60888/60888), 17.57 MiB | 8.08 MiB/s, 완료.
델타를 알아내는 중: 100% (34398/34398), 완료.
인벤토리 생성
user@k8s-master:~/kubespray/contrib/inventory_builder$ pip3 install -r requirements.txt
user@k8s-master:~/kubespray/contrib/inventory_builder# python3 inventory.py
sample inventory를 복사
user@k8s-master:~/kubespray$ sudo cp -rfp inventory/sample/ inventory/test
`inventory.ini`를 수정.
user@k8s-master:~/kubespray/inventory/test$ sudo vi inventory.ini
# ## Configure 'ip' variable to bind kubernetes services on a
# ## different ip than the default iface
# ## We should set etcd_member_name for etcd cluster. The node that is not a etcd member do not need to set the value, or can set the empty string value.
[all]
k8s-master ip=192.168.xxx.238
k8s-node1 ip=192.168.xxx.239
k8s-node2 ip=192.168.xxx.240
[kube-master]
k8s-master
[etcd]
k8s-master
[kube-node]
k8s-master
k8s-node1
k8s-node2
[k8s-cluster:children]
kube-master
kube-node
SSH 키 복사하기
user@k8s-master:~/kubespray/inventory/test$ ssh-keygen
user@k8s-master:~/kubespray/inventory/test$ ssh-copy-id 192.168.xxx.238
user@k8s-master:~/kubespray/inventory/test$ ssh-copy-id 192.168.xxx.239
user@k8s-master:~/kubespray/inventory/test$ ssh-copy-id 192.168.xxx.240
설치
$ ansible-playbook -u orchard -i inventory/test/inventory.ini cluster.yml -b -vvv
에러가 발생한다.
PermissionError: [Errno 13] 허가 거부: b'/home/somaz/kubespray/inventory/test/credentials
(https://junghyeonsu.tistory.com/49)
위의 사이트를 참조하여 에러를 해결했다.
master node의 permission denied 인 것 같다.
/home/somaz/kubespray/inventory/test 폴더에 credentials 라는 폴더를 만들지 못한다.
라는 뜻 같다.
user@k8s-master:~/kubespray/inventory/test$ sudo chmod 777 credentials/
user@k8s-master:~/kubespray$ ansible-playbook -u orchard -i inventory/test/inventory.ini cluster.yml -b -vvv
설치가 완료되었다.
PLAY RECAP **********************************************************************************************************
k8s-master : ok=734 changed=58 unreachable=0 failed=0 skipped=1303 rescued=0 ignored=5
k8s-node1 : ok=502 changed=26 unreachable=0 failed=0 skipped=745 rescued=0 ignored=2
k8s-node2 : ok=502 changed=26 unreachable=0 failed=0 skipped=745 rescued=0 ignored=2
localhost : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node가 보이지가 않는다?
$ kubectl get node
The connection to the server localhost:8080 was refused - did you specify the right host or port?
kubectl 명령을 root가 아닌 user 계정으로 실행할 수 있도록 한다.
user@k8s-master:~$ mkdir .kube
user@k8s-master:~$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
user@k8s-master:~$ sudo chown $(id -u):$(id -g) $HOME/.kube/config
kubectl 자동완성 기능도 적용하자.
root@k-master:~# apt install bash-completion
root@k-master:~# echo 'source <(kubectl completion bash)' >>~/.bashrc
root@k-master:~# . ~/.bashrc
node 가 잘보인다. 그러나 `ROLES`가 비어있다.
user@k8s-master:~$ kubectl get node
NAME STATUS ROLES AGE VERSION
k8s-master Ready control-plane,master 8m37s v1.23.6
k8s-node1 Ready <none> 7m27s v1.23.6
k8s-node2 Ready <none> 7m27s v1.23.6
label 추가 후 확인해주자.
user@k8s-master:~$ kubectl label node k8s-node1 node-role.kubernetes.io/worker=worker
node/k8s-node1 labeled
user@k8s-master:~$ kubectl label node k8s-node2 node-role.kubernetes.io/worker=worker
node/k8s-node2 labeled
user@k8s-master:~$ kubectl get node
NAME STATUS ROLES AGE VERSION
k8s-master Ready control-plane,master 12m v1.23.6
k8s-node1 Ready worker 11m v1.23.6
k8s-node2 Ready worker 11m v1.23.6
Pod 확인
user@k8s-master:~$ kubectl get po -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system calico-kube-controllers-58dfb4874f-76w9h 1/1 Running 0 10m
kube-system calico-node-9bxgh 1/1 Running 0 11m
kube-system calico-node-cbzll 1/1 Running 0 11m
kube-system calico-node-fjmbb 1/1 Running 0 11m
kube-system coredns-76b4fb4578-dsccx 1/1 Running 0 10m
kube-system coredns-76b4fb4578-gkhxh 1/1 Running 0 10m
kube-system dns-autoscaler-7979fb6659-vgvf9 1/1 Running 0 10m
kube-system kube-apiserver-k8s-master 1/1 Running 0 12m
kube-system kube-controller-manager-k8s-master 1/1 Running 1 12m
kube-system kube-proxy-2tdfg 1/1 Running 0 11m
kube-system kube-proxy-5m4w2 1/1 Running 0 11m
kube-system kube-proxy-kd8nd 1/1 Running 0 11m
kube-system kube-scheduler-k8s-master 1/1 Running 1 12m
kube-system nginx-proxy-k8s-node1 1/1 Running 0 11m
kube-system nginx-proxy-k8s-node2 1/1 Running 0 11m
kube-system nodelocaldns-blv7g 1/1 Running 0 10m
kube-system nodelocaldns-hkxxj 1/1 Running 0 10m
kube-system nodelocaldns-zv8pm 1/1 Running 2 (9m59s ago) 10m
Reference
https://kubernetes.io/ko/docs/setup/production-environment/tools/kubespray/
'Container Orchestration > Kubernetes' 카테고리의 다른 글
Kubernetes 어피니티 (0) | 2022.05.13 |
---|---|
Kubernetes 컨테이너 이미지 생성하기 (0) | 2022.05.10 |
Kubernetes 클러스터 구축하기(kubeadm) (0) | 2022.05.03 |
쿠버네티스 배포 도구 : Kubeadm vs Kubespray vs Kops (0) | 2022.05.03 |
Kubernetes 개념과 Minikube 실습 (0) | 2022.03.22 |