- 컨테이너 인프라 환경: 리눅스 운영 체제의 커널 하나에서 여러 개의 컨테이너가 격리된 상태로 실행되는 인프라 환경
컨테이너 인프라 환경 중 다룰 쿠버네티스 부분
3.1.1 쿠버네티스 구성하기
1. 깃허브에서 필요한 파일 내려받고, 폴더내용 확인
2. ch3의 3.1.3 폴더로 가서 실습에 필요한 파일 확인
Vagrantfile
#5 N = 3
#6 Ver = '1.18.4'
#25 cfg.vm.provision "shell", path: "install_pkg.sh", args: [ Ver, "Main" ]
#26 cfg.vm.provision "shell", path: "master_node.sh"
#48 cfg.vm.provision "shell", path: "work_nodes.sh"
- 5: 쿠버네티스에서 작업을 수행항 워커 노드의 수를 변수(N = 3)로 받음. 해당 변수를 24번째 줄(args: N)과 46번째 줄(args: N)에서 config.sh로 넘김 > 사용자가 워커 노드의 개수를 직접 조절할 수 있게 해줌
- 6: 쿠버네티스 버전을 사용자가 선택할 수 있도록 변수(Ver = '1.18.4')로 저장. 다른 쿠버네티스 버전을 사용하고 싶을 경우 해당 값변뎡
- 25: args: [ Ver, "Main" ] 코드를 투가해 쿠버네티스 버전 정보(Ver)와 Main이라는 문자를 install_pkg.sh로 넘김. Ver 변수는 각 노드에 해당 버전의 쿠버네티스 버전을 설치하게 함. 두 번째 인자인 Main 문자는 install_pkg.sh에서 조건문으로 처리해 마스터 노드에만 이 책의 전체 실행 코드를 내려받게 함
- 26~48: 쿠버네티스 마스터 노드를 위한 master_node.sh와 워커 노드를 위한 work_nodes.sh 코드 추가
config.sh : kuberadm으로 쿠버네티스를 설치하기 위한 사전 조건을 설정하는 스크립트 파일.
#4 echo 'alias vi=vim' >> /etc/profile
#7 swapoff -a
#9 sed -i.bak -r 's/(.+ swap .+)/#\1/' /etc/fstab
#12 gg_pkg="packages.cloud.google.com/yum/doc" # Due to shorten addr for key
#13 cat <<EOF > /etc/yum.repos.d/kubernetes.repo
#14 [kubernetes]
#15 name=Kubernetes
#16 baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
#17 enabled=1
#18 gpgcheck=0
#19 repo_gpgcheck=0
#20 gpgkey=https://${gg_pkg}/yum-key.gpg https://${gg_pkg}/rpm-package-key.gpg
#21 EOF
#24 setenforce 0
#25 sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
#28 cat <<EOF > /etc/sysctl.d/k8s.conf
#29 net.bridge.bridge-nf-call-ip6tables = 1
#30 net.bridge.bridge-nf-call-iptables = 1
#31 EOF
#32 modprobe br_netfilter
#35 echo "192.168.1.10 m-k8s" >> /etc/hosts
#36 for (( i=1; i<=$1; i++ )); do echo "192.168.1.10$i w$i-k8s" >> /etc/hosts; done
#39 cat <<EOF > /etc/resolv.conf
#40 nameserver 1.1.1.1 #cloudflare DNS
#41 nameserver 8.8.8.8 #Google DNS
#42 EOF
- 4: vi를 호출하면 vim을 호출하도록 프로파일에 입력. 이렇게 하면 코드에 하이라이트를 넣어 코드 쉽게 구분 가능
- 7: 쿠버네티스의 설치 요구 조건을 맞추기 위해 스왑되지 않도록 설정
- 9: 시스템이 다시 시작되더라도 스왑되지 않도록 설정
- 13~21: 쿠2버네티스를 내려받을 리포지터리를 설정하는 구문
- 24~25: selinux가 제한적으로 사용되지 않도록 permissive 모드로 변경
- 28~31: 브리지 네트워크를 통과하는 IPv4와 IPv6의 패킷을 iptables가 관리하게 설정.파드의 통신을 iptables로 제어.필요에 따라 IPVS 같은 방식으로도 구성 가능
- 32: br_netfilter 커널 모듈을 사용해 브리지로 네트워크 구성. 이때 IP 마스터레이드를 사용해 내부 네트워크와 외부 네트워크를 분리. IP 마스커레이드는 쉽게 설명하면 커널에서 제공하는 NAT 기능으로 이해하면 됨. 실제로는 BR_NETFILTER를 적용함으로써 28~31번재 줄에서 적용한 iptables가 활성화 됨
- 35~36: 쿠버네티스 안에서 노드 간 통신을 이름으로 할 수 있도록 각 노드의 호스트 이름과 IP를 /etc/hosts에 설정. 이 대 워커 노드는 Vagrantfile에서 넘겨받은 N변수로 전달된 노드 수에 맞게 동적으로 생성
- 39~42 : 외부와 통신할 수 있게 DNS 서버 지정
Install_pkg.sh : 클러스터를 구성하기 위해 가상 머신에 설치돼야 하는 의존성 패키지를 명시.
실습에 필요한 소스 코드를 특정 가상 머신 내부에 내려받도록 설정되어 있음
#6 yum install git -y
#9 yum install docker -y && systemctl enable --now docker
#12 yum install kubectl-$1 kubelet-$1 kubeadm-$1 -y
#13 systemctl enable --now kubelet
#16 if [ $2 = 'Main' ]; then
#17 git clone https://github.com/sysnet4admin/_Book_k8sInfra.git
#18 mv /home/vagrant/_Book_k8sInfra $HOME
#19 find $HOME/_Book_k8sInfra/ -regex ".*\.\(sh\)" -exec chmod 700 {} \;
#20 fi
- 6: 깃허브에서 코드를 내려받을 수 있게 깃을 설치
- 9: 쿠버네티스를 관리하는 컨테이너를 설치하기 위해 도커를 설치하고 구동
- 12~13: 쿠버네티스를 구성하기 위해 첫 번째 변수($1=Ver='1.18.4')로 넘겨받은 1.18.4 버전의 kubectl, kubectl, kubeadm을 설치하고 kubelet을 시작
- 16~20: 이 책의 전체 실행 코드를 마스터 노드에만 내려받도록 Vagrantfile에서 두 번째 변수($2 = 'Main')을 넘겨받음. 그리고 깃에서 코드를 내려받아 실습을 진행할 루트 홈디렉토리(/root)로 옮김. 배시 스크립트(.sh)를 find로 찾아서 바로 실행 가능한 상태가 되도록 chmod 700으로 설정
master_node.sh : 1개의 가상 머신을 쿠버네티스 마스터 노드로 구성하는 스크립트
쿠버네티스 클러스터를 구성할 때 꼭 선택해야 하는 컨테이너 네트워크 인터페이스도 함께 구성
#4 kubeadm init --token 123456.1234567890123456 --token-ttl 0 \
#5 --pod-network-cidr=172.16.0.0/16 --apiserver-advertise-address=192.168.1.10
#8 mkdir -p $HOME/.kube
#9 cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
#10 chown $(id -u):$(id -g) $HOME/.kube/config
#13 kubectl apply -f \
#14 https://raw.githubusercontent.com/sysnet4admin/IaC/master/manifests/172.16_net_calico.yaml
- 4~5: kubeadm을 통해 쿠버네티스의 워커 노드를 받아들일 준비를 함. 토큰을 123456.1234567890123456으로 지정하고 ttl을 0으로 설정해서 기본값이 24시간 후에 토큰이 계속 유지되게 함. 그리고 워커 노드가 정해진 토큰으로 들어오게 함. 쿠버네티스가 자동으로 컨테이너에 부여하는 네트워크를 172..16.0.0/16(172.16.0.1~172.16.255.254)로 제공하고, 워커 노드가 접속하는 API 서버의 IP를 192.168.1.10으로 지정해 워커 노드들이 자동으로 API 서버에 연결되게 함.
- 8~10: 마스터 노드에서 현재 사용자가 쿠버네티스를 정상적으로 구동할 수 ㅣㅇㅆ게 설정 파일을 루트의 홈디렉토리(/root)에 복사하고 쿠버네티스를 이용할 사용자에게 권한을 줌
- 13~14: 컨테이너 네트워크 인터페이스(CNI)인 캘리코의 설정을 적용해 쿠버네티스의 네트워크를 구성
work_nodes.sh : 3대의 가상 머신에 쿠버네티스 워커 노드를 구성하는 스크립트
마스터 노드에 구성된 클러스터에 조인이 필요한 정보가 모두 코드화돼 있어 스크립트를 실행하기만 하면 편하게 워커 노드로서 쿠버네티스 클러스터에 조인 됨
#4 kubeadm join --token 123456.1234567890123456 \
#5 --discovery-token-unsafe-skip-ca-verification 192.168.1.10:6443
- 4~5: kubeadm을 이용해 쿠버네티스 마스터 노드에 접속. 이 때 연결에 필요한 토큰은 기존에 마스터 노드에서 생성한 123456.1234567890123456을 사용. 간단하게 구성하기 위해 --discovery-token-unsafe-skip-ca-verification으로 인증을 무시하고, API 서버 주소인 192.168.1.10으로 기본 포트 번호인 6443번 포트에 접속하도록 설정
3. 쿠버네티스 설치 파일이 있는 디렉토리로 이동 > vagrant up 명령 실행
지금까지 설명한 파일들로 쿠버네티스 클러스터가 자동으로 구성됨
4. vagrant up 실행이 끝나면 슈퍼푸티를 열어 2장에서 설정한 세션 창에서 m-k8s 터미널에 접속
5. kubectl get nodes 명령으로 쿠버네티스 클러스터에 마스터 노드와 워커 노드들이 정상적으로 생성되고 연결됐는지 확인
$ kubectl get nodes
--쿠버네티스 클러스터 구성 끝--
3.1.2 파드 배포를 중심으로 쿠버네티스 구성 요소 살펴보기
설치된 쿠버네티스 구성 요소 확인
$ kubectl get pods --all-namespaces
--all-namespaces : 기본 네임스페이스인 default 외에 모든 것을 표시하겠다는 의미
따라서 모든 네임스페이스에서 파드를 수집해 보여줌. 쿠버네티스 클러스터를 이루는 구성 요소들은 파드 형태로 이루어져 있음
관리자나 개발자가 파드를 배포할 때
- 파드를 배포하는 순서에 따라 요소들의 역할 정리
마스터 노드(클러스터의 두뇌 역할)
0. kubectl
- 쿠버네티스 클러스터에 명령을 내리는 역할
- 다른 구성 요소들과 다르게 바로 실행되는 명령 형태인 binary로 배포되기 때문에 마스터 노드에 있을 필요는 없음
- 하지만 통상적으로 API 서버와 주로 통신하여 실습에서는 마스터 노드에 구성
1. API 서버
- 쿠버네티스 클러스터의 중심 역할을 하는 통로
- 주로 상태 값을 저장하는 ectd와 통신
- 그 밖의 요소들 또한 api 서버를 중심에 두고 통신하므로 api 서버를 중심에 두고 통신하므로 api 서버의 역할이 매우 중요
- (회사에 비유하면 모든 직원과 상황을 관리하고 목표를 설정하는 관리자역할)
2. etcd
- 구성 요소들의 상태 값이 모두 저장되는 곳
- (회사의 관리자가 모든 보고 내용을 기록하는 노트)
- 실제로 etcd외의 다른 구성 요소는 상태 값을 관리하지 않음
- 따라서 etcd의 정보만 백업돼 있으면 긴급란 장애 상황에서도 쿠버네티스 클러스터는 복구 가능
- 분산 저장이 가능한 key-value 저장소 > 복제해 여러 곳에 저장해 두면 하나의 etcd에서 장애가 나도 시스템의 가용성 확보 가능
3. 컨트롤러 매니저
- 쿠버네티스 클러스터의 오브젝트 상태 관리
- ex1) 워커 노드에서 통신이 되지 않는 경우, 상태 체크와 복구는 컨트롤러 매니저에 속한 노드 컨트롤러에서 이루어짐
- ex2) 레플리카셋 컨트롤러는 레플리카셋에 요청받은 파드 개수대로 파드 생성
- 서비스와 파드를 연결하는 역할을 하는 엔드 포인트 컨트롤러 또한 컨트롤러 매니저
4. 스케줄러
- 노드의 상태와 자원, 레이블, 요구 조건 등을 고려해 파드를 어떤 워커 노드에 생성할 것인지 결정 및 할당
- 파드를 조건에 맞는 워커 노드에 지정하고, 파드가 워커 노드에 할당되는 일정을 관리
노드 워커
5. kubelet
- 파드의 구성 내용을 받아 컨테이너 런타임으로 전달, 파드 안의 컨테이너들이 정상적으로 작동하는지 모니터링
6. 컨테이너 런타임(CRI, Container Runtime Interface)
- 파드를 이루는 컨테이너의 실행 담당
- 파드 안에서 다양한 종류의 컨테이너가 문제 없이 작동하게 만드는 표준 인터페이스
7. 파드(Pod)
- 한 개 이상의 컨테이너로 단일 목적의 일을 하기 위해서 모인 단위
- 웹 서버 역할을 할 수 있고 로그나 데이터 분석도 가능
- 언제라도 죽을 수 있는 존재
선택 가능한 구성 요소
11. 네트워크 플러그인
- 쿠버네티스 클러스터릐 통신을 위해 네트워크 플러그인을 선택하고 구성해야 함
- 일반적으로 CNI로 구성
- 주로 사용하는 CNI : 캘리코, 플래널, 실리움, 큐브 라우터, 로마나, 위브넷, Canal
12. CoreDNS
- 클라우드 네이티브 컴퓨팅 재단에서 보증하는 프로젝트
- 빠르고 유연한 DNS서버
- 쿠버네티스 클러스터에서 도메인 이름을 이용해 통신하는 게 사용
- 실무에서 쿠버네티스 클러스터를 구성하영 사용할 떄는 IP보다 도메인 네임을 편리하게 관리해 주는 CoreDNS를 사용하는 게 일반적
사용자가 배포된 파드에 접속할 때
(파드가 배포된 이후 사용자 입장에서 배포된 파드에 접속하는 과정)
1. Kube-proxy
- 쿠버네티스 틀러스터는 파드가 위치한 노드에 kube-proxy를 통해 파드가 통신할 수 있는 네트워크 설정
- 이 때 실제 통신은 br_nefilter와 iptables로 관리
2. 파드
- 이미 배포된 파드에 접속하고 필요한 내용을 전달받음
3.1.3 파드의 생명주기로 쿠버네티스 구성 요소 살펴보기
- 생명 주기: 파드가 생성, 수정, 삭제되는 과정을 나타냄
1. kubectl을 통해 API 서버에 생성 요청
2. (업데이트가 있을 때마다 매번) API 서버에 전달된 내용이 있으면 API 서버는 etcd에 전달된 내용을 모두 기록해 클러스터의 값을 최신으로 유지 > 각 요소가 상태를 업데이트 할 때마다 모두 API 서버를 통해 etcd에 기록됨
3. API 서버에 파드 생성이 요청된 것을 컨트롤러 매니저가 인지하면 컨트롤러 매니저는 파드를 생성하고, 이 상태를 API에 전달 > 아직 어떤 워커 노드에 파드를 적용할지는 결정되지 않은 상태로 파드만 생성
4. API 서버에 파드가 생성됐다는 정보를 스케줄러가 인지, 스케줄러는 생성된 파드를 어떤 워커 노드에 적용할지 조건을 고려해 결정하고 해당 워커 노드에 파드를 띄우도록 요청
5. API 서버에 전달된 정보대로 지정한 워커 노드에 파드가 속해 있는지 스케줄러가 kubelet으로 확인
6. kubelet에서 컨테이너 런타임으로 파드 생성 요청
7. 파드 생성
8. 파드가 사용 가능한 상태가 됨
3.1.4 쿠버네티스 구성 요소의 기능 검증
kubectl
1. 슈퍼푸티 세션 창에서 w3-k8s 터미널에 접속
2. kubectl get nodes 실행
$ kubectl get nodes
> 쿠버네티스 클러스터의 정보를 kubectl이 모르기 때문에 명령을 실행해도 쿠버네티스의 노드들의 정보가 표시되지 않음
>> kubectl은 API 서버를 통해 쿠버네티스에 명령을 내림
>>> kubectl이 어디에 있더라도 API 접속 정보만 있으면 어느 곳에서든 쿠버네티스에 명령 내리기 가능
3. 쿠버네티스 클러스터의 정보(/etc/kubetnetes/admon.conf)를 마스터 노드에서 scp(secure copy)명령으로 w3-k8s의 현재 디렉토리(.)에 받아옴
이 때, 접속기록이 없기 때문에 known_hosts로 저장하도록 yes 입력
마스터 노드의 접속 암호인 vagrant도 입력
$ scp root@192.168.1.10:/etc/kubernetes/admin.conf .
4. kubectl get nodes 명령에 추가로 쿠버네치스 클러스터 정보를 입력받는 옵션(--kubeconfig)과 마스터 노드에서 받아온 admin.conf를 입력하고 실행
$ kubectl get nodes --kubeconfig admin.conf
kubelet
- 쿠버네티스에서 파드의 생성과 상태 관리 및 복구 등을 담당하는 매우 중요한 구성 요소
- kubelet에 문제가 생기면 파드가 정상적으로 관리되지 않음
1. 기능을 검증하려면 실제로 파드 배포해야 함.
m-k8s(마스터 노드)에서 kubectl create -f ~/_Book_k8sInfra/ch3/3.1.6/nginx-pod.yaml 명령으로 nginx 웹 서버 파드를 배포
(-f 옵션 : filename > 즉, 파드의 구성 내용을 파일로 읽어 1개의 파드를 임의의 워커 노드에 배포)
$ kubectl create -f ~/_Book_k8sInfra/ch3/3.1.6/nginx-pod.yaml
2. kubectl get pod 명령으로 배포된 파드가 정상적으로 배포된 상태(Running)인지 확인
$ kubectl get pod
3. kubectl get pods -o wide 명령을 실행해 파드가 배포된 워커 노드를 확인
- o (output) : 특정 형식을 해 주는 옵션
wide : 제공되는 출력 형식 중에서 출력 정보를 더 많이 표시해 주는 옵션
$ kubectl get pods -o wide
4. 배포된 노드인 w1-k8s에 접속해 systemctl stop kubelet 서비스를 멈춤
스케줄러가 임의로 노드를 지정해 배포하므로 실습 정보와 상이 할 수 있음
$ systemctl stop kubelet
5. m-k8s에서 kubectl get pod로 상태를 확인하고, kubectl delete pod nginx-pod 명령을 입력해 파드 삭제
> 삭제하는데 시간이 꽤 소요됨
$ kubectl get pod
$ kubectl delete pod nginx-pod
6. 시간이 지났음에도 슈퍼푸티 명령 창에 변화가 없음. 따라서 ctrl + c 를 눌러 kubectl delete pod nginx-pod 명령을 중지
7. 다시 kubectl get pod 명령을 실행해 파드의 상태 확인.
실행 결과 보면 nginx-pod를 삭제(Terminating)하고 있음. 그러나 kubelet이 작동하지 않는 상태라 파드는 삭제되지 않음
$ kubectl get pod
8. 내용을 확인했으니 w1-k8s에서 systemctl start kubelet을 실행해 kubelet 복구
$ systemctl start kubelet
9. m-k8s에서 kubelet get pod 명령을 실행해 nginx-pod가 삭제됐는지 확인
$ kubectl get pod
kube-proxy
- 파트의 통신 담당
kube-proxy에 문제가 생길 경우 확인해보기
1. 테스트를 위해 마스터 노드인 m-k8s에서 다시 파드 배포
$ kubectl create -f ~/_Book_k8sInfra/ch3/3.1.6/nginx-pod.yaml
2. kubectl get pod -o wide 명령으로 파드의 IP와 워커 노드 확인
$ kubectl get pod -o wide
3. curl(client URL)로 파드의 전 단계에서 확인한 파드의 IP로 nginx 웹 서버 메인 페이지 내용을 확인
$ curl 172.16.221.134
4. w1-k8s(앞 명령에 나온 노드)에 접속해 modprobe -r br_netfilter 명령으로 파드가 위치한 워커 노드에서 br_netfilter 모듈 제거 (-r : remove)
네트워크 재시작 > kube-proxy에 문제가 생기는 상황을 만듦
$ modprobe -r br_netfilter
$ systemctl restart network
5. m-k8s에서 다시 웹 서버 페이지 정보를 받아옴 > 받아오지 못 함
$ curl 172.16.221.134
6. kubectl get pod -o wide를 실행해 파드 상태 확인
$ kubectl get pod -o wide
> 파드의 노드 위치와 IP는 그대로고, 상태도 작동 중
> kube-proxy가 이용하는 br_netfilter에 문제가 있어, nginx 웹 서버와의 통신망이 정상적으로 이루어지지 않는 상태
7. 정상적으로 파드의 nginx 웹 서버 페이지 정보를 받아올 수 있는 상태로 만들기
> 워커 노드에서 modprobe br_netfilter 명령을 실행해 br_netfilter를 커널에 적재하고 시스템을 시작해 적용
$ modprobe br_netfilter
$ reboot
8. 일정 시간이 지난 후 m-k8s에서 파드의 상태를 확인하면 파드가 1회 다시 시작했다는 의미로 RESTARTS가 1로 등가하고 IP가 변경된 것 확인 가능
$ kubectl get pod -o wide
9. 바뀐 IP로 curl 명령을 실행해 파드로부터 정보를 정상적으로 받아오는지 확인
10. 다음 실습을 진행하기 위해 배포한 파드 삭제
'공부 (`・ω・´)ゞ > 쿠버네티스' 카테고리의 다른 글
2. 테스트환경 구성하기 (0) | 2023.03.06 |
---|