들어가며
이번 글에서는 Kubernetes Network에 대해 스터디에서 배운 내용을 정리하도록 한다.
Kubernetes는 클러스터 내부 통신을 위해 Network Plugin을 사용한다. 플러그인은 CNI(Container Network Interface)를 사용한 다양한 오픈소스를 이용하는데, 그중 Calico를 많이 사용하는 것 같다. 사내에 구축한 Kubernetes Cluster 역시 Calico 기반이다.
Kubernetes Pod는 Container들로 구성되는데 Pod의 Pause 컨테이너를 통해 하나의 IP를 할당할 수 있다.
(Container 개별적으로 접근하려면 Port를 이용해야 한다.)
Pod 들은 Node(Host)의 이더넷 카드를 이용하여 외부로 통신한다. 여기서 외부는 클러스터 안이 될 수도 있고, 클러스터 바깥이 될 수도 있다. 클러스터 안에서 통신을 하기 위해선 Overlay Network를 거쳐야한다. (Overlay Network는 앞서 이야기한 노드들의 가상 네트워크 인터페이스와 bridge와 라우팅 rule 조합을 일컫는다. - 참고: 커피고래님의 블로그) 클러스터 바깥으로 통신하려면 Kubernetes service를 이용해야 한다.
여기까지가 Kubernetes Network에 대해 자주 접할 수 있는 정보이고, 기본적으로 필자가 알고 있던 개념이었다. 그래서 이번 스터디가 진행되기 전에는 이러한 Overview 적인 내용을 다룰 것이라고 생각했는데.. 그것보다 훨씬 신선하고 유용한 내용들을 알게 되었다. 그것은 바로 갓(GOD) AWS VPC CNI !
AWS VPC CNI
AWS VPC CNI는 클러스터 내의 모든 Pod와 통신할 때 Overlay Network를 거치지 않고, 직접 통신을 할 수 있다.
이를 가능하게 하는 건 Node와 Pod에 동일한 네트워크 대역을 할당하기 때문이다. 이를 통해 Overlay Network를 거치면서 발생하는 Packet Overhead를 없애고 네트워크 통신의 성능을 향상한다.
클러스터 내부 환경에서도 다음과 같이 NAT를 거치지 않고 직접 통신한다.
클러스터 외부 환경으로 통신할 때는 워커노드의 IP로 통신한다.
워커 노드에 생성 가능한 최대 파드 개수
워커 노드에 생성 가능한 최대 파드 개수는 할당 가능한 IP 수와 머신의 리소스에 따라 좌우된다. 파드 할당에 충분하지 않은 컨디션일 경우 scale 조정을 했을 때 Panding 된다. 할당 가능한 IP 수는 아래의 두 가지로 좌우된다.
1. Secondary IPv4 address : 인스턴스 유형에 최대 ENI 개수와 할당 가능 IP 수를 조합하여 선정된다.
2. IPv4 Prefix Delegation: IPv4 28bit 서브넷을 위임하여 할당 가능 IP 수와 인스턴스 유형에 권장하는 최대 개수로 선정된다.
Secondary IPv4 address
Secondary IPv4 address 방식은 Kops를 통해 EC2 인스턴스를 제너럴 하게 설치했을 때 동작하는 방식으로, 인스턴스 타입마다 정해진 ENI 최대 개수와 할당 가능한 최대 IP 갯수에 따라 파드 배치 갯수가 결정된다.
다음의 링크를 통해 인스턴스 타입별 ENI 최대 갯수와 프라이빗 IPv4 주소를 확인할 수 있다.
참고: https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/using-eni.html - 인스턴스 유형별 네트워크 인터페이스당 IP 주소
정해진 규격을 통해 최대 파드 생성 개수를 유추해 볼 수 있다.
(Number of network interfaces for the instance type × (the number of IP addressess per network interface - 1)) + 2
터미널에서도 다음 명령어를 통해 규격을 확인할 수 있다.
aws ec2 describe-instance-types --filters Name=instance-type,Values=t3.* \
--query "InstanceTypes[].{Type: InstanceType, MaxENI: NetworkInfo.MaximumNetworkInterfaces, IPv4addr: NetworkInfo.Ipv4AddressesPerInterface}" \
--output table
IPv4 Prefix Delegation
IPv4 Prefix Delegation 설정을 통해 IPv4 28bit 서브넷을 이용하여 훨씬 많은 파드를 노드에 배치할 수 있다. kOps 환경에서 아래의 설정을 통해 Prefix Delegation을 설정한 후 클러스터를 업데이트한다.
# LimitRanges 기본 정책 삭제
kubectl delete limitranges limits
# 클러스터 환경설정 수정
kops edit cluster
# kubelet 설정과 amazonvpc networking 설정을 변경한다.
...
kubelet:
anonymousAuth: false
maxPods: 220
...
networking:
amazonvpc:
env:
- name: ENABLE_PREFIX_DELEGATION
value: "true"
...
# 클러스터 롤링 업데이트
kops update cluster --yes && echo && sleep 5 && kops rolling-update cluster --yes
kOps kubernetes defalut limitrange가 존재할 경우, Pod 리소스 사용량에 관계없이 CPU 할당량이 생기기 때문에 IP가 여유롭더라도 다음과 같이 Pending 되는 Pod가 생길 수 있다.
정상적으로 설정된 경우 다음과 같이 정상적으로 파드가 배포된다.
AWS Load Balacer Controller + NLB IP 모드
Kubernetes의 서비스는 ClusterIP, NodePort, LoadBalacer 타입이 있다. 보통 서비스들은 Leader Node 또는 Follow Node의 iptables를 통해 파드로 접근할 수 있다. 하지만 AWS Load Balacer Controller와 NLB IP 모드를 통해 Load Balacer를 Pod로 다이렉트로 연결할 수 있다. 이는 Pod가 VPC의 IP 대역에서 IP를 할당받고, NLB가 바로 접속할 수 있는 환경을 제공해 주기 때문에 가능한 일이다. LoadBalacer Controller Pod는 kOps 클러스터로부터 Pod들의 IP 정보를 받아와 NLB가 Pod로 트래픽을 전달할 수 있게 한다.
이를 적용하기 위해서는 Leader Node와 Follow Node에 AWSLoadBalancerControllerIAMPolicy를 추가한 뒤, kOps 클러스터의 환경설정에서 awsLoadBalancer를 활성화시켜줘야 한다.
# 클러스터 환경설정 수정
kops edit cluster
-----
spec:
awsLoadBalancerController:
enabled: true
-----
# 롤링 업데이트
kops update cluster --yes && echo && sleep 5 && kops rolling-update cluster
이렇게 하면 AWS Load Balacer Controller + NLB IP모드가 적용이 되고, Pod가 추가될 때마다 NLB에서 Load Balacing Target을 자동으로 추가한다.
External DNS 연결
Kubernetes Service/Ingress 생성 시 도메인을 설정하면 도메인을 통해 클러스터 접근이 가능하다.
도식 출처: https://edgehog.blog/a-self-hosted-external-dns-resolver-for-kubernetes-111a27d6fc2c
# Leader, Follow Node에 부여할 정책 생성
----
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"route53:ChangeResourceRecordSets"
],
"Resource": [
"arn:aws:route53:::hostedzone/*"
]
},
{
"Effect": "Allow",
"Action": [
"route53:ListHostedZones",
"route53:ListResourceRecordSets"
],
"Resource": [
"*"
]
}
]
}
----
curl -s -O https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/AKOS/externaldns/externaldns-aws-r53-policy.json
aws iam create-policy --policy-name AllowExternalDNSUpdates --policy-document file://externaldns-aws-r53-policy.json
# 정책 적용
export POLICY_ARN=$(aws iam list-policies --query 'Policies[?PolicyName==`AllowExternalDNSUpdates`].Arn' --output text)
aws iam attach-role-policy --policy-arn $POLICY_ARN --role-name masters.$KOPS_CLUSTER_NAME
aws iam attach-role-policy --policy-arn $POLICY_ARN --role-name nodes.$KOPS_CLUSTER_NAME
# kOps Cluster에 externalDns 적용
kops edit cluster
--------------------------
spec:
externalDns:
provider: external-dns
--------------------------
# 업데이트 적용
kops update cluster --yes && echo && sleep 5 && kops rolling-update cluster
# 서비스에 External DNS 적용
kubectl annotate service svc-nlb-ip-type "external-dns.alpha.kubernetes.io/hostname=nginx.devlos.link"
MyDOMAIN1=nginx.devlos.link
NLB에 TLS 적용
AWS Certificate Manager를 이용하여 NLB에 TLS를 적용할 수 있다.
인증서 발급이 완료되면 Service 생성 시 다음의 내용을 추가하여 인증서를 등록할 수 있다.
# kOps Cluster에 certManager 적용
kops edit cluster
--------------------------
spec:
certManager:
enabled: true
--------------------------
# Certification 환경변수 설정
CERT_ARN=`aws acm list-certificates --query 'CertificateSummaryList[].CertificateArn[]' --output text`
# Service 생성
----
apiVersion: v1
kind: Service
metadata:
annotations:
external-dns.alpha.kubernetes.io/hostname: "{$MyDomain}"
service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "https"
service.beta.kubernetes.io/aws-load-balancer-ssl-cert: ${CERT_ARN}
...
----
인증서가 적용되면 다음과 같이 https로 접속이 가능해진다.
CKA 자격증 취득과정과 SRE팀은 무슨 일을할까? - 송영준님 발표
이번 스터디에서는 CKA 자격증 취득과정과 SRE팀은 무슨일을 하는지에 대한 내용을 들었다. 지난해 말에 CKA, CKAD 자격증을 취득을 위해 고군분투했던 시간이 생각나면서 공감되는 부분이 많았다. 인도 아저씨 강의는 정말 진리인 듯하다.. 요즘은 시험 환경이 많이 복잡해서 다들 스트레스를 받아하는 것 같았다.
좋았던 점
이번 스터디에서 배운 내용은 정말 주옥같았다.
AWS dependent 하긴 하지만 Pod 간 통신이 Overlay 없이 가능하다는 점은 스터디에 참여하지 못했다면 전혀 알지 못했을 것 같다.
IPv4 Prefix Delegation 기능을 알지 못했다면, 매우 비효율적으로 서비스를 운영하게 되었을 것 같다. 사내에서 진행하는 프로젝트의 저 스펙 마이크로서비스가 14개 정도 되는데 Secondary IPv4 address을 썼다면 scale을 1씩 늘릴 때마다 인스턴스가 하나씩 늘어나는 상황이 생겼을 것 같다.(t3.medium 기준)
External DNS와 NLB에 TLS를 적용하는 방법도 캡틴 가시다님의 코드를 통해 아주 편하게 적용할 수 있었고, TLS 인증서를 적용하는 스트레스를 많이 줄일 수 있게 되어 좋았다.
힘들었던 점
이번 스터디 복습과정에서는 개념이 많아서 그렇지 크게 어려운 부분은 없었다. 좀 위기였던 부분은 AWS Certificate Manager를 통한 TLS 인증서 발급 과정에서 생각보다 시간이 오래 걸려 마지막 과제를 해결 못하는 것 아닌가 하는 위기감이 느껴졌다. 하지만 그 원인은 Route 53에서 Record를 생성하지 않았던 것이었고, 검색을 통해 뒤늦게 알 수 있었다. 실제로 적용할 실무 환경에서는 잘 사용할 수 있을 것 같다. (이번 글의 내용대로 하면 별문제 없이 발급이 가능하다.)
마치며
이번 글에서는 쿠버네티스 실무 실습 스터디 2주 차에 진행한 내용을 정리해 보았다.
설 연휴도 있고, 이런저런 일들로 인해 블로깅 시기가 좀 늦어진 것 같다.
다음 주엔 좀 더 긴장감을 가지고 성실히 학습해야겠다 :)
참고자료
[1] PKOS 스터디 자료
[2] 쿠버네티스 네트워킹 이해하기#1: Pods | 2019 | 커피고래님 | 링크
[3] A Self-hosted external DNS resolver for Kubernetes | 2020 | The Edgehogs | 링크
'클라우드 컴퓨팅 & NoSQL > [PKOS] 쿠버네티스 실무 실습 스터디' 카테고리의 다른 글
[6주차] PKOS 쿠버네티스 실무 실습 스터디 (23.02.19) (1) | 2023.02.26 |
---|---|
[5주차] PKOS 쿠버네티스 실무 실습 스터디 (23.02.12) (0) | 2023.02.18 |
[4주차] PKOS 쿠버네티스 실무 실습 스터디 (23.02.04) (0) | 2023.02.11 |
[3주차] PKOS 쿠버네티스 실무 실습 스터디 (23.01.29) (0) | 2023.02.04 |
[1주차] PKOS 쿠버네티스 실무 실습 스터디 (23.01.08) (2) | 2023.01.13 |