Certified Kubernetes Administrator (CKA) with Practice Tests (강의 링크, 레퍼런스 노트)
- 평소 강의 할인도 많이 하고, 연습문제도 풀어볼 수 있으니 실제 강의 수강을 추천
- 아래는 강의 내용 번역 및 정리본 (문제 시 댓글로 알려주세요)
네트워크 기본 (선행 개념)
스위칭과 라우팅
스위칭 (Switching)
- 2 개의 시스템을 연결할 때 스위치 사용
- 스위치가 네트워크를 생성해 두 시스템을 연결
- 스위치와 연결하기 위해서는 각 호스트마다 인터페이스 필요
ip link
: 인터페이스 확인 명령어
ip addr add [호스트 ip 주소] dev eth0
: 각 시스템에 ip 주소 할당
- ip 주소가 할당되고 네트워크로 연결된다면 스위치를 통해 두 시스템이 통신 가능
ping [호스트 ip 주소]
: 통신 가능 여부 확인
- 스위치는 네트워크 내에서만 통신을 가능하게 할 수 있음
- 한 호스트로부터 패킷을 받아 같은 네트워크에 있는 다른 시스템에 전달
라우팅 (Routing)
- 다른 네트워크들을 연결하는 장치
- 여러 네트워크 포트를 가진 별개의 서버라고 생각할 수 있음
- 라우터는 연결된 네트워크마다 다른 IP를 가짐 (게이트웨이)
- 라우팅 테이블에 정의된 내용을 통해 다른 네트워크에 존재하는 시스템끼리 통신 가능
route
: 라우팅 테이블 확인
ip route add [스위치 ip 주소] via [라우터 게이트웨이 ip 주소]
: 다른 네트워크 연결, 라우팅 테이블에 해당 내용 작성됨
- 모든 시스템에 대해 이러한 설정(configuration) 이루어져야 함
- e.g. 인터넷과 연결하고자 한다면 스위치 ip 주소에 인터넷 ip 주소 사용할 수 있음
- 라우터가 없이 세 개의 호스트가 있고 두 개의 호스트가 다른 하나로 연결되어 있을 때, 네트워크 IP와 호스트 인터페이스 ip 주소를 연결할 수 있음
- 일반적으로 받은 패킷을 다른 호스트로 포워드하지 못하지만, 설정을 바꿔주면 가능
echo 1 > /proc/sys/net/ipv4/ip_forward
: 기본값 0
- /etc/sysctl.conf의 net.ipv4.ip_forward 값 변경
- 기본 게이트웨이 (Default gateway)
- 외부의 어떠한 네트워크로부터 오는 요청이라도 라우터를 통과할 수 있게 함 (일일이 지정할 필요 없음)
ip route add default via [라우터 게이트웨이 ip 주소]
- default 대신 0.0.0.0으로 표현할 수 있음
명령어
ip link
: 호스트의 인터페이스를 나열하고 수정
ip addr
: 인터페이스에 할당된 ip 주소 확인
ip addr add 192.168.1.10/24 dev eth0
: 인터페이스에 ip 주소 할당
- 해당 명령어들은 재시작 전까지만 효력을 발휘
- 영구적 변경을 원한다면 etc/network/interface 수정 필요
ip route
혹은 route
: 라우팅 테이블 확인
ip route add 192.168.1.0/24 via 192.168.2.1
: 라우팅 테이블에 엔트리 추가
cat /proc/sys/net/ipv4/ip_forward
: 라우터처럼 설정된 호스트가 있을 때 ip 포워딩이 가능한지 여부 확인 (0일 경우 불가능)
DNS
- 호스트를 호출할 때 ip 주소 대신 이름을 사용
- /etc/hosts에 ip 주소와 이름을 엔트리로 작성함으로써 이름 사용 가능
- 하나의 ip 주소에 여러 개의 이름을 사용할 수 있음 (별도의 엔트리로 작성)
- 호스트마다 별개의 /etc/hosts 파일을 관리하는 대신 DNS 서버를 두어 한꺼번에 관리
- 모든 호스트의 /etc/resolv.conf에 DNS 변환 설정 (resolution configuration) 파일 추가
- e.g. nameserver [DNS 서버 ip 주소] 와 같이 엔트리 작성
- 호스트의 /etc/hosts와 DNS에 동일한 이름 있을 경우
- 로컬 파일을 먼저 확인, 엔트리 찾으면 해당 엔트리를 이용 (없을 시 DNS 확인)
- 순서는 /etc/nsswitch.conf 파일에서 수정 가능 (hosts 항목 확인)
- 호스트와 DNS에 모두 없는 이름일 경우
- 호스트의 /etc/resolv.conf에서 nameserver 8.8.8.8 엔트리 등록 가능
- 8.8.8.8은 구글에서 제공하는, 인터넷 상 모든 웹사이트를 알고 있는 공공 네임서버
- 혹은 DNS에서 Forward All to 8.8.8.8을 파일의 가장 하단에 작성할 수도 있음
도메인 이름
- e.g. www.facebook.com
- 공공 인터넷에서 우리가 기억할 수 있도록 ip 주소가 이름으로 변환된 것
- 상위 단계 도메인
- .com: 상업적 혹은 일반적 이용
- .net: 네트워크
- .edu: 교육기관
- .org: 비영리 기관
- .io
- 서브 도메인
- 추가적인 그룹핑을 도와줌
- e.g. www, drive, maps, apps, mail, ...
도메인 탐색
- 상위 단계에서부터 서브 도메인까지 각기 다른 DNS 서버를 지나오면서 올바른 IP 주소를 찾음
- e.g. com -> google -> app 순서
- 찾은 결과를 짧은 시간동안 캐시에 저장하고 사용하기도 함
- 내부 도메인 서버에서 192.168.1.10의 도메인을 web.mycompany.com으로 지정했지만 web이라는 간단한 이름으로 찾고 싶을 때
- 호스트의 /etc/resolv.conf에서 search mycompany.com 엔트리를 작성해줄 수 있음
- mycompany.com은 추가적으로 붙이고 싶은 도메인 이름을 의미
- 붙이고 싶은 도메인 이름은 여러 개를 작성해줄 수도 있음
레코드 타입
- A
- 이름과 IP 주소 (e.g. 192.168.1.1) 매핑
- AAAA
- CNAME
nslookup, dig
nslookup www.google.com
: DNS 서버에서 호스트 이름을 검색할 때 사용
- nslookup은 로컬 /etc/hosts 파일은 검색하지 못함
dig www.google.com
: DNS 서버에서 호스트 이름 검색, 더욱 자세한 내용 조회
CoreDNS
- 호스트를 DNS 서버로 설정하는 것을 도와주는 여러 솔루션 중 하나
- 깃허브 페이지 혹은 도커 이미지 형식으로 CoreDNS 바이너리 파일 다운로드 가능
네트워크 네임스페이스
- 네임스페이스
- 호스트가 집이라면, 네임스페이스는 집 안의 격리된 방
- 각 네임스페이스는 자신이 수행하는 프로세스만 확인할 수 있음 (
ps aux
)
- 호스트에서 동일 명령어를 사용하면 모든 네임스페이스의 프로세스 확인 가능
- 네트워크 네임스페이스
- 호스트는 로컬 네트워크와 연결하는 인터페이스, 라우팅 테이블, ARP 테이블을 가짐
- 컨테이너가 생성되면 네트워크 네임스페이스를 만들어 호스트의 네트워크 관련 정보를 컨테이너가 볼 수 없게 함
- 컨테이너는 가상 인터페이스, 라우팅 테이블, ARP 테이블을 별도로 가짐
명령어
ip nets add [네임스페이스명]
: 네트워크 네임스페이스 생성
ip netns exec [네임스페이스명] ip link
: 네임스페이스 내에서 인터페이스 정보 확인
ip -n [네임스페이스명] ip link
또한 동일한 명령어
ip netns exec [네임스페이스명] arp/route
: 네임스페이스 내에서 ARP 테이블, 라우팅 테이블 정보 확인
네임스페이스 연결 (2개)
- 가상의 이더넷 쌍 혹은 케이블 사용해 연결 가능 (파이프라고 일컬어짐)
ip link add [인터페이스명1] type veth peer name [인터페이스명2]
: 두 개의 인터페이스 연결
ip link set [인터페이스명] netns [네임스페이스명]
: 인터페이스를 각각 해당되는 네임스페이스에 연결
ip -n [네임스페이스명] addr add [ip주소] dev [인터페이스명]
: ip 주소 할당
ip -n [네임스페이스명] link set [인터페이스명] up
: 링크 업, 네임스페이스가 서로 통신 가능
ip -n [네임스페이스명] link del [인터페이스명]
: 브릿지를 활용할 때 케이블 필요없어 삭제
네임스페이스 연결 (n개)
- 리눅스 브릿지를 활용해 여러 개의 네임스페이스를 연결할 수 있음
ip link add [브릿지명] type bridge
ip link set dev [브릿지명] up
- 네임스페이스에게는 스위치 역할, 호스트에게는 인터페이스 역할
ip link add [인터페이스명1] type veth peer name [브릿지 인터페이스명1]
: 네임스페이스마다 지정
ip link set [인터페이스명] netns [네임스페이스명]
ip link set [브릿지 인터페이스명] master [브릿지명]
ip -n [네임스페이스명] addr add [ip주소] dev [인터페이스명]
ip -n [네임스페이스명] link set [인터페이스명] up
ip addr add [브릿지 ip주소] dev [브릿지명]
: 호스트와 모든 네임스페이스 연결 (브릿지 이용)
네임스페이스와 외부의 LAN 네트워크 연결
- 호스트와 브릿지를 연결해놓았다면 호스트가 일종의 게이트웨이 역할을 수행
ip netns exec [네임스페이스명] ip route add [외부 LAN ip 주소] via [브릿지와 로컬 호스트 인터페이스 ip 주소]
- 로컬 호스트는 브릿지와 연결된 인터페이스와 외부 네트워크와 연결된 인터페이스를 가짐 (총 2개)
- 명령어 수행 시 네임스페이스에서 외부 LAN 네트워크로 ping은 보낼 수 있으나 NAT 기능 수행 불가
iptables -t nat -A POSTROUTING -s [브릿지 ip 주소] -j MASQUERADE
- NAT IP 테이블에 새로운 규칙 추가
- 소스 네트워크로부터 오는 모든 패킷의 from address를 교체
- 이를 통해 외부 네트워크와 통신 가능
ip netns exec [네임스페이스명] ip route add default via [브릿지와 로컬 호스트 인터페이스 ip 주소]
- 호스트를 기본 게이트웨이로 설정함으로써 외부 인터넷 또한 접속 가능함
iptables -t nat -A PREROUTING --dport 80 --to-destination [네임스페이스 ip주소:80] -j DNAT
- 외부의 호스트가 다른 호스트에 있는 네임스페이스와 통신하고 싶은 경우 해당 규칙을 지정해줄 수 있음
- 로컬 호스트에서 포트 80으로 들어오는 트래픽은 모두 해당 네임스페이스로 포워드한다는 뜻
도커 네트워킹
docker run --network none [이름]
- 컨테이너는 외부 네트워크 및 다른 컨테이너와 통신 불가
docker run --network host [이름]
- 포트 80을 사용하는 컨테이너를 실행할 경우, 호스트에서 추가적인 포트 매핑 없이 사용 가능
- 두 개의 프로세스가 동시에 같은 포트를 사용할 수는 없음 (컨테이너의 인스턴스 하나만 가능)
docker run [이름]
- 호스트와 컨테이너가 붙어있는 내부적인 프라이빗 네트워크(브릿지)가 생성됨
- 브릿지는 기본적으로 172.17.0.0 주소를 가짐
브릿지
docker network ls
: bridge라는 이름으로 조회됨
ip link
: docker0이라는 이름으로 조회됨
- docker0는 기본적으로 172.17.0.1를 ip 주소로 부여받음 (
ip addr
)
ip netns
: 도커는 컨테이너 실행 시 네트워크 네임스페이스를 생성
docker inspect [컨테이너 ID]
: 네트워크 네임스페이스 확인 가능
브릿지와 컨테이너의 네임스페이스 연결하기
ip link
: 브릿지의 인터페이스 엔드 확인 가능
ip -n [네트워크 네임스페이스명] link
: 네트워크 네임스페이스의 엔드 확인 가능
외부 사용자와 컨테이너 연결하기
docker run -p 8080:80 [컨테이너명]
: 도커 호스트 8080과 컨테이너의 포트(80)를 연결
curl http://[도커 호스트 IP]:8080
: 외부 사용자 또한 컨테이너의 어플리케이션 접근 가능
CNI
네트워크 네임스페이스 동작순서
- 네트워크 네임스페이스 생성
- 브릿지 네트워크/인터페이스 생성
- VETH 쌍 생성 (파이프, 가상 케이블)
- vEth를 네임스페이스에 연결
- 다른 vEth를 브릿지에 연결
- IP 주소 할당
- 인터페이스를 사용중(up)으로 변경
- NAT -IP Masquerade 사용 가능하도록 변경
CNI
- 위의 2-8 과정을 브릿지 네트워크 생성 과정으로 묶고 프로그램화할 수 있음 (프로그램 = 플러그인)
bridge add [컨테이너 ID] [네임스페이스명]
- CNI는 프로그램이 컨테이너 런타임 엔진에서 네트워킹을 잘 수행하도록 일련의 기준을 제시
- 플러그인이 어떻게 개발되어야 하고 컨테이너 런타임이 어떻게 그것을 수행해야 하는지를 정의
- CNI를 지원하는 컨테이너 런타임 엔진
- CNI를 지원하는 플러그인 종류
- BRIDGE, VLAN, IPVLAN, MACVLAN, WINDOWS
- DHCP, host-local (IPAM 플러그인)
- weaveworks, flannel, cilium, NSX, ...(제 3 기관)
- 도커는 CNI를 지원하지 않음 (Container Network Model; CNM 지원)
docker run --network=cni-bridge [컨테이너명]
: 네트워크 플러그인 이런 방식으로 사용 불가
docker run --network=none [컨테이너명]
후 수동으로 bridge add [컨테이너ID] [네임스페이스명]
진행해줘야 함
- 쿠버네티스 또한 도커 컨테이너를 만들 때 이런 순서를 따름
쿠버네티스
클러스터 노드 네트워킹
- 마스터 노드, 워커 노드는 네트워크에 연결된 1개 이상의 인터페이스를 가짐
- 인터페이스는 IP를 가짐
- 호스트는 유일한 호스트명과 MAC 주소를 가짐
- 오픈하는 포트
- kube-api: 6443
- 해당 포트로 외부 사용자, kubectl, kubelet, kube-scheduler, kube-controller-manager 등의 요청을 받음
- kubelet: 10250
- kube-scheduler: 10259
- kube-controller-manager: 10257
- ETCD: 2379
- 마스터 노드가 여러 개일 때 2380 또한 사용
- ETCD 클라이언트가 서로 통신하기 위한 목적
- Services (워커 노드): 30000-32767
명령어
ip link
ip address
혹은 ip addr
혹은 ip a
- 인터페이스의 IP 주소 확인 가능
- 인터페이스의 MAC 주소 확인 가능 (show 옵션)
- controlplane이 아닌 다른 노드를 확인하고 싶다면 ssh 필요
ip address show type bridge
ip addr add [ip주소] dev [인터페이스]
ip route
혹은 route
- 라우팅 정보 확인 가능 (기본 게이트웨이 포함)
netstat
- -l 옵션: 듣고 있는 포트 정보 확인 가능
- -p 옵션: 프로그램 이름 혹은 PID 정보 확인 가능
- -n 옵션: don't resolve names (numeric)
- e.g.
netstat -npl | grep -i scheduler
- -i는 대소문자 구분 없음을 의미
- 스케줄러가 어떤 포트를 듣고 있는지 확인 가능
파드 네트워킹
- 노드를 연결하는 네트워크 말고도 파드를 연결하는 네트워크 또한 필요
- 네트워킹 모델
- 모든 파드는 IP 주소를 가져야 함
- 모든 파드는 같은 노드에 위치한 다른 파드와 통신 가능해야 함
- 모든 파드는 NAT 없이 다른 노드에 있는 다른 파드와 통신 가능해야 함
- flannel, NSX, weaveworks 등 네트워킹 솔루션 사용 가능
네트워킹 모델 구성 및 명령어
- 노드를 연결하는 LAN 네트워크
- 세 개의 노드
- node1 (192.168.1.11) 에 컨테이너 2개 (10.244.1.2, 10.244.1.3)
- node2 (192.168.1.12) 에 컨테이너 1개 (10.244.2.2)
- node3 (192.168.1.13) 에 컨테이너 1개 (10.244.3.2)
- 노드마다 브릿지 네트워크 생성 및 활성화
ip link add v-net-0 type bridge
ip link set dev v-net-0 up
- 브릿지 인터페이스에 IP 주소 설정 (노드마다)
ip addr add 10.244.1.1/24 dev v-net-0
ip addr add 10.244.2.1/24 dev v-net-0
ip addr add 10.244.3.1/24 dev v-net-0
- 파이프 혹은 가상 네트워크 케이블로 컨테이너를 브릿지에 연결
- 노드마다 스크립트로 만들어 사용 가능
ip link add ...
: veth 쌍 생성
ip link set ...
: veth를 각각의 인터페이스에 붙이기
ip -n [네임스페이스] addr add ...
: ip 주소 할당
ip -n [네임스페이스] route add ...
: ip 주소 할당
ip -n [네임스페이스] link set ...
: 인터페이스 활성화
- 다른 노드의 컨테이너 접근 가능하도록 라우팅 설정 (방법 1, 비추천)
node1$ ip route add 10.244.2.2 via 192.168.1.12
node1$ ip route add 10.244.3.2 via 192.168.1.13
node2$ ip route add 10.244.1.2 via 192.168.1.11
node2$ ip route add 10.244.3.2 via 192.168.1.13
- ...
- 각 서버에서 라우팅을 설정하는 것보다 라우터의 라우팅 테이블 활용하는 것이 편리 (방법 2, 추천)
- 모든 호스트는 기본 게이트웨이를 사용하도록 지정
- e.g. 네트워크 10.244.1.0/24 (브릿지)의 게이트웨이는 192.168.1.1 (노드)
- 10.244.0.0/16 이라는 하나의 거대한 네트워크를 생성하게 됨
CNI
- 컨테이너 혹은 파드 생성 시 CNI 표준에 맞춰서 위와 같은 명령어를 가진 스크립트를 생성할 수 있음
- ADD 섹션에 파이프 생성, 파이프 인터페이스에 붙임, IP 주소 할당, 인터페이스 활성화 등 포함
- DEL 섹션에 파이프 삭제 포함
- 컨테이너 런타임이 컨테이너를 생성 시
- /etc/cni/net.d/net-script/conflist에서 스크립트 이름을 확인
- /opt/cni/bin에서 스크립트 확인
- ./[스크립트명].sh add [컨테이너][네임스페이스]로 컨테이너 생성
쿠버네티스에서의 CNI
- CNI
- 컨테이너 런타임은 네트워크 네임스페이스를 만들어야 함
- 컨테이너가 붙는 네트워크를 확인해야 함
- 컨테이너 런타임은 컨테이너가 추가 혹은 삭제될 때 네트워크 플러그인 (브릿지)를 작동시켜야 함
- 네트워크 환경설정(configuration)은 JSON 형태여야 함
- CNI 설정 확인
- kubelet.service 파일의 --network-plugin에서 확인 가능
ps -aux | grep kubelet
에서도 확인 가능
- 바이너리 파일은 기본적으로 /opt/cni/bin에 저장
- 어떤 플러그인이 설정되어 있는지는 /etc/cni/net.d에서 확인 가능
Weaveworks
CNI
- 각 노드마다 에이전트를 배치, 각 에이전트는 서로 통신 가능
- 다른 노드의 파드와 IP 정보 등 셋업의 토폴로지 갖고 있음
- 패킷을 인터셉팅해 새로운 주소로 갈음 및 캡슐화, 다른 노드로 전송
Weave 배포
- pod 형태로 배포하는 것이 편리
kubectl apply -f https://github.com/weaveworks/weave/releases/download/v2.8.1/weave-daemonset-k8s.yaml
- daemonset으로 배포되어 클러스터의 모든 노드에 각각 하나의 파드가 배포되도록 함
- weave peers
kubectl get pods -n kube-system
- weavenet에서 배포한 파드들을 확인할 수 있음 (weave peers)
kubectl logs [pod명] weave -n kube-system
- 로그 확인 또한 가능 (e.g. IP 주소 범위 등)
IP 주소 관리
- CNI는 수동이 아니라 자동으로 IP 주소를 관리할 수 있는 2개의 빌트인 플러그인 제공
- DHCP, host-local
- 스크립트에 ip = get_free_ip_from_host_local()처럼 플러그인을 실행하는 코드 작성해 사용할 수 있음
- 혹은 cat /etc/cni/net.d/[스크립트명].conf의 IPAM에서 플러그인 종류를 정의할 수 있음
- e.g. ipam > type, subnet, routes, ..
- weaveworks의 경우 기본적으로 10.32.0.0/12 범위의 네트워크를 사용
- 10.32.0.1 > 10.47.255.254
- 피어가 각 노드에 해당 IP의 범위를 나누어 사용
- 참고: node01에 pod를 스케줄링하고 기본 게이트웨이를 확인하고 싶다면
kubectl run [pod명] --image=[image명] --dry-run=client -o yaml > [파일명].yaml
처럼 yaml 파일 생성
- spec > nodeName: node01 작성
kubectl apply -f [파일명].yaml
으로 pod 생성
kubectl exec [pod명] -- ip route
로 기본 게이트웨이 확인 가능
서비스 네트워킹
- 파드가 다른 파드가 호스팅하는 서비스에 접근하고 싶다면, 서비스(Service) 활용 가능
- 서비스 IP 혹은 서비스명으로 접근 가능
- e.g. 블루 파드가 오렌지 파드에 접근하고 싶다면, 오렌지 서비스의 IP 혹은 이름으로 접근 가능
- ClusterIP
- 클러스터 내부에 존재하는 파드라면 ClusterIP 서비스에 어디서든 접근 가능
- 파드가 어떤 노드에 위치해있는지와 무관
- NodePort
- ClusterIP와 마찬가지로 클러스터 내의 파드라면 어디서든 접근 가능
- 이에 더하여, 모든 노드의 포트를 통해 서비스를 노출시켜 외부 사용자 또한 접근 가능
- 파드 vs. 서비스
- 파드의 컨테이너는 IP를 할당한 인터페이스와 네임스페이스를 가짐
- 서비스는 클러스터 전체에서 사용되기 때문에 인터페이스, 네임스페이스 등이 없음
Kube-proxy, IP 주소 범위
- 각 노드의 kube-proxy가 서비스의 IP:Port로 들어오는 요청을 파드의 IP로 포워드 (규칙 생성)
kube-proxy --proxy-mode [userspace | iptables | ipvs]
- 프록시 모드를 정의하지 않는다면 기본값은 iptable
kubectl logs [pod명] -n kube-system
iptables -L -t nat | grep [서비스명]
- 서비스의 IP:port로 들어오는 요청을 어떤 IP(pod)로 포워드하는지 확인 가능 (DNAT 규칙)
- 서비스가 생성될 때 부여받는 IP 주소의 범위 확인
kube-api-server --service-cluster-ip-range ipNet
ps aux | grep kube-api-server
cd /etc/kubernetes/manifests/kube-api-server.yaml
- 기본값: 10.0.0.0/24
kubectl get all --all-namespaces
- pod, daemonset, deployment, service, replicaset 등의 정보를 모두 조회 가능
쿠버네티스에서의 DNS
- 쿠버네티스는 클러스터 구성 시 자동으로 빌트인 DNS 서버를 배포
- DNS를 생각할 때 Pod와 Service만 염두에 두면 됨 (노드에 대해 고려할 필요 없음)
- 모든 pod와 service가 서로 통신 가능하기 때문
- DNS 서버에 호스트명(web-service), ip 주소(10.107.37.188) 정보가 있다고 가정
- 네임스페이스가 같을 경우 호스트 이름으로 호출 가능
curl http://web-service
- pod의 경우 호스트 이름은 IP 주소에서 .을 -로 변경한 버전이 사용됨 (e.g. 10-244-1-5)
- 네임스페이스가 다를 경우 호스트 이름.네임스페이스로 호출 가능
curl http://web-service.apps
- DNS 서버는 호스트명, IP 주소 외에도 여러 서브 도메인 정보를 가질 수 있음
- 네임스페이스, 타입(e.g. svc, pod) 등
curl http://web-service.apps.svc
- DNS 서버는 기본적으로 cluster.local이라는 루트 도메인 정보를 가짐
curl http://web-service.apps.svc.cluster.local
CoreDNS
- 호스트마다 /etc/hosts로 DNS를 관리하는 것은 어려움
- 이를 해결하기 위해 중앙 DNS 서버를 사용
- 각 호스트의 /etc/resolv.conf에 namerserver 정보 (DNS 서버) 제공
- CoreDNS는 pod의 형태로 배포됨 (2개의 replicaset)
- /etc/coredns/Corefile에 플러그인 정보들 포함
- kubernetes cluster.local ... { # CoreDNS가 쿠버네티스에서 잘 작동하도록 함
- pods insecure ...} # pod를 DNS 서버 레코드에 추가할 때 이름을 IP 주소의 .을 -로 변경한 값 사용
- proxy . /etc/resolve.conf # 모르는 주소를 호출할 때 resolve.conf에 있는 na meserver에 넘겨줌
- 해당 파일은 configmap 객체의 형태로 pod에서 사용됨
- 수정이 필요할 시 configmap을 수정하면 됨
- CoreDNS는 다른 요소들이 접근 가능하도록 kube-dns라는 이름을 가진 서비스를 배포
- 각 호스트의 /etc/resolv.conf에 nameserver IP 주소로 해당 서비스의 IP 주면 됨
- /etc/resolv.conf에 search 엔트리를 등록할 수 있음
- e.g. search default.svc.cluster.local svc.cluster.local cluster.local
인그레스
서비스 vs. 인그레스
- 두 가지 서비스를 제공하는 홈페이지가 있다고 가정 (wear, video)
- wear 기능을 담당하는 pod는 deployment로 감싸져 있고, video 기능을 담당하는 pod 또한 별개의 deployment로 배포됨
- 트래픽이 많아지면 deployment 안의 pod가 많아짐
- service는 해당 deployment를 외부에 노출 (NodePort), 트래픽이 많아지면 LoadBalancer 역할을 수행
- 서비스에서는 30000 이상의 높은 숫자의 포트만 사용 가능
- 별도의 프록시 서버 혹은 로드밸런서를 이용해 사용자의 서비스 접근을 용이하게 함
- 인그레스란, 사용자로 하여금 단일한 URL을 통해 어플리케이션에 접근 가능하도록 하는 기능
- SSL 보안 또한 편리하게 적용할 수 있음
- 일종의 로드밸런서 역할을 하는 서비스 상단의 레이어라고 생각할 수 있음
- 외부에서 접근 가능하도록 노출시켜야 하기 때문에, NodePort(서비스) 혹은 클라우드 기반의 로드밸런서로 퍼블리시해야 함
Ingress
- 지원 가능한 솔루션을 배포 (e.g. traefik, haproxy, nginx, ..)
- 인그레스를 환경설정하기 위한 규칙을 명세화
- ingress resources (yaml 파일 이용)
Ingress Controller
- 쿠버네티스에서 기본으로 배포해주는 ingress controller 없음
- e.g. GCE (GCP HTTP(S) Load Balancer), Contour, Haproxy, Nginx, traefik, Istio
- 쿠버네티스 프로젝트에서 GCE, Nginx 지원 중
- Nginx-ingress-controller를 deployment로 배포할 수 있음
- apiVersion: extensions/v1beta1
- kind: Deployment
- metadata:
- name: nginx-ingress-controller
- spec:
- replicas: 1
- selector:
- template:
- metadata:
- spec:
- containers:
- -name: nginx-ingress-controller
- image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.21.0
- args:
- -/nginx-ingress-controller # nginx 프로그램이 해당 경로에 위치, 해당 서비스를 시작하려면 명령어로 이 내용 넣어주어야 함
- --configmap=$(POD_NAMESPACE)/nginx-configuration
- env: # configuration 데이터를 pod 안에서 읽기 위해 필요한 정보
- -name: POD_NAME
- valueFrom:
- fieldRef:
- fieldPath: meatadata.name
- -name: POD_NAMESPACE
- valueFrom:
- fieldRef:
- fieldPath: meatadata.namespace
- ports: # ingress-controller에 의해 사용되는 포트 정보
- -name: http
- containerPort: 80
- -name: https
- containerPort: 443
- Nginx의 환경설정 데이터를 컨트롤러 이미지와 분리시키기 위해 Configmap 객체 사용
- Nginx Configuration: err-log-path, keep-alive, ssl-protocols, ...
- apiVersion: v1
- kind: ConfigMap
- metadata:
- name: nginx-configuration
- Ingress Controller를 외부에 노출시키기 위한 서비스 필요
- apiVersion: v1
- kind: Service
- metadata:
- spec:
- type: NodePort
- ports:
- -port: 80
- targetPort: 80
- protocol: TCP
- name: http
- -port: 443
- targetPort: 443
- protocol: TCP
- name: https
- selector:
- Ingress Controller가 리소스를 모니터링하고 변화가 있을 때 서버를 환경설정 하기 위해서는 서비스 계정 필요 (Roles, ClusterRoles, RoleBindings)
- apiVersion: v1
- kind: ServiceAccount
- metadata:
- name: nginx-ingress-serviceaccount
Ingress Resources
- 트래픽을 어떻게 라우팅할지 결정할 수 있음
- 각 호스트 혹은 도메인명에 따라서 별개의 규칙이 존재
- e.g. www.my-online-store.com은 규칙 1, www.wear.my-online-store.com은 규칙 2, ...
- 각 규칙 내에서 URL을 기반으로 트래픽을 라우팅
- e.g. 규칙 1에서 www.my-online-store.com/wear, www.my-online-store.com/watch 등 다른 경로에 따라 라우팅
단순 포워드
- apiVersion: networking.k8s.io/v1
- kind: Ingress
- metadata:
- spec:
규칙 기반 라우팅 (규칙 1개)
- 단일 도메인명, 즉 규칙이 있고 (www.my-online-store.com) /wear, /watch라는 2개의 경로 존재
kubectl create ingress [ingress명] --rule="host/path=service:port"
- 최근 버전에서는 이렇게 ingress resource를 생성할 수도 있음
- apiVersion: networking.k8s.io/v1
- kind: Ingress
- metadata:
- spec:
- rules:
- -http:
- paths:
- -path: /wear
- pathType: Prefix
- backend:
- -path: /watch
- backend:
- service:
- name: watch-service
- port:
규칙 기반 라우팅 (규칙 2개)
- 2개의 도메인명이 있고 (wear.my-online-store.com, watch.my-online-store.com) 각 규칙마다 하나의 경로만 존재
- apiVersion: networking.k8s.io/v1
- kind: Ingress
- metadata:
- spec:
- rules:
- -host: wear.my-online-store.com
- http:
- -host: watch.my-online-store.com
- http:
- paths:
- -backend:
- service:
- name: watch-service
- port:
명령어로 ingress resource 만들기
- 다른 네임스페이스에 새로운 어플리케이션이 생긴다면, 그에 맞춰 해당 네임스페이스에 ingress resource 생성해줘야 함
- 해당 어플리케이션의 서비스명과 서비스 포트를 알아야 함
kubectl create ingress [ingress명] -n [네임스페이스명] --rule="[path]=[서비스명]:[서비스포트]"
- e.g.
kubectl create ingress ingress-pay -n critical-space --rule="/pay=pay-service:8282"
- metadata > annotations > nginx.ingress.kubernetes.io/rewrite-target: /
- 해당 내용을 yaml 파일에 추가해 경로가 제대로 작동하도록 수정할 수 있음