BGP(Border Gateway Protocol): AS 사이에서 이용되는 라우팅 프로토콜. 대규모 네트워크(수천만의 경로 수)에 대응하도록 설계됐다. 그래서 BGP로 동작하는 라우터는 비교적 고가인 제품이 많다.
AS(Autonomous System): 하나의 정책을 바탕으로 관리되는 네트워크(자율 시스템)를 말한다. ISP, 엔터프라이즈 기업, 공공기관 같은 조직이 이에 해당하며 인터넷은 이러한 자율 시스템의 집합체이다.여러가지 구성 요소가 많지만, 일단 눈여겨 볼 내용은 Calico가 사용하는 Datastore[1]와 마스터 노드를 포함한 모든 노드들에 존재하는 Calico Pods[2]
Felix (필릭스) : 인터페이스 관리, 라우팅 정보 관리, ACL 관리, 상태 체크
BIRD (버드): BGP Peer 에 라우팅 정보 전파 및 수신, BGP RR(Route Reflector)
Confd : calico global 설정과 BGP 설정 변경 시(트리거) BIRD 에 적용해줌
Datastore plugin : calico 설정 정보를 저장하는 곳 – k8s API datastore(kdd) 혹은 etcd 중 선택
Calico IPAM plugin : 클러스터 내에서 파드에 할당할 IP 대역
calico-kube-controllers : calico 동작 관련 감시(watch)
calicoctl : calico 오브젝트를 CRUD 할 수 있다, 즉 datastore 접근 가능
구성 요소 확인하기
데몬셋으로 각 노드에 calico-node 파드가 동작하여, 해당 파드에 bird, felix, confd 등이 동작 + Calico 컨트롤러 파드는 디플로이먼트로 생성
Calico의 특징은 BGP를 이용해 각 노드에 할당된 Pod 대역의 정보를 전달한다. 즉, 쿠버네티스 서버뿐만 아니라 물리적인 라우터와도 연동이 가능 하다는 뜻이다. (Flannel의 경우 해당 구성 불가)
Calico Pod 안에서 Bird라고 하는 오픈소스 라우팅 데몬 프로그램이 프로세스로 동작하여 각 Node의 Pod 정보가 전파되는 것이다.
이후 Felix라는 컴포넌트가 리눅스 라우터의 라우팅 테이블 및 iptables rule에 전달 받은 정보를 주입하는 형태이다.
confd는 변경되는 값을 계속 반영할 수 있도록 트리거 하는 역할이다.
Calico 기본 통신 과정 확인하기
calicoctl 설치
리소스 관리를 위해 Calico CLI를 설치 및 구성
마스터 노드 확인
Calico CNI 설치시, 데몬셋이므로 모든 노드에 칼리코 파드가 하나씩 존재하게 된다. (calico-node-*)
칼리코 컨트롤러가 하나 존재하는 것을 확인할 수 있다.
calicoctl ipm show 명령어를 통해, IAPM 정보를 확인할 수 있다. 아래 스크린샷에서는 172.16.0.0/16 대역을 해당 쿠버네티스 클러스터에서 사용할 수 있다는 내용을 알 수 있다.
IPAM(IP Address Management): 풍부한 사용자 환경을 통해 IP 주소 인프라의 엔드 투 엔드 계획, 배포, 관리 및 모니터링을 지원하는 통합 도구 모음이다.
IPAM은 네트워크상의 IP 주소 인프라 서버 및 DNS(도메인 이름 시스템) 서버를 자동으로 검색하여 중앙 인터페이스에서 이들 서버를 관리할 수 있다.
옵션을 통해 아래와 같이 특정한 노드에 할당 가능한 대역대를 확인할 수도 있음(Block는 각 노드에 할당된 Pod CIDR 정보를 나타냄)
calicoctl node 정보 확인
ippool 정보 확인
파드와 서비스 사용 네트워크 대역 정보 확인
실습 1.
동일 노드 내 파드 간 통신
결론: 동일 노드 내의 파드 간 통신은 내부에서 직접 통신됨
파드 생성 전 노드(k8s-w1)의 기본 상태
노드(k8s-w1)에 파드 2개 생성
아래 내용으로 node1-pod2.yaml 파일 작성 후 파드 생성
파드 생성 전후의 변화를 관찰하기 위해 터미널 하단 추가 탭에watch calicoctl get workloadEndpoint 명령어를 사용하여 모니터링
calicoctl 명령어로 endpoint 확인: veth 정보도 확인할 수 있음
생성된 파드 정보 확인
네트워크 인터페이스 정보 확인(k8s-w1)
calice#~ 두개 추가된 것을 확인할 수 있음
각각 net ns 0,1로 호스트와 구별되는 것을 확인할 수 있음
네트워크 네임스페이스 확인
아래 2개 PAUSE 컨테이너가 각각 파드별로 생성된 것을 확인할 수 있음
바로 위 스크린샷인 link-netnsid 0, link-netnsid 1과 매칭됨
라우팅 테이블 확인
파드의 IP/32bit 호스트 라우팅 대역이 라우팅 테이블에 추가된 것을 확인할 수 있음
파드간 통신 실행 이해
(위) 마스터 노드에서 Pod1 Shell에 접근하여 Pod2로 Ping 테스트
(아래) 워커 노드(k8s-w1)에서 iptables 필터 테이블에 FORWARD 리스트 중 cali-FORWARD 룰 정보를 필터링해서 watch로 확인
테스트 결과 아래 이미지와 같이 Host iptables에서 FOWRARD라는 테이블의 허용 조건에 따라 정상적으로 통신이 가능한 것을 확인할 수 있다.
파드에서 외부(인터넷)로의 통신
결론: 파드에서 외부(인터넷) 통신 시에는 해당 노드의 네트워크 인터페이스 IP 주소로 MASQUERADE(출발지 IP가 변경) 되어서 외부에 연결됨
파드 배포 전 calico 설정 정보 확인 & 노드에 iptables 확인
마스터 노드에서 아래 내용 확인: natOutgoing의 기본값이 true로 설정되어 있는 것을 확인 할 수 있다. 즉 이 노드에서 외부로 통신할 때 NAT의 MASQUERADE를 사용하겠다는 의미이다.
NAT – MASQUERADE : 조건에 일치하는 패킷의 출발지 주소를 변환하는 것. 내부에서 전달되는 요청의 출발지 주소를 조건에 지정된 인터페이스의 IP로 변환한다.
워커 노드(k8s-w1)에서도 외부로 통신시 MASQUERADE 동작 Rule이 존재하는 것을 확인할 수 있다.
마스터 노드에서 워커 노드(k8s-w1)에 아래 내용의 파드 1개 생성
외부 통신 가능 여부 확인
통신 전, 워커 노드(k8s-w1)에 iptables NAT MASQUERADE 모니터링을 활성화 하면 외부 통신시 pkts값이 증가하는지 확인할 수 있다.
(위) 마스터 노드에서 Pod1 Shell 실행 후, 8.8.8.8로의 통신 성공
(아래) pkts 값이 이전 이미지와 다르게 증가한 것을 확인할 수 있다.
다른 노드에서 파드 간 통신
결론: 다른 노드 환경에서 파드 간 통신시에는 IPIP터널(기본값) 모드를 통해서 이루어진다.
각 노드에 파드 네트워크 대역은 Bird에 의해서 BGP로 광고 전파/전달 되며, Felix에 의해서 호스트의 라우팅 테이블에 자동으로 추가/삭제 된다.
다른 노드 간의 파드 통신은 tunl0 인터페이스를 통해 IP 헤더에 감싸져서 상대측 노드로 도달 후 tunl0 인터페이스에서 Outer 헤더를 제거하고 내부 파드와 통신한다.
파드 배포 전, 노드에서 BGP에 의해 전달 받은 정보가 호스트 라우팅 테이블에 존재하는지 확인
아래 명령어를 통해 나머지 노드들의 파드 대역을 자신의 호스트 라우팅 테이블에 가지고 있고, 해당 경로는 tunl0 인터페이스로 보내게 된다는 사실을 알 수 있다.
워커 노드(k8s-w1, w2)의 tunl0 정보 확인
터널 인터페이스가 IP에 할당되어 있음
MTU는 1480 (칼리코 사용 시 파드의 인터페이스도 기본 MTU 1480 사용)
현재 TX/RX 카운트는 0 –> 잠시 후, 오버레이 통신시 카운트 값이 증가할 것
마스터 노드에서 워커 노드(k8s-w1, w2) 대상으로 각각 파드 1개씩 생성
calicoctl 명령어를 이용하여 생성된 파드의 엔드포인트 확인
각 노드에서 파드 간 통신을 처리하는 라우팅 정보 확인
k8s-w1(172.16.158.4/32) 노드에서 w2(172.16.184.0) 노드 대역에 통신하려면 192.168.10.102를 거쳐야 한다는 것을 확인할 수 있다.
반대로 w2(172.16.184.1/32) 노드에서 w1(172.16.158.0) 노드 대역에 통신하려면 192.168.10.101를 거쳐야 한다.
다른 노드 파드 간 통신이 어떻게 실행되는지 확인 ⇒ IPIP
(상) Pod2가 속한 노드(k8s-w2)에 tunl0 인터페이스 TX/RX 패킷 카운트 모니터링 세팅
(중) 마스터 노드에서 Pod1 Shell 접속 후, Pod2로 Ping 통신 테스트 준비
(하) Pod1이 속한 노드(k8s-w1)에서 패킷 덤프 세팅: tunl0 – 터널 인터페이스에 파드간 IP 패킷 정보를 확인할 수 있음
결과
(중) Pod1 –> Pod2로 정상 통신 확인
(상) tunl0 인터페이스의 TX/RX 패킷 카운트가 각각 10개로 증가
(하) 실제 통신을 하게 되는 파드 간 IP 패킷 정보 확인
실제로 오버레이 통신을 하고 있는지 확인하기 위해 패킷덤프 명령어를 아래와 같이 수정하여 Ping 통신을 다시 하였고, 결과적으로 IP Outer(파란색 박스) 헤더 정보 안쪽에 Inner(빨간색 박스) 헤더가 1개 더 있음을 확인할 수 있다.
Calico 네트워크 모드
Calico Mode 요약
칼리코는 다양한 네트워크 통신 방법을 제공한다.
IPIP 모드
파드 간 통신이 노드와 노드 구간에서는 IPIP 인캡슐레이션을 통해 이루어진다.
단, Azure 네트워크에서는 IPIP 통신이 불가능하기 때문에 대신 VXLAN 모드를 사용한다고 한다.
Direct 모드
파드 통신 패킷이 출발지 노드의 라우팅 정보를 보고 목적지 노드로 원본 패킷 그대로 전달된다.
단, 클라우드 사업자 네트워크 사용 시, NIC에 매칭되지 않는 IP 패킷은 차단되니 NIC의 Source/Destination Check 기능을 Disable해야 정상 통신 가능 (AWS 문서 링크)
BGP 연동
Kubernetes 클러스터 내부 네트워크와 IDC 내부망 네트워크 간 직접 라우팅도 가능
VXLAN 모드
파드 간 통신이 노드와 노드 구간에서는 VXLAN 인캡슐레이션을 통해서 이루어진다.
다른 노드 간의 파드 통신은 vxlan 인터페이스를 통해 L2 프레임이 UDP – VXLAN에 감싸져 상대 노드로 도달 후 vxlan 인터페이스에서 Outer헤더를 제거하고 내부의 파드와 통신하게 된다.
BGP 미사용, VXLAN L3 라우팅을 통해서 동작한다.
UDP를 사용하므로 Azure 네트워크에서도 사용 가능하다.
Pod 패킷 암호화(네트워크 레벨)
Calico의 다양한 네트워크 모드 환경 위에서 WireGuard 터널을 자동 생성 및 파드 트래픽을 암호화하여 노드 간 전달한다.
Yaml 파일에 간단하게 추가하는 것만으로도 네트워크 레벨의 패킷 암호화를 설정할 수 있다.
이제 이미지도 준비되었고, yaml 파일만 생성하여 기동해보면 된다.
도커와는 다르게 쿠버네티스의 경우에는 쿠버네티스 클러스터 내에서 동작하기 때문에 생성된 컨테이너의 IP 또한 클러스터 내의 CNI 네트워크 대역으로 할당된다.
그렇기 때문에 외부에서 해당 컨테이너에 접근하여 서비스를 호출하려면 Service를 통해 가능하다. AWS나 GCP같은 Public Cloud의 경우에는 Service에서 LoadBalnancer를 제공하여 외부로 노출할 IP를 할당 받지만, 우리가 테스트하는 방식과 같이 Baremetal(On-Premise) 환경에서는 LoadBalancer 기능이 없다. 그래서 LoadBalancer타입을 지원하게끔 하기 위해 MetalLB라는 놈을 사용해주어야 한다.
=================================
metallb.yaml 파일을 이용하여 파드와 기타 등등의 서비스를 실행한다.
이후, metallb-system 네임스페이스에 있는 리소스들을 조회해본다.
=================================
root@master:~/yaml# kc get all -n metallb-system
NAME READY STATUS RESTARTS AGE
pod/controller-675d6c9976-d5k57 1/1 Running 0 9s
pod/speaker-h4l8n 1/1 Running 0 9s
pod/speaker-rm54l 1/1 Running 0 9s
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
daemonset.apps/speaker 2 2 2 2 2 beta.kubernetes.io/os=linux 9s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/controller 1/1 1 1 9s
NAME DESIRED CURRENT READY AGE
replicaset.apps/controller-675d6c9976 1 1 1 9s
이제 3-Tier환경의 컨테이너를 생성할 차례다.
yaml 파일의 경우 아래와 같다.
모든 항목들을 세세히 설명할 수는 없고 하나씩 찾아보면 기본적인 설정(포트/환경변수)만 되어있음을 볼 수 있다.
이 글에서는 가볍게 구성해보는 것이기 때문에 다음 글에서 좀 더 yaml 문법이나 파라미터 값을 공부해보아야 겠다.
(중략)
…
update-alternatives: using /usr/lib/jvm/java-11-openjdk-amd64/bin/unpack200 to provide /usr/bin/unpack200 (unpack200) in auto mode
update-alternatives: using /usr/lib/jvm/java-11-openjdk-amd64/lib/jexec to provide /usr/bin/jexec (jexec) in auto mode
Setting up libxdmcp-dev:amd64 (1:1.1.3-0ubuntu1) …
Setting up x11proto-core-dev (2019.2-1ubuntu1) …
Setting up libxcb1-dev:amd64 (1.14-2) …
Setting up libx11-dev:amd64 (2:1.6.9-2ubuntu1.2) …
Setting up libxt-dev:amd64 (1:1.1.5-1) …
1-3. JAVA_HOME 설정
> 현재 java -version으로 버전 확인 시 설치한 자바로 설정되어 있지 않기 때문에 아래와 같이 변경이 필요하다.
root@master:/home/src# java -version
openjdk version “1.8.0_292”
OpenJDK Runtime Environment (build 1.8.0_292-8u292-b10-0ubuntu1~20.04-b10)
OpenJDK 64-Bit Server VM (build 25.292-b10, mixed mode)
1-4. 소스 Build
> 이제 소스와 컴파일 할 JDK와 maven도 준비되었기 때문에 Compile을 해보도록 하자
소스 경로에 들어가 압축을 풀고 아래와 같이 빌드를 진행해준다.
빌드 전에 잠시 소스 수정이 필요하다. pom.xml에 mysql 연동 부분에 localhost:3306을 mysql-petclinic:3306으로 수정하자. was와 db가 다른 컨테이너로 기동되기 때문에 localhost를 인식할 수 없다. 그러나 mysql-petclinic은 컨테이너 명으로 link가 걸려 통신이 가능하다..
root@master:/home/src/spring-framework-for-petclinic/spring-framework-for-petclinic# mvn clean package -Dmaven.test.skip=true -P MySQL
…(중략)
[INFO] ————————————————————————
[INFO] BUILD SUCCESS
[INFO] ————————————————————————
[INFO] Total time: 16.802 s
[INFO] Finished at: 2021-11-07T13:54:37+09:00
[INFO] ————————————————————————
========================================================================= 빌드를 하고 나면, 소스 경로 하위의 target 디렉토리에 petclinic.war 소스 파일이 생성된다.
root@master:/home/src/spring-framework-for-petclinic/spring-framework-for-petclinic/target# ls -arlt|grep petclinic.war
-rw-r–r– 1 root root 41605349 11월 7 13:54 petclinic.war
1-5. WAS 이미지 생성
> 이제 만든 소스를 활용하여 tomcat 이미지를 만들어보도록 하자.
우선 이미지 생성을 위해 Dockerfile을 생성하고 이전에 만들었던 petclinic.war 파일을 같은 디렉토리에 위치시킨다.
root@master:/home/dockerfile/petclinic# pwd
/home/dockerfile/petclinic
root@master:/home/dockerfile/petclinic# ls -arlt
total 40644
drwxr-xr-x 5 root root 4096 11월 7 14:06 ..
-rw-r–r– 1 root root 41605349 11월 7 14:06 petclinic.war
-rw-r–r– 1 root root 64 11월 7 14:06 Dockerfile
drwxr-xr-x 2 root root 4096 11월 7 14:06 .
하기는 Dockerfile 내용이다.
root@master:/home/dockerfile/petclinic# cat Dockerfile
From tomcat:8-jre8
ADD petclinic.war /usr/local/tomcat/webapps/
> tomcat 컨테이너에서 mysql 컨테이너의 ip로 접속할 수 있겠지만, static ip가 아니기 때문에 mysql 컨테이너의 이름으로 접속을 해야 할 필요가 있다. 이럴 경우 link 옵션을 통해 컨테이너를 구동하면 tomcat 컨테이너에서 mysql 컨테이너로 이름으로 접속할 수 있다. link 옵션으로 구동하면 톰캣 컨테이너 안의 /etc/hosts에 링크된 mysql 컨테이너 hostname과 ip가 들어간다.
Windows OS에서 디스크 파티션을 조작할려면 [컴퓨터 관리]에 있는 [저장소] → [디스크 관리]를 사용하는 것이 일반적일 것입니다. 하지만 diskpart.exe라는 명령어를 이용해서도 똑같은 작업을 할 수 있습니다.
※ Diskpart는 파티션 작업 명령으로 데이터가 삭제되므로 중요 데이터 백업 및 확인후 사용토록 주의하시기 바랍니다.
Diskpart 란?
– Windows98이나 Windows ME에서 사용하던 Fdisk를 대체하는 파티션 툴로 동적 디스크를 지원하고, 디스크 관리 스냅인에서 지원하는 것보다 더 많은 작업을 수행할 수 있습니다. 디스크 관리 스냅인은 사용자가 실수로 데이터 손실을 초래할 수 있는 작업을 수행하지 못하도록 하지만, Diskpart를 사용하면 파티션과 볼륨을 명시적으로 제어할 수 있으며, 이런 기능 때문에 신중히 사용해 주셔야 합니다.
– 윈도우 XP, 2000, Vista, 7 이상 OS에서 사용 가능합니다. (위치 : C:\Windows\****32 폴더내 있습니다.)
Diskpart 사용 방법
1] Diskpart 모드 진입하기
1. **** 모드로 CMD 콘솔 실행합니다.
방법 : 시작 > 프로그램 및 파일 검색(또는 Windows 검색) 창에 ‘CMD’ 입력 > CMD 항목에 마우스 오른쪽 버튼 클릭 후 ‘**** 권한으로 실행’ 선택
2. diskpart 입력 후 엔터를 칩니다.
3. DISKPART> 프롬프트 발생하면 이후 사용 가능합니다.
2] 디스크 초기화하기
Diskpart 모드 진입 상태에서 명령어를 이용하여 하드디스크의 파티션을 모두 초기화합니다.
1. list disk : 디스크목록 보기
2. select disk 1 : 초기화할 disk를 선택합니다. (“sel disk 1” 와 동일)
3. list partition : 파티션정보 확인 (“list part” 와 동일)
4. clean : 선택된 디스크의 파티션정보를 전부 초기화
5. list partition : 파티션 정보 사라짐 확인
※ 여기서 포커스란 개념이 나옵니다. select 명령을 이용해 작업하고자 하는 객체에 포커스를 주어야 합니다. select disk 1 이라고 주고 list disk 하자 disk 1 옆에 * 가 붙었습니다. 앞으로 disk 1 이 작업대상이 된 겁니다. (select disk=1이라고 해도 됩니다.)
120000M 크기(size=120000)의 주파티션(primary partition)을 만들라(create)는 명령입니다. size 지정을 안하게 되면 이용가능한 모든 용량을 잡습니다. 파티션을 1개만 잡을 때 또는 마지막 파티션을 잡을 때는 size 옵션을 생략하면 됩니다. 주파티션은 4개까지 만들 수 있고, 그 이상을 만들려면 주파티션 1개 대신 확장파티션을 잡아야 합니다. 즉, 최대 주파티션 3개 확장파티션 1개가 됩니다. 확장파티션은 디스크당 1개만 만들 수 있습니다. 확장파티션에서 원하는 개수만큼 논리드라이브를 만듭니다.
※ 확장 파티션 설정
create partition extended : 확장파티션(extended partition)을 만들라(create)는 의미입니다. size 지정이 없으면 disk의 남은 용량을 전부 이용합니다. 확장 파티션에서는 반드시 1개 이상의 논리드라이브를 지정해 주어야 합니다. create partition logical size = 250 라고 하면 250메가의 논리드라이브(partition logical)가 생성되고, create partition logical size = 100 하면 100메가의 논리드라이브(partition ligical)가 추가 생성됩니다. create partition logical 이라고만 하면 나머지 용량을 모두 잡습니다. list partition을 입력하면 선택한 디스크의 파티션 정보를 볼 수 있습니다.
※ create partition 이후 디스크 관리에서 디스크1의 파티션에 포맷과 드라이브 문자 할당이 안 되어 있습니다.
4] 파티션 포맷하기
분할된 파티션을 포맷합니다.
1. format fs=ntfs quick : 현재 선택되어 있는 파티션을 ntfs로 빠른 포맷한다.
2. list partition : 파티션 선택 확인
3. select partition 1 : 포맷할 파티션 선택
4. format fs=ntfs quick : 선택한 파티션을 ntfs로 빠른 포맷합니다.
※ 참고로 fs=fat32로 하면 FAT32로 포맷합니다. (단, 30GB 이하일 경우에만 진행해야 합니다.)
5. 디스크 관리에서 포맷 완료는 확인되나, 아직 드라이브 문자 할당은 안된 상태로 보이게 됩니다.
5] 파티션[드라이브] 문자 할당
분할된 파티션에 드라이브명을 할당합니다.
1. assign letter=x : 선택되어 있는 파티션에 X 드라이브명 할당
2. list partition : 선택된 파티션을 확인
3. select partition 2 : 문자를 할당할 파티션을 선택
4. assign letter=Z : 선택되어있는 파티션에 Z드라이브명 할당
5. 디스크1의 파티션에 드라이브명이 할당된 것을 확인할 수 있습니다.
※ assign letter=X 명령어에서, letter=X 옵션을 안쓰면 차례로 미사용 문자가 할당됩니다. list volume을 입력하면 선택한 디스크의 볼륨(드라이브명)을 확인할 수 있습니다.
6] 파티션 삭제하기
분할된 파티션을 삭제합니다.
1. 파티션 4,5,6(볼륨 3,4,5)에 각각 X:, Y:, Z: 가 할당된 파티션입니다.
2. 파티션을 삭제합니다. 볼륨으로 지정하는 경우 드라이브명이 지정되어 있다면, 드라이브명을 쓸 수 있습니다. 볼륨 번호랑 파티션 번호가 다르니 혼동하지 않도록 주의하세요.
select volume z 볼륨 z에 포커스를 맞춥니다. (select volume=z 도 같음 “=” 생략 가능)
$ kubectl apply -f deploy/kubernetes/
clusterrole.rbac.authorization.k8s.io/system:aggregated-metrics-reader created
clusterrolebinding.rbac.authorization.k8s.io/metrics-server:system:auth-delegator created
rolebinding.rbac.authorization.k8s.io/metrics-server-auth-reader created
apiservice.apiregistration.k8s.io/v1beta1.metrics.k8s.io created
serviceaccount/metrics-server created
deployment.apps/metrics-server created
service/metrics-server created
clusterrole.rbac.authorization.k8s.io/system:metrics-server created
clusterrolebinding.rbac.authorization.k8s.io/system:metrics-server created
중간에 metrics.k8s.io라는 API가 생성되어 Api server에 등록된 것을 확인할 수 있습니다.
$ kubectl apply -f autoscaler.yaml
horizontalpodautoscaler.autoscaling/php-apache created
hpa커맨드를 통해 현재 hpa에 감지되는 시스템 부하정도와 관리하는 pod의 개수를 확인할 수 있습니다.
$ kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
php-apache Deployment/php-apache 0%/50% 1 10 1 18s
아직은 서버로 어떠한 요청도 하지 않았기 때문에, 현재 cpu소비량은 0%임을 알 수 있습니다. (TARGET은 deployment에 의해 제어되는 pod들의 평균을 뜻합니다.)
부하테스트
부하가 증가함에 따라 오토스케일러가 어떻게 반응하는지 살펴보겠습니다.
창을 하나 더 띄워서 php-apache 서비스에 무한루프 쿼리를 전송합니다.
$ kubectl run -it--rm load-generator --image=busybox /bin/sh
If you don't see a command prompt, try pressing enter.
/ #
/ # while true; do wget -q -O- http://php-apache.default.svc.cluster.local; done
OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!...
1~2분 지난 뒤에 hpa커맨드로 부하상태를 살펴보면 TARGET의 수치가 높아진 것을 확인할 수 있습니다.
$ kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
php-apache Deployment/php-apache 248%/50% 1 10 1 9m7s
그리고 deployment 컨트롤러를 확인해보면 pod의 replica수가 5개까지 늘어난 것을 확인할 수 있습니다.
$ kubectl get deploy php-apache
NAME READY UP-TO-DATE AVAILABLE AGE
php-apache 5/5 5 5 12m
busybox컨테이너를 띄운 터미널에서 Ctrl+C로 부하 발생을 중단시키고, 몇 분 후에 결과를 확인합니다.
$ kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
php-apache Deployment/php-apache 0%/50% 1 10 5 11m
cpu의 사용량이 0%까지 떨어졌고, deployment의 pod replica수도 1개로 줄어든 것을 확인할 수 있습니다.
$ kubectl get deploy php-apache
NAME READY UP-TO-DATE AVAILABLE AGE
php-apache 1/1 1 1 19m
kubernetes에서 HA를 구성하는 방법으로 stacked etcd, external etcd 두가지 방법이 있다. 그림 1의 stacked etcd는 control plane node에서 etcd가 작동하는 반면, 그림 2의 external etcd는 control plane node와 etcd가 다른 노드에서 작동한다. HA를 구성하기 위해서는 쿼럼이 과반수를 초과해야만 하기 때문에 최소 3대 이상(3,5,7,…)의 노드를 필요로 한다. 이번 시간에는 stacked etcd 를 구성하는 방법에 대해 알아보고자 한다.
[그림 1] HA 토폴로지 – stacked etcd[그림 1] HA 토폴로지 – external etcd
구성환경
Ubuntu 18.04.1, Docker 19.03.8, Kubernet v1.17.4
사전 준비
Docker, Kubernet이 미리 설치 되어 있어야한다.
로드 발란서(Load Balancer)
– dns 로드 발란서 사용, apisvr 라운드로빈(round-robin) 활용, 참고로 도메인은 hoya.com
apisvr IN A 192.168.0.160
IN A 192.168.0.161
IN A 192.168.0.162
–upload-certs : control plane 인스턴스에서 공유해야 하는 인증서를 업로드(자동배포), 수동으로 인증서를 복사할 경우는 이 옵션 생략
control plane 초기화(kubeadm init)를 진행하면 아래와 같은 내용이 출력될 것이다. 아래 내용을 복사해 놓도록 한다. 이 명령어를 이용하여 클러스터에 조인(join) 할수 있다. 파란색글씨(위쪽)는 control plane 노드에서 실행, 주황색 글씨(아래)는 worker node에서 실행
You can now join any number of control-plane node by running the following command on each as a root:
kubeadm join apisvr.hoya.com:6443 –token 9vr73a.a8uxyaju799qwdjv –discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866 –control-plane –certificate-key f8902e114ef118304e561c3ecd4d0b543adc226b7a07f675f56564185ffe0c07Please note that the certificate-key gives access to cluster sensitive data, keep it secret!
As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you can use kubeadm init phase upload-certs to reload certs afterward.
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join apisvr.hoya.com:6443 –token 9vr73a.a8uxyaju799qwdjv –discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866
참고: 인증서를 다시 업로드하고 새 암호 해독 키를 생성하려면 이미 클러스터에 연결된 control plane 노드에서 다음 명령을 사용하십시오.
shell> sudo kubeadm init phase upload-certs –upload-certs
W0322 16:20:40.631234 101997 validation.go:28] Cannot validate kube-proxy config – no validator is available
W0322 16:20:40.631413 101997 validation.go:28] Cannot validate kubelet config – no validator is available
[upload-certs] Storing the certificates in Secret “kubeadm-certs” in the “kube-system” Namespace
[upload-certs] Using certificate key:
7f97aaa65bfec1f039c4dbdf3a2073de853c708bd4d9ff9d72b776b0f9874c9d
참고 : 클러스터를 control plane 조인(join)하는 데 필요한 전체 ‘kubeadm join’ 플래그를 출력
shell> kubectl get nodes
NAME STATUS ROLES AGE VERSION
master1 Ready master 41s v1.17.4
master2 Ready master 3m59s v1.17.4
master3 Ready master 92s v1.17.4
shell>
** kubectl delete node로 control plane노드 를 제거하지 않도록 한다. 만약 kubectl delete node로 삭제하는 경우 이후 추가 되는 control plane 노드들은 HA에 추가 될수 없다. 그 이유는 kubeadm reset은 HA내 다른 control plane 노드의 etcd에서 etcd endpoint 정보를 지우지만 kubectl delete node는 HA 내의 다른 controle plane 노드에서 etcd endpoint 정보를 지우지 못하기 때문이다. 이로 인해 이후 HA에 추가되는 control plane 노드는 삭제된 노드의 etcd endpoint 접속이 되지 않기 때문에 etcd 유효성 검사 과정에서 오류가 발생하게 된다.
– control plane 노드를 kubectl delete node 로 삭제후 control plane 노드 추가시 오류 메시지
shell> kubeadm join ….. –control-plane –certyficate-key
… 생략 …
[check-etcd] Checking that the etcd cluster is healthy
error execution phase check-etcd: etcd cluster is not healthy: failed to dial endpoint https://192.168.0.159:2379 with maintenance client: context deadline exceeded
To see the stack trace of this error execute with –v=5 or higher