brunch

You can make anything
by writing

C.S.Lewis

by Master Seo Mar 12. 2023

쿠버4탄-2. K8S - 네트워크

2/11

본 내용은 CloudNet 에서 진행하는 주말 스터디에 참여하여 해당 내용을 참고로 작성되었습니다.
https://gasidaseo.notion.site/gasidaseo/CloudNet-Blog-c9dfa44a27ff431dafdd2edacc8a1863  


목표

CloudFormation으로 실습 환경 한번에 구축하기

pod간 통신은 직접 통신 한다는것을 인지한다.

서버 별로 Pod생성수 제한이 있다는것을 이해한다.

Service (LoadBalancer Controller) 사용.

NLB에 TLS 적용하기

NLB에서 바로 파드로 인입 및 ClientIP 확인 설정

ingress 이해



<1> CloudFormation으로 실습 환경 한번에 구축하기

<2> (선택) Cli로 구축 할때 

<3> 정책 추가

<4>  Pod 통신

<5>  기본 정보 확인

<6> master node 접속 확인

<7> 워커 노드 SSH 접속

<8> 노드 간 파드 통신

<9> 파드에서 외부 통신

<10> pod 생성수 제한

<11>  max-pod 설정

<12> Service (LoadBalancer Controller)

<13> Service (LoadBalancer Controller) 서비스/파드 배포

<14> NLB에 TLS 적용하기

<15> NLB IP Target & Proxy Protocol v2 활성화 : NLB에서 바로 파드로 인입 및 ClientIP 확인 설정

<16> ingress(ALB)

<17>  Ingress with ExternalDNS

<18> 정리





<1> CloudFormation으로 실습 환경 한번에 구축하기



1

콘솔로 로그인

CloudFormation 안에 필요한 EC2 키페어, 키 , 도메인 이름, 버킷명을 넣도록 코드화 하였다.

CloudFormation 한번 돌리면 명령 EC2와 쿠버네티스 클러스터가 생성된다.



CloudFormation을 사용하기 위해 필요한 정보 4가지 생성 (필수)


EC2  > Key pairs 

access-key  / secret-key

도메인 네임  masterseo0.link   (정식으로 구매한 도메인이여야 한다.)

s3 버킷 생성 필요  master-seo-bk7



mykops



2

CloudFormation으로 한번에 구축해보자.


구매한 도메인명 (필수)  masterseo0.link

S3 버킷명 입력 (필수)  masgter-seo-bk7 



oneclick



mykops

c5d.large




3

kops-ec2 에 로그온해서 master, node 서버들이 만들어지는지 모니터링 하자.


# EC2 인스턴스 모니터링

while true; do aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --output text | sort; echo "------------------------------" ;date; sleep 1; done



kops로 생성 모니터링 

kops validate cluster --wait 10m



(15분 걸림)




# 잘 안되면 ec2 로그인 해서 kops로 수동 생성


export AWS_PAGER=""

export REGION=ap-northeast-2

export KOPS_CLUSTER_NAME=masterseo0.link

export KOPS_STATE_STORE=master-seo-bk7



kops create cluster --zones="$REGION"a,"$REGION"c --networking amazonvpc --cloud aws --master-size t3.medium --node-size t3.medium --node-count=2 --network-cidr 172.30.0.0/16 --ssh-public-key ~/.ssh/id_rsa.pub --name=$KOPS_CLUSTER_NAME --kubernetes-version "1.28.0" --dry-run -o yaml > mykops.yaml



kops create cluster --zones="$REGION"a,"$REGION"c --networking amazonvpc --cloud aws --master-size t3.medium --node-size t3.medium --node-count=2 --network-cidr 172.30.0.0/16 --ssh-public-key ~/.ssh/id_rsa.pub --name=$KOPS_CLUSTER_NAME --kubernetes-version "1.28.0" -y



오류로 안될때


# kops로  클러스터 삭제

kops delete cluster --yes


# cloudformation 삭제

aws cloudformation delete-stack --stack-name mykops




https://vclock.kr/timer/#countdown=00:14:00&date=2024-01-15T15:56:29&sound=xylophone&loop=1





4

콘솔상에서 node들이 생성중인것을 바로 확인하자.

버킷이나 키가 틀리거나 하면 kops-ec2 만 만들어지고,  node들은 생성되지 않는다.





5


버전

1.24.10

아래 클릭하면 파일 다운로드 해서 사용

https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/K8S/kops-oneclick-f1.yaml




버전

1.28





<2> (선택) Cli로 구축 할때 


1

# YAML 파일 다운로드 

curl -O https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/K8S/kops-oneclick-f1.yaml



2

aws cloudformation deploy --template-file kops-oneclick-f1.yaml --stack-name mykops --parameter-overrides KeyName=topasvga4-ec2 SgIngressSshCidr=$(curl -s ipinfo.io/ip)/32  MyIamUserAccessKeyID=5QV MyIamUserSecretAccessKey='SFCzL' ClusterBaseName='masterseo1.link' S3StateStore='master-seo-bk6' MasterNodeInstanceType=t3.medium WorkerNodeInstanceType=c5d.large --region ap-northeast-2







<3> 정책 추가


1

# CloudFormation 스택 배포 완료 후 kOps EC2 IP 출력

aws cloudformation describe-stacks --stack-name mykops --query 'Stacks[*].Outputs[0].OutputValue' --output text


2

# 15분 후 작업  EC2에 SSH 접속

ssh -i ~/.ssh/xxxxxxxxx.pem ec2-user@$(aws cloudformation describe-stacks --stack-name mykops --query 'Stacks[*].Outputs[0].OutputValue' --output text)


or

putty 로 접속



3

생성 확인

k get nodes

(masterseo0:N/A) [root@kops-ec2 ~]# k get nodes

NAME                  STATUS   ROLES           AGE     VERSION

i-05810838f3a3914a5   Ready    node            61s     v1.24.12

i-0b91bbdaf1040a3b2   Ready    node            65s     v1.24.12

i-0c5057f7ffbf17fd2   Ready    control-plane   3m52s   v1.24.12


콘솔로 EC2가서 node 가 생성되었는지 확인 = 서버 4대






4

# ExternalDNS IAM 정책 생성 

: 이미 정책이 있다면 Skip~

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



5

# AWSLoadBalancerController IAM 정책 생성 

: 이미 정책이 있다면 Pass.


curl -o iam_policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.4.5/docs/install/iam_policy.json


aws iam create-policy --policy-name AWSLoadBalancerControllerIAMPolicy --policy-document file://iam_policy.json





6

master node와 work node 서버가 생성된후에 추가 작업


# EC2 instance profiles 에 IAM Policy 추가(attach) 


로드밸런서 정책 / dns 업데이트 정책을 마스터 노드에 추가, 워커 노드에 추가.



aws iam attach-role-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy --role-name masters.$KOPS_CLUSTER_NAME


aws iam attach-role-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy --role-name nodes.$KOPS_CLUSTER_NAME


aws iam attach-role-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AllowExternalDNSUpdates --role-name masters.$KOPS_CLUSTER_NAME


aws iam attach-role-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AllowExternalDNSUpdates --role-name nodes.$KOPS_CLUSTER_NAME







7

# 메트릭 서버 확인 : 메트릭은 15초 간격으로 cAdvisor를 통하여 가져옴

매트릭 파트 설치시 나옴.   top 명령어 가능.


kubectl top node

(masterseo0:N/A) [root@kops-ec2 ~]# kubectl top node

NAME                  CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%

i-05810838f3a3914a5   43m          2%     967Mi           25%

i-0b91bbdaf1040a3b2   52m          2%     1018Mi          27%

i-0c5057f7ffbf17fd2   175m         8%     2011Mi          53%




(masterseo0:N/A) [root@kops-ec2 ~]# k get nodes

NAME                  STATUS   ROLES           AGE     VERSION

i-05810838f3a3914a5   Ready    node            3m49s   v1.24.12

i-0b91bbdaf1040a3b2   Ready    node            3m53s   v1.24.12

i-0c5057f7ffbf17fd2   Ready    control-plane   6m40s   v1.24.12



kubectl top pod -A

전체 파드 보기



8

# (옵션) LimitRanges 기본 정책 삭제


kubectl describe limitranges 


# LimitRanges 기본 정책 확인 : 컨테이너는 기본적으로 0.1CPU(=100m vcpu)를 최소 보장(개런티)

Name:       limits

Namespace:  default

Type        Resource  Min  Max  Default Request  Default Limit  Max Limit/Request Ratio

----        --------  ---  ---  ---------------  -------------  -----------------------

Container   cpu       -    -    100m             -              -




kubectl delete limitranges limits

// test시 워커 노드에 pod 100개 생성시  제한에 걸려 안되므로 미리 테스트를 위해 해지한다.


kubectl get limitranges








<4> Pod 통신


1

K8S Calico CNI 와 AWS VPC CNI 차이


K8S Calico CNI 는 pod대역과 노드 대역이 다르다.

AWS VPC CNI는  워커 노드와 파드의 네트워크 대역을 동일하다.


네트워크 통신의 최적화(성능, 지연)




2

kops는 아직 Pod를 위한 보안그룹은 지원하지 않는다.  2023년 4월 현재.

https://reaperes.medium.com/security-group-%EC%9D%84-pod-%EB%8B%A8%EC%9C%84%EB%A1%9C-%ED%95%A0%EB%8B%B9%ED%95%98%EA%B8%B0-bef922065684




3

파드간 통신 시 ?

AWS VPC CNI는 동일 대역으로 직접 통신을 한다.

일반적으로 K8S CNI는 오버레이(VXLAN, IP-IP 등) 통신을 한다. 



4

실습 목표 ?

Secondary IPv4 addresses : 인스턴스 유형에 최대 ENI 갯수와 할당 가능 IP 수를 조합하여 선정


IPv4 Prefix Delegation : IPv4 28bit 서브넷(prefix)를 위임하여 할당 가능 IP 수와 인스턴스 유형에 권장하는 최대 갯수로 선정



5

Amazon EC2 노드에 사용 가능한 IP 주소 증량

https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/cni-increase-ip-addresses.html




https://trans.yonghochoi.com/translations/aws_vpc_cni_increase_pods_per_node_limits.ko






<5>  기본 정보 확인


1

# CNI 정보 확인

kubectl describe daemonset aws-node --namespace kube-system | grep Image | cut -d "/" -f 2


amazon-k8s-cni-init:v1.12.2

amazon-k8s-cni:v1.12.2



2

# 노드 IP 확인


aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,PrivateIPAdd:PrivateIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output table






3

node  Version 확인?


 k get nodes -owide



4

# 파드 IP 확인

kubectl get pod -n kube-system -o=custom-columns=NAME:.metadata.name,IP:.status.podIP,STATUS:.status.phase


NAME                                            IP              STATUS

aws-cloud-controller-manager-4bfjz              172.30.52.252   Running

aws-load-balancer-controller-7f7db58d57-n872d   172.30.52.252   Running

aws-node-bcmgd                                  172.30.49.133   Running

aws-node-ngjvl                                  172.30.52.252   Running

aws-node-rlswc                                  172.30.90.39    Running




# 파드 이름 확인

kubectl get pod -A -o name



5

# 파드 갯수 확인

kubectl get pod -A -o name | wc -l

21



node cpu mem, pod cpu mem 한눈에 보기 ?


kubectl ktop  






<6> master node 접속 확인


1

master node 접속

ssh -i ~/.ssh/id_rsa ubuntu@api.$KOPS_CLUSTER_NAME



2

master node에 툴 설치

sudo apt install -y tree jq net-tools


exit






<7> 워커 노드 SSH 접속


1

# 워커 노드 Public IP 확인



aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value}" --filters Name=instance-state-name,Values=running --output table



+---------------------------------------------------------+----------------+

|                      InstanceName                       |  PublicIPAdd   |

+---------------------------------------------------------+----------------+

|  nodes-ap-northeast-2c.masterseo1.link                           |  3.36.62.3     |

|  nodes-ap-northeast-2a.masterseo1.link                           |  3.39.249.36   |

|  kops-ec2                                                                          |  3.39.227.247  |

|  control-plane-ap-northeast-2a.masters.masterseo1.link  |  13.124.94.132 |

+---------------------------------------------------------+----------------+




2

k get nodes -owide


NAME                  STATUS   ROLES           AGE   VERSION    INTERNAL-IP     EXTERNAL-IP      OS-IMAGE             KERNEL-VERSION    CONTAINER-RUNTIME

i-05810838f3a3914a5   Ready    node            27m   v1.24.12   172.30.41.86    3.38.181.205     Ubuntu 20.04.5 LTS   5.15.0-1031-aws   containerd://1.6.18

i-0b91bbdaf1040a3b2   Ready    node            27m   v1.24.12   172.30.71.136   15.164.102.54    Ubuntu 20.04.5 LTS   5.15.0-1031-aws   containerd://1.6.18

i-0c5057f7ffbf17fd2   Ready    control-plane   30m   v1.24.12   172.30.50.100   54.180.151.215



3

# 워커 노드 Public IP 변수 지정

W1PIP=<워커 노드 1 Public IP>

W2PIP=<워커 노드 2 Public IP>


W1PIP=3.36.62.3

W2PIP=3.39.249.36



# 별도 터미널 2개 띠우기 - 워커 노드 2곳에 접속 하기

접속 후 아래 툴 설치 등 정보 각각 확인

ssh -i ~/.ssh/id_rsa ubuntu@$W1PIP

ssh -i ~/.ssh/id_rsa ubuntu@$W2PIP



# 툴 설치

sudo apt install -y tree jq net-tools



# CNI 정보 확인

ls /var/log/aws-routed-eni

egress-v4-plugin.log  ipamd.log  plugin.log


cat /var/log/aws-routed-eni/plugin.log | jq

cat /var/log/aws-routed-eni/ipamd.log | jq




# 네트워크 정보 확인


1번

ip -br -c addr

lo               UNKNOWN        127.0.0.1/8 ::1/128

ens5             UP             172.30.90.39/19 fe80::887:feff:fe03:ede/64

nodelocaldns     DOWN           169.254.20.10/32



2번

ip -br -c addr

Processing triggers for libc-bin (2.31-0ubuntu9.9) ...

ubuntu@i-084961883568b7489:~$ ip -br -c addr

lo               UNKNOWN        127.0.0.1/8 ::1/128

ens5             UP             172.30.49.133/19 fe80::fc:36ff:fe8a:ab14/64

nodelocaldns     DOWN           169.254.20.10/32



ip -c addr

ip -c route

sudo iptables -t nat -S

sudo iptables -t nat -L -n -v


# 빠져나오기

exit



5

namespace ?

(masterseo1:N/A) [root@kops-ec2 ~]# k ns default



6

EBS pod ip  와  work node ip 대역이 같다.


172.30 대역으로 같은 대역이다.



EBS pod ip  ?



kubectl get pod -n kube-system -l app=ebs-csi-node -owide


NAME                 READY   STATUS    RESTARTS   AGE    IP              NODE                  NOMINATED NODE   READINESS GATES

ebs-csi-node-99b4g   3/3     Running   0          102m   172.30.61.160   i-09d56577f34433283   <none>           <none>

ebs-csi-node-d92rr   3/3     Running   0          100m   172.30.84.176   i-04a76bea23f8eadca   <none>           <none>

ebs-csi-node-rhrph   3/3     Running   0          100m   172.30.55.144   i-084961883568b7489   <none>           <none>

(masterseo1:default




 work node ip 대역 ?


 k get nodes -owide



NAME                  STATUS   ROLES           AGE    VERSION    INTERNAL-IP     EXTERNAL-IP      OS-IMAGE             KERNEL-VERSION    CONTAINER-RUNTIME

i-04a76bea23f8eadca   Ready    node            102m   v1.24.12   172.30.90.39    13.124.203.110   Ubuntu 20.04.5 LTS   5.15.0-1031-aws   containerd://1.6.18

i-084961883568b7489   Ready    node            102m   v1.24.12   172.30.49.133   43.201.148.72    Ubuntu 20.04.5 LTS   5.15.0-1031-aws   containerd://1.6.18

i-09d56577f34433283   Ready    control-plane   105m   v1.24.12   172.30.52.252   54.180.202.81    Ubuntu 20.04.5 LTS   5.15.0-1031-aws   containerd://1.6.18






7

[실습] 테스트용 파드 생성 - nicolaka/netshoot



# [터미널] 워커 노드 1~2 모니터링


ssh -i ~/.ssh/id_rsa ubuntu@$W1PIP

watch -d "ip link | egrep 'ens5|eni' ;echo;echo "[ROUTE TABLE]"; route -n | grep eni"


ssh -i ~/.ssh/id_rsa ubuntu@$W2PIP

watch -d "ip link | egrep 'ens5|eni' ;echo;echo "[ROUTE TABLE]"; route -n | grep eni"




8

ec2 서버에서  테스트용 파드 netshoot-pod 2개 생성 해보자.

위에 node 2곳 모니터링에 변화가 생긴다. = 172.30 라우팅 2개가 생긴다.


cat <<EOF | kubectl create -f -

apiVersion: apps/v1

kind: Deployment

metadata:

  name: netshoot-pod

spec:

  replicas: 2

  selector:

    matchLabels:

      app: netshoot-pod

  template:

    metadata:

      labels:

        app: netshoot-pod

    spec:

      containers:

      - name: netshoot-pod

        image: nicolaka/netshoot

        command: ["tail"]

        args: ["-f", "/dev/null"]

      terminationGracePeriodSeconds: 0

EOF



9

# 파드 이름 변수 지정

PODNAME1=$(kubectl get pod -l app=netshoot-pod -o jsonpath={.items[0].metadata.name})

PODNAME2=$(kubectl get pod -l app=netshoot-pod -o jsonpath={.items[1].metadata.name})


# 파드 확인

kubectl get pod -o wide


kubectl get pod -o=custom-columns=NAME:.metadata.name,IP:.status.podIP

NAME                            IP

netshoot-pod-7757d5dd99-gxrc9   172.30.84.182

netshoot-pod-7757d5dd99-mfm7q   172.30.55.148





8

# 테스트용 파드 접속(exec) 후 Shell 실행

kubectl exec -it $PODNAME1 -- zsh


# pod-1 Shell 에서 실행 : 네트워크 정보 확인

----------------------------

ip -c addr


 netshoot-pod-7757d5dd99-gxrc9  ~  ip -c addr

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000

    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

    inet 127.0.0.1/8 scope host lo

       valid_lft forever preferred_lft forever

    inet6 ::1/128 scope host

       valid_lft forever preferred_lft forever

3: eth0@if10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP group default

    link/ether 22:89:ab:17:dc:3d brd ff:ff:ff:ff:ff:ff link-netnsid 0

    inet 172.30.84.182/32 scope global eth0

       valid_lft forever preferred_lft forever

    inet6 fe80::2089:abff:fe17:dc3d/64 scope link

       valid_lft forever preferred_lft forever


// 모니터링 하고 있는 워커 노드 서버에서  172.30.84.182 확인 가능하다.

node 1번에서 떠 있는 pod이다.



ip -c route

route -n

ping -c 1 <pod-2 IP>

ps

cat /etc/resolv.conf

exit

----------------------------



9

# 파드2 Shell 실행

kubectl exec -it $PODNAME2 -- ip -c addr


동일하게  ip정보 확인

ip -c addr





<8> 노드 간 파드 통신


1

파드간 통신 흐름 : AWS VPC CNI 경우 별도의 오버레이(Overlay) 통신 기술 없이, VPC Native 하게 파드간 직접 통신이 가능하다



1번 node  , 2 node 간  pod 통신하자.

원본 IP 패킷이 그대로 날아간다.



2

파드간 직접 통신이 가능하다




3

[실습] 파드간 통신 테스트 및 확인 

 별도의 NAT 동작 없이 통신 가능!



4

# 파드 IP 변수 지정

PODIP1=$(kubectl get pod -l app=netshoot-pod -o jsonpath={.items[0].status.podIP})

PODIP2=$(kubectl get pod -l app=netshoot-pod -o jsonpath={.items[1].status.podIP})


# 파드1 에서 파드2로 ping 테스트

kubectl exec -it $PODNAME1 -- ping -c 2 $PODIP2


# 파드2 에서 파드1로 ping 테스트

kubectl exec -it $PODNAME2 -- ping -c 2 $PODIP1



5

# 워커 노드에서

: TCPDUMP 확인 

ip -c addr

ens5나 6 에서 패킷 덤프 확인이 되나요?


sudo tcpdump -i any -nn icmp

sudo tcpdump -i ens5 -nn icmp

sudo tcpdump -i ens6 -nn icmp


POD IP가 찍힌다 !!!!






<9> 파드에서 외부 통신


1

파드에서 외부 통신 흐름 : iptable 에 SNAT 을 통하여 노드의 eth0 IP로 변경되어서 외부와 통신됨


VPC CNI 의 External source network address translation (SNAT) 설정에 따라, 외부(인터넷) 통신 시 SNAT 하거나 혹은 SNAT 없이 통신을 할 수 있다



2

[실습] 파드에서 외부 통신 테스트 및 확인


파드에서 외부 통신 테스트 및 확인


# 작업용 EC2

pod-1 에서 외부로 ping

kubectl exec -it $PODNAME1 -- ping -c 1 www.google.com

kubectl exec -it $PODNAME1 -- ping -i 0.1 www.google.com



3

# 워커 노드 EC2 에서 확인

: 퍼블릭IP 확인, TCPDUMP 확인

curl -s ipinfo.io/ip ; echo

sudo tcpdump -i any -nn icmp

sudo tcpdump -i ens5 -nn icmp



4

# 작업용 EC2 에서 확인

: pod-1 Shell 에서 외부 접속 확인 - 공인IP는 어떤 주소인가?

pod 가 외부 통신 할때, work node의 첫번째 외부 인터넷 ip를 가지고 나간다.


콘솔에서 work node 공인 ip 확인해보자 



5

Pod가 외부 인터넷 된다.

## The right way to check the weather - 링크

kubectl exec -it $PODNAME1 -- curl -s ipinfo.io/ip ; echo



명령어로 날씨 보는 것

kubectl exec -it $PODNAME1 -- curl -s wttr.in/seoul



kubectl exec -it $PODNAME1 -- curl -s wttr.in/seoul?format=3

kubectl exec -it $PODNAME1 -- curl -s wttr.in/Moon

kubectl exec -it $PODNAME1 -- curl -s wttr.in/:help



6

# 워커 노드 EC2


## 출력된 결과를 보고 어떻게 빠져나가는지 고민해보자!

ip rule

ip route show table main

sudo iptables -L -n -v -t nat

sudo iptables -t nat -S



7

# 파드가 외부와 통신시에는 아래 처럼 'AWS-SNAT-CHAIN-0, AWS-SNAT-CHAIN-1' 룰(rule)에 의해서 SNAT 되어서 외부와 통신!

# 참고로 뒤 IP는 eth0(ENI 첫번째)의 IP 주소이다


8

kubectl delete deploy netshoot-pod





<10> pod 생성수 제한


1

# t3 타입의 정보(필터) 확인

aws ec2 describe-instance-types --filters Name=instance-type,Values=t3.*  --query "InstanceTypes[].{Type: InstanceType, MaxENI: NetworkInfo.MaximumNetworkInterfaces, IPv4addr: NetworkInfo.Ipv4AddressesPerInterface}"  --output table


--------------------------------------

|        DescribeInstanceTypes       |

+----------+----------+--------------+

| IPv4addr | MaxENI   |    Type      |

+----------+----------+--------------+

|  15      |  4       |  t3.xlarge   |

|  15      |  4       |  t3.2xlarge  |

|  12      |  3       |  t3.large    |

|  2       |  2       |  t3.nano     |

|  6       |  3       |  t3.medium   |

|  4       |  3       |  t3.small    |

|  2       |  2       |  t3.micro    |

+----------+----------+--------------+





# 파드 사용 가능 계산 예시 : aws-node 와 kube-proxy 파드는 host-networking 사용으로 IP 2개 남음

((MaxENI * (IPv4addr-1)) + 2)

t3.medium 경우 : ((3 * (6 - 1) + 2 ) = 17개 >> aws-node 와 kube-proxy 2개 제외하면 15개


# 워커노드 상세 정보 확인 : 노드 상세 정보의 Allocatable 에 pods 에 17개 정보 확인

kubectl describe node | grep Allocatable: -A6

Allocatable:

  cpu:                2

  ephemeral-storage:  59763732382

  hugepages-1Gi:      0

  hugepages-2Mi:      0

  memory:             3854320Ki

  pods:               17




2

# 워커 노드 EC2 - 모니터링


watch -d "ip link | egrep 'ens|eni'"

while true; do ip -br -c addr show && echo "--------------" ; date "+%Y-%m-%d %H:%M:%S" ; sleep 1; done



3

# 작업용 EC2 - 터미널1

watch -d 'kubectl get pods -o wide'


# 작업용 EC2 - 터미널2

# 디플로이먼트 생성

cat ~/pkos/2/nginx-dp.yaml | yh

kubectl apply -f ~/pkos/2/nginx-dp.yaml


# 파드 확인

kubectl get pod -o wide

kubectl get pod -o=custom-columns=NAME:.metadata.name,IP:.status.podIP

kubectl ktop



4

watch -d kubectl get pod



# 파드 증가 테스트 >> 파드 정상 생성 확인, 워커 노드에서 eth, eni 갯수 확인

kubectl scale deployment nginx-deployment --replicas=8


# 파드 증가 테스트 >> 파드 정상 생성 확인, 워커 노드에서 eth, eni 갯수 확인 >> 어떤일이 벌어졌는가?

kubectl scale deployment nginx-deployment --replicas=10


# 파드 증가 테스트 >> 파드 정상 생성 확인, 워커 노드에서 eth, eni 갯수 확인 >> 어떤일이 벌어졌는가?

kubectl scale deployment nginx-deployment --replicas=100


# 파드 생성 실패!

kubectl get pods | grep Pending

nginx-deployment-7fb7fd49b4-d4bk9   0/1     Pending   0          3m37s

nginx-deployment-7fb7fd49b4-qpqbm   0/1     Pending   0          3m37s

...


kubectl describe pod <Pending 파드> | grep Events: -A5

Events:

  Type     Reason            Age   From               Message

  ----     ------            ----  ----               -------

  Warning  FailedScheduling  45s   default-scheduler  0/3 nodes are available: 1 node(s) had untolerated taint {node-role.kubernetes.io/control-plane: }, 2 Too many pods. preemption: 0/3 nodes are available: 1 Preemption is not helpful for scheduling, 2 No preemption victims found for incoming pod.



5

# 디플로이먼트 삭제

kubectl delete deploy nginx-deployment




<11>  max-pod 설정


1

# 파드 갯수 모니터링

watch "kubectl get pod | grep -v NAME | wc -l"


# 파드 60개 , 100개 배포

kubectl apply -f ~/pkos/2/nginx-dp.yaml

kubectl scale deployment nginx-deployment --replicas=60

kubectl scale deployment nginx-deployment --replicas=100



2

# Nitro 인스턴스 유형 확인

aws ec2 describe-instance-types --filters Name=hypervisor,Values=nitro --query "InstanceTypes[*].[InstanceType]" --output text | sort | egrep 't3\.|c5\.|c5d\.'

c5.12xlarge

c5.18xlarge

c5.24xlarge

c5.2xlarge

c5.4xlarge

c5.9xlarge

c5d.12xlarge

c5d.18xlarge



3

# 노드 인스턴스 타입 확인

kubectl describe nodes | grep "node.kubernetes.io/instance-type"

                    node.kubernetes.io/instance-type=t3.medium

                    node.kubernetes.io/instance-type=t3.medium

                    node.kubernetes.io/instance-type=t3.medium



4

# 노드 상세 정보 확인 : 노드 상세 정보의 Allocatable 에 노드별 최대 생성 가능한 pods 정보 확인 - 각각 마스터 노드, 워커 노드


kubectl describe node | grep Allocatable: -A6

Allocatable:

  cpu:                2

  ephemeral-storage:  119703055367

  hugepages-1Gi:      0

  hugepages-2Mi:      0

  memory:             3854328Ki

  pods:               100

--



5

# 파드 배포 확인

kubectl get pod


kubectl get pod | grep -v NAME | wc -l

100


kubectl get replicasets



6

# LimitRanges 기본 정책 확인

kubectl describe limitranges


# 수정 전 env 정보 확인

kubectl describe ds -n kube-system aws-node | grep ADDITIONAL_ENI_TAGS: -A22


수정후

kubectl describe daemonsets.apps -n kube-system aws-node | egrep 'ENABLE_PREFIX_DELEGATION|WARM_PREFIX_TARGET'

      ENABLE_PREFIX_DELEGATION:               true

      WARM_PREFIX_TARGET:                     1



7

해결 내용


kops edit cluster

...

  kubelet:

    anonymousAuth: false

    maxPods: 110

...

  networking:

    amazonvpc:

      env:

      - name: ENABLE_PREFIX_DELEGATION

        value: "true"




8

참고 

https://trans.yonghochoi.com/translations/aws_vpc_cni_increase_pods_per_node_limits.ko





<12> Service (LoadBalancer Controller)



1

외부에서 로드 밸런서로 가면 바로  Pod로 간다.

iptables를 사용하지 않는다.


2

동적으로 변하는 Pod의 정보를 알아야 한다.

Load Balancer Controller 파드가 그 정보를 알아서 지속적인 정보제공을 로드밸런서에 한다.

"대상 타겟에 pod 추가로 생겼어~ "  "Pod삭제 되었네, NLB나 ALB에서 제외하자~"

Load Balancer Controller 파드가 워커 노드에 생성된다.


워커 노드에 로드밸런서를 변경할수 있는 권한을 부여하여 권한 문제를 해결하자.


4

설정시 반드시 IP유형이여야 한다.

AWS Load Balancer Controller 파드 및 정책 설정이 필요하다.


Proxy Protocol v2 비활성화 = NLB에서 바로 파드로 인입, 단, 클라이언트IP가 NLB로 SNAT되어 Client IP확인 불가능


Proxy Protocol v2 활성화 = NLB에서 바로 파드로 인입 및 클라이언트IP 확인 가능, 단, PPv2를 애플리케이션이 인지할수 있도록 설정이 필요하다.


설정법

https://gasidaseo.notion.site/AWS-NLB-Client-IP-Proxy-protocol-57827e2c83fc474992b37e65db81f669


기타 - 인스턴스 유형으로 하면 비효율적인 처리가 된다.




5

명령 ec2에서 로그온해 권한 확인하자.


# 기본 EC2 profile 권한 확인 


aws elbv2 describe-load-balancers

{

    "LoadBalancers": []

}




6

# 마스터/워커 노드에 EC2 IAM Role 에 Policy (AWSLoadBalancerControllerIAMPolicy) 추가


# IAM Policy 정책 생성

curl -o iam_policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.4.1/docs/install/iam_policy.json


curl -o iam_policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.4.5/docs/install/iam_policy.json


aws iam create-policy --policy-name AWSLoadBalancerControllerIAMPolicy --policy-document file://iam_policy.json



7

# 계정 Account ID 변수 지정

ACCOUNT_ID=`aws sts get-caller-identity --query 'Account' --output text`

echo $ACCOUNT_ID



8

# 생성된 IAM Policy Arn 확인

aws iam list-policies --scope Local


aws iam get-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy


aws iam get-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy --query 'Policy.Arn'

"arn:aws:iam::911283464785:policy/AWSLoadBalancerControllerIAMPolicy"



9

# EC2 instance profiles 이름 확인 


aws iam list-instance-profiles


aws iam list-instance-profiles --query 'InstanceProfiles[*].InstanceProfileName'

[

    "masters.masterseo1.link",

    "nodes.masterseo1.link"

]



10

# EC2 instance profiles 에 IAM Policy 추가(attach)

#aws iam attach-role-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy --role-name masters.<My Domain Name>


#aws iam attach-role-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy --role-name nodes.<My Domain Name>


aws iam attach-role-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy --role-name masters.$KOPS_CLUSTER_NAME


aws iam attach-role-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy --role-name nodes.$KOPS_CLUSTER_NAME



11

# kOps 클러스터 편집 : 아래 내용 추가

## 인증서 구성을 웹훅에 삽입할 수 있도록 cert-manager를 설치합니다. 

## Cert-manager는 쿠버네티스 클러스터 내에서 TLS인증서를 자동으로 프로비저닝 및 관리하는 오픈 소스입니다

kops edit cluster --name ${KOPS_CLUSTER_NAME}

-----

spec:

  certManager:

    enabled: true

  awsLoadBalancerController:

    enabled: true

-----


12

# 업데이트 적용 : 적용이 안될 경우 한번 더 아래 명령 실행

kops update cluster --yes && echo && sleep 5 && kops rolling-update cluster


# aws-load-balancer-controller 파드 확인 : 서비스 정상 상태로 변경까지 대략 2분 30초 정도 소요

watch kubectl get pod -A


# 버전 확인 : v2.4.3

kubectl describe deploy -n kube-system aws-load-balancer-controller | grep Image | cut -d "/" -f 2

aws-alb-ingress-controller:v2.4.5@sha256:46029f2e2d48c55064b9eef48388bb6f5ec3390e6bf58790dd6b8d350e57ac90



13

위 내용은 이미 적용되어 있다. 

콘솔에서 확인하자.

master, work node 서버에 모두 AWSLoadBalancerControllerIAMPolicy가 들어가 있다.



14

# crds 확인

kubectl get crd

NAME                                  CREATED AT

certificaterequests.cert-manager.io   2023-03-14T08:58:24Z

certificates.cert-manager.io          2023-03-14T08:58:24Z

challenges.acme.cert-manager.io       2023-03-14T08:58:24Z

clusterissuers.cert-manager.io        2023-03-14T08:58:24Z

eniconfigs.crd.k8s.amazonaws.com      2023-03-12T10:46:28Z

ingressclassparams.elbv2.k8s.aws      2023-03-14T08:58:43Z

issuers.cert-manager.io               2023-03-14T08:58:24Z

orders.acme.cert-manager.io           2023-03-14T08:58:24Z

targetgroupbindings.elbv2.k8s.aws     2023-03-14T08:58:43Z


// targetgroupbindings   = 로드밸런서의 타켓 그룹





<13> Service (LoadBalancer Controller) 서비스/파드 배포



1

다른 터미널에서 모니터링 


 watch -d  'kubectl  get deploy,svc,ep,ingress,pods'


NAME                      TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE

service/svc-nlb-ip-type   LoadBalancer   100.66.221.167   k8s-default-svcnlbip-d5b51418f3-ecc992ff25d85192.elb.ap-northeast-2.amazonaws.com   80:30494/TCP   5m14s





2

실습

# 작업용 EC2 - 디플로이먼트 & 서비스 생성

cat ~/pkos/2/echo-service-nlb.yaml | yh

kubectl apply -f ~/pkos/2/echo-service-nlb.yaml



내용 확인

ip 타입이다.

NLB이다.


  service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip

  loadBalancerClass: service.k8s.aws/nlb




apiVersion: apps/v1

kind: Deployment

metadata:

  name: deploy-echo

spec:

  replicas: 2

  selector:

    matchLabels:

      app: deploy-websrv

  template:

    metadata:

      labels:

        app: deploy-websrv

    spec:

      terminationGracePeriodSeconds: 0

      containers:

      - name: akos-websrv

        image: k8s.gcr.io/echoserver:1.5

        ports:

        - containerPort: 8080

---

apiVersion: v1

kind: Service

metadata:

  name: svc-nlb-ip-type

  annotations:

    service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip

    service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing

    service.beta.kubernetes.io/aws-load-balancer-healthcheck-port: "8080"

    service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"

spec:

  ports:

    - port: 80

      targetPort: 8080

      protocol: TCP

  type: LoadBalancer

  loadBalancerClass: service.k8s.aws/nlb

  selector:

    app: deploy-websrv



3

# 확인

kubectl get deploy,pod,svc

kubectl get crd

kubectl get svc,ep,ingressclassparams,targetgroupbindings

kubectl get targetgroupbindings -o json | jq


4

# AWS ELB(NLB) 정보 확인

aws elbv2 describe-load-balancers | jq

aws elbv2 describe-load-balancers --query 'LoadBalancers[*].State.Code' --output text


5

# 웹 접속 주소 확인

kubectl get svc svc-nlb-ip-type -o jsonpath={.status.loadBalancer.ingress[0].hostname} | awk '{ print "Pod Web URL = http://"$1 }'

------------------------------

Pod Web URL = http://k8s-default-svcnlbip-d5b51418f3-ecc992ff25d85192.elb.ap-northeast-2.amazonaws.com



6

EP 가 Pod 정보 이다.

watch -d  'kubectl  get deploy,svc,ep,ingress,pods'


Every 2.0s: kubectl  get deploy,svc,ep,ingress,pods                                                                                                              Fri Apr 28 05:16:23 2023

NAME                          READY   UP-TO-DATE   AVAILABLE   AGE

deployment.apps/deploy-echo   2/2     2            2           20m

NAME                      TYPE           CLUSTER-IP       EXTERNAL-IP                                                                         PORT(S)        AGE

service/kubernetes        ClusterIP      100.64.0.1       <none>                                                                              443/TCP        10h

service/svc-nlb-ip-type   LoadBalancer   100.66.221.167   k8s-default-svcnlbip-d5b51418f3-ecc992ff25d85192.elb.ap-northeast-2.amazonaws.com   80:30494/TCP   20m


NAME                        ENDPOINTS                               AGE

endpoints/kubernetes        172.30.52.252:443                       10h

endpoints/svc-nlb-ip-type   172.30.55.147:8080,172.30.84.184:8080   20m


NAME                               READY   STATUS    RESTARTS   AGE

pod/deploy-echo-5c4856dfd6-r4bht   1/1     Running   0          20m

pod/deploy-echo-5c4856dfd6-r6dqh   1/1     Running   0          5m36s




 k get pods -owide

(masterseo1:default) [root@kops-ec2 ~]# k get pods -owide

NAME                           READY   STATUS    RESTARTS   AGE   IP              NODE                  NOMINATED NODE   READINESS GATES

deploy-echo-5c4856dfd6-r4bht   1/1     Running   0          42m   172.30.84.184   i-04a76bea23f8eadca   <none>           <none>

deploy-echo-5c4856dfd6-r6dqh   1/1     Running   0          28m   172.30.55.147   i-084961883568b7489   <none>           <none>




콘솔 로드밸런서의 타켓 그룹에 가서 확인하자.




7

kubectl get deploy,svc,ep,pods,ingressclassparams,targetgroupbindings                       


NAME                          READY   UP-TO-DATE   AVAILABLE   AGE

deployment.apps/deploy-echo   2/2     2            2           24m


NAME                      TYPE           CLUSTER-IP       EXTERNAL-IP

           PORT(S)        AGE

service/kubernetes        ClusterIP      100.64.0.1       <none>

           443/TCP        10h

service/svc-nlb-ip-type   LoadBalancer   100.66.221.167   k8s-default-svcnlbip-d5b51418f3-ecc992ff25d85192.elb.ap-northeast-2.amazo

naws.com   80:30494/TCP   24m


NAME                        ENDPOINTS                               AGE

endpoints/kubernetes        172.30.52.252:443                       10h

endpoints/svc-nlb-ip-type   172.30.55.147:8080,172.30.84.184:8080   24m


NAME                               READY   STATUS    RESTARTS   AGE

pod/deploy-echo-5c4856dfd6-r4bht   1/1     Running   0          24m

pod/deploy-echo-5c4856dfd6-r6dqh   1/1     Running   0          10m


NAME                                   GROUP-NAME   SCHEME   IP-ADDRESS-TYPE   AGE

ingressclassparams.elbv2.k8s.aws/alb                                           10h


NAME                                                               SERVICE-NAME      SERVICE-PORT   TARGET-TYPE   AGE

targetgroupbinding.elbv2.k8s.aws/k8s-default-svcnlbip-75b3c4aa04   svc-nlb-ip-type   80             ip            24m





7

# CLB에 ExternanDNS 로 도메인 연결


kubectl annotate service svc-nlb-ip-type "external-dns.alpha.kubernetes.io/hostname=nginx.$KOPS_CLUSTER_NAME"


# 확인

dig +short nginx.$KOPS_CLUSTER_NAME

15.164.183.41

3.37.252.151


kubectl logs -n kube-system -l k8s-app=external-dns


# 웹 접속 주소 확인 및 접속

echo -e "Nginx Web URL = http://nginx.$KOPS_CLUSTER_NAME"

------------------------------

Nginx Web URL = http://nginx.masterseo1.link



# 파드 로깅 모니터링

kubectl logs -l app=deploy-websrv -f



8

# 분산 접속 확인

NLB=$(kubectl get svc svc-nlb-ip-type -o jsonpath={.status.loadBalancer.ingress[0].hostname})


echo $NLB

------------------------------

k8s-default-svcnlbip-d5b51418f3-ecc992ff25d85192.elb.ap-northeast-2.amazonaws.com


curl -s $NLB

for i in {1..100}; do curl -s $NLB | grep Hostname ; done | sort | uniq -c | sort -nr

------------------------------

  52 Hostname: deploy-echo-55456fc798-2w65p

  48 Hostname: deploy-echo-55456fc798-cxl7z



9

# 지속적인 접속 시도 : 아래 상세 동작 확인 시 유용(로깅시 확인 패킷 덤프 등)

while true; do curl -s --connect-timeout 1 $NLB | egrep 'Hostname|client_address'; echo "----------" ; date "+%Y-%m-%d %H:%M:%S" ; sleep 1; done




10

# 작업용 EC2 - 파드 1개로 설정을 변경한다.

kubectl scale deployment deploy-echo --replicas=1



콘솔 확인!

자동으로 서버 1대가 healthy -> draining으로 빠진다.




# 확인

kubectl get deploy,pod,svc,ep

curl -s nginx.$KOPS_CLUSTER_NAME

curl -s $NLB


for i in {1..100}; do curl -s --connect-timeout 1 nginx.$KOPS_CLUSTER_NAME | grep Hostname ; done | sort | uniq -c | sort -nr

   100 Hostname: deploy-echo-5c4856dfd6-r4bht



for i in {1..100}; do curl -s --connect-timeout 1 $NLB | grep Hostname ; done | sort | uniq -c | sort -nr



11

# 작업용 EC2 - 파드 4개 설정 

kubectl scale deployment deploy-echo --replicas=4



자동으로 Pod가 추가 된다.




12


# 확인

curl -s nginx.$KOPS_CLUSTER_NAME


curl -s $NLB


for i in {1..100}; do curl -s --connect-timeout 1 nginx.$KOPS_CLUSTER_NAME | grep Hostname ; done | sort | uniq -c | sort -nr


for i in {1..100}; do curl -s --connect-timeout 1 $NLB | grep Hostname ; done | sort | uniq -c | sort -nr



13

2가지가 필요하다.

AWS에서도 권한이 필요하고, 쿠버네티스에서도 role이 필요하다.


Load Balancer Controller파드가  EKS Cluster를 찔러서 Pod정보를 가져와야 함.



14

# [AWS LB Ctrl] 클러스터 롤 바인딩 정보 확인

kubectl describe clusterrolebindings.rbac.authorization.k8s.io aws-load-balancer-controller-rolebinding


Name:         aws-load-balancer-controller-rolebinding

Labels:       addon.kops.k8s.io/name=aws-load-balancer-controller.addons.k8s.io

              app.kubernetes.io/managed-by=kops

              app.kubernetes.io/name=aws-load-balancer-controller

              k8s-addon=aws-load-balancer-controller.addons.k8s.io

Annotations:  <none>

Role:

  Kind:  ClusterRole

  Name:  aws-load-balancer-controller-role

Subjects:

  Kind            Name                          Namespace

  ----            ----                          ---------

  ServiceAccount  aws-load-balancer-controller  kube-system



15

# [AWS LB Ctrl] 클러스터롤이 필요하다. 확인 

kubectl describe clusterroles.rbac.authorization.k8s.io aws-load-balancer-controller-role


(masterseo1:default) [root@kops-ec2 ~]# kubectl describe clusterroles.rbac.authorization.k8s.io aws-load-balancer-controller-role

Name:         aws-load-balancer-controller-role

Labels:       addon.kops.k8s.io/name=aws-load-balancer-controller.addons.k8s.io

              app.kubernetes.io/managed-by=kops

              app.kubernetes.io/name=aws-load-balancer-controller

              k8s-addon=aws-load-balancer-controller.addons.k8s.io

Annotations:  <none>

PolicyRule:

  Resources                                 Non-Resource URLs  Resource Names  Verbs

  ---------                                 -----------------  --------------  -----

  targetgroupbindings.elbv2.k8s.aws         []                 []              [create delete get list patch update watch]

  events                                    []                 []              [create patch]

  services                                  []                 []              [get list patch update watch]

  ingresses.extensions                      []                 []              [get list patch update watch]

  ingresses.networking.k8s.io               []                 []              [get list patch update watch]

  endpoints                                 []                 []              [get list watch]

  namespaces                                []                 []              [get list watch]

  nodes                                     []                 []              [get list watch]

  pods                                      []                 []              [get list watch]

  endpointslices.discovery.k8s.io           []                 []              [get list watch]

  ingressclassparams.elbv2.k8s.aws          []                 []              [get list watch]

  ingressclasses.networking.k8s.io          []                 []              [get list watch]

  pods/status                               []                 []              [patch update]

  services/status                           []                 []              [patch update]

  targetgroupbindings.elbv2.k8s.aws/status  []                 []              [patch update]

  ingresses.extensions/status               []                 []              [patch update]

  ingresses.networking.k8s.io/status        []                 []              [patch update]

(masterseo1:default) [root@kops-ec2 ~]#




16

한가지 더 ?

NLB에 대상에 넣고 빼는 권한 할수 있는게 필요하다.

위에서 EC2 인스턴스 프로파일에 ELB를 조작할수 있는 권한을 붙였다.




17

NLB TLS사용해보자.

HTTPS 사용.

AWS에서 인증서 발급받자.

*




18

삭제

kubectl delete deploy deploy-echo; kubectl delete svc svc-nlb-ip-type






<14> NLB에 TLS 적용하기


https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.4/guide/use_cases/nlb_tls_termination/



1

# 사전 준비 : 공인도메인 소유, AWS Route53 도메인등록 상태, NLB 가 위치한 리전(서울)의 인증서 요청/발급 완료상태, ExternalDNS 준비완료상태


인증서 발급은 cert manager 가서 한다. *.도메인

dns에서 cname으로 위임해 줘야 한다.   승인되는데 10분 걸린다.



2

# 클러스터 네임 확인

echo $KOPS_CLUSTER_NAME


3

watch -d kubectl get deploy,rs,svc,ep,pods



4

# 사용 리전의 인증서 ARN 확인

aws acm list-certificates

aws acm list-certificates --max-items 10

aws acm list-certificates --query 'CertificateSummaryList[].CertificateArn[]' --output text

CERT_ARN=`aws acm list-certificates --query 'CertificateSummaryList[].CertificateArn[]' --output text`

echo $CERT_ARN


# 자신의 도메인 변수 지정

MyDomain=<자신의 도메인>

MyDomain=websrv.$KOPS_CLUSTER_NAME

echo $MyDomain


5

# 생성

cat <<EOF | kubectl create -f -

apiVersion: apps/v1

kind: Deployment

metadata:

  name: deploy-echo

spec:

  replicas: 2

  selector:

    matchLabels:

      app: deploy-websrv

  template:

    metadata:

      labels:

        app: deploy-websrv

    spec:

      terminationGracePeriodSeconds: 0

      containers:

      - name: akos-websrv

        image: k8s.gcr.io/echoserver:1.5

        ports:

        - containerPort: 8080

---

apiVersion: v1

kind: Service

metadata:

  name: svc-nlb-ip-type

  annotations:

    external-dns.alpha.kubernetes.io/hostname: "${MyDomain}"

    service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip

    service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing

    service.beta.kubernetes.io/aws-load-balancer-healthcheck-port: "8080"

    service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"

    service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "https"

    service.beta.kubernetes.io/aws-load-balancer-ssl-cert: ${CERT_ARN}

    service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "http"

spec:

  ports:

    - port: 80

      targetPort: 8080

      protocol: TCP

      name: http

    - port: 443

      targetPort: 8080

      protocol: TCP

      name: https

  type: LoadBalancer

  loadBalancerClass: service.k8s.aws/nlb

  selector:

    app: deploy-websrv

EOF



6

# 확인

kubectl get svc,ep

kubectl describe svc svc-nlb-ip-type

kubectl describe svc svc-nlb-ip-type | grep Annotations: -A8


# (외부) 접속 테스트

curl -s http://<접속 도메인 주소> | grep Hostname

curl -s -k https://<접속 도메인 주소> | grep Hostname

...

curl -s -k http://$MyDomain | grep Hostname


curl -s -k https://$MyDomain | grep Hostname

Hostname: deploy-echo-55456fc798-5m5ps



7

# 삭제

kubectl delete deploy deploy-echo; kubectl delete svc svc-nlb-ip-type






<15> NLB IP Target & Proxy Protocol v2 활성화 : NLB에서 바로 파드로 인입 및 ClientIP 확인 설정


기본적으로 외부에서 접속하면 사용자 IP가 안보인다.

Client IP를 확인할수 있도록 미리 만들어놓은 이미지 , apache에 proxy 프로토콜로 들어오면 ip를 확인할수 있도록 미리 만들어놓은 이미지 사용한다.

로그 보자.




참고

https://gasidaseo.notion.site/AWS-NLB-Client-IP-Proxy-protocol-57827e2c83fc474992b37e65db81f669#a599aa7f26774fecb73bbd1f42c5e52a



https://canaryrelease.tistory.com/42



1

# 생성

cat <<EOF | kubectl create -f -

apiVersion: apps/v1

kind: Deployment

metadata:

  name: gasida-web

spec:

  replicas: 1

  selector:

    matchLabels:

      app: gasida-web

  template:

    metadata:

      labels:

        app: gasida-web

    spec:

      terminationGracePeriodSeconds: 0

      containers:

      - name: gasida-web

        image: gasida/httpd:pp

        ports:

        - containerPort: 80

---

apiVersion: v1

kind: Service

metadata:

  name: svc-nlb-ip-type-pp

  annotations:

    service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip

    service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing

    service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"

    service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: "*"

spec:

  ports:

    - port: 80

      targetPort: 80

      protocol: TCP

  type: LoadBalancer

  loadBalancerClass: service.k8s.aws/nlb

  selector:

    app: gasida-web

EOF



NLB생성에 5분 걸림.



2

 watch -d  'kubectl  get pods,svc,deploy '


NAME                         TYPE           CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE

service/kubernetes           ClusterIP      172.20.0.1    <none>        443/TCP        47h

service/svc-nlb-ip-type-pp   LoadBalancer   172.20.1.80   <pending>     80:30453/TCP   5m59s



3

# 확인

kubectl get svc,ep

kubectl describe svc svc-nlb-ip-type-pp

kubectl describe svc svc-nlb-ip-type-pp | grep Annotations: -A5


# apache에 proxy protocol 활성화 확인

kubectl exec deploy/gasida-web -- apachectl -t -D DUMP_MODULES

kubectl exec deploy/gasida-web -- cat /usr/local/apache2/conf/httpd.conf



4

# 접속 확인

NLB=$(kubectl get svc svc-nlb-ip-type-pp -o jsonpath={.status.loadBalancer.ingress[0].hostname})


curl -s $NLB


5

# 지속적인 접속 시도 : 아래 상세 동작 확인 시 유용(패킷 덤프 등)

while true; do curl -s --connect-timeout 1 $NLB; echo "----------" ; date "+%Y-%m-%d %H:%M:%S" ; sleep 1; done



6

# 로그 확인

kubectl logs -l app=gasida-web -f


3.38.213.98 - - [27/Apr/2023:21:14:06 +0000] "GET / HTTP/1.1" 200 45

3.38.213.98 - - [27/Apr/2023:21:14:07 +0000] "GET / HTTP/1.1" 200 45

[Thu Apr 27 21:14:07.681768 2023] [remoteip:error] [pid 10:tid 140571888822016] [client 172.30.52.231:45576] AH03507: RemoteIPProxyProtocol: unsupported command 20

3.38.213.98 - - [27/Apr/2023:21:14:08 +0000] "GET / HTTP/1.1" 200 45

3.38.213.98 - - [27/Apr/2023:21:14:09 +0000] "GET / HTTP/1.1" 200 45




7

# 삭제

kubectl delete deploy gasida-web; kubectl delete svc svc-nlb-ip-type-pp







<16> ingress(ALB)


1

Load Balancer Controller는 위의 NLB나 ingress 모두 처리한다.






2

EC2 instance profiles 설정 및 AWS LoadBalancer 배포 & ExternalDNS 설치 및 배포 ← 이미 설정 되어 있음


3

# 마스터/워커 노드에 EC2 IAM Role 에 Policy (AWSLoadBalancerControllerIAMPolicy) 추가

## IAM Policy 정책 생성 : 2주차에서 IAM Policy 를 미리 만들어두었으니 Skip


curl -o iam_policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.4.5/docs/install/iam_policy.json

aws iam create-policy --policy-name AWSLoadBalancerControllerIAMPolicy --policy-document file://iam_policy.json



4

# EC2 instance profiles 에 IAM Policy 추가(attach)

aws iam attach-role-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy --role-name masters.$KOPS_CLUSTER_NAME

aws iam attach-role-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy --role-name nodes.$KOPS_CLUSTER_NAME



5

# IAM Policy 정책 생성 : 2주차에서 IAM Policy 를 미리 만들어두었으니 Skip

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



6

# EC2 instance profiles 에 IAM Policy 추가(attach)

aws iam attach-role-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AllowExternalDNSUpdates --role-name masters.$KOPS_CLUSTER_NAME

aws iam attach-role-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AllowExternalDNSUpdates --role-name nodes.$KOPS_CLUSTER_NAME



7

add온으로 작업할때는 아래 추가 필요하다.

여기서는 원클릭으로 설치해서 따로 설정할 필요는 없다.

아래  9.서비스/파드 배포 테스트 부터 하면 된다.


# kOps 클러스터 편집 : 아래 내용 추가

kops edit cluster

-----

spec:

  certManager:

    enabled: true

  awsLoadBalancerController:

    enabled: true

  externalDns:

    provider: external-dns

-----


8

# 업데이트 적용

kops update cluster --yes && echo && sleep 3 && kops rolling-update cluster




9

서비스/파드 배포 테스트 with Ingress(ALB)


모니터링

watch -d kubectl get deploy,rs,svc,ep,ingress,pods



# 게임 파드와 Service, Ingress 배포

cat ~/pkos/3/ingress1.yaml | yh

kubectl apply -f ~/pkos/3/ingress1.yaml



10

인터넷 , IP 타입으로 생성한다.

    alb.ingress.kubernetes.io/scheme: internet-facing

    alb.ingress.kubernetes.io/target-type: ip



파일 내용


apiVersion: v1

kind: Namespace

metadata:

  name: game-2048

---

apiVersion: apps/v1

kind: Deployment

metadata:

  namespace: game-2048

  name: deployment-2048

spec:

  selector:

    matchLabels:

      app.kubernetes.io/name: app-2048

  replicas: 2

  template:

    metadata:

      labels:

        app.kubernetes.io/name: app-2048

    spec:

      containers:

      - image: public.ecr.aws/l6m2t8p7/docker-2048:latest

        imagePullPolicy: Always

        name: app-2048

        ports:

        - containerPort: 80

---

apiVersion: v1

kind: Service

metadata:

  namespace: game-2048

  name: service-2048

spec:

  ports:

    - port: 80

      targetPort: 80

      protocol: TCP

  type: NodePort

  selector:

    app.kubernetes.io/name: app-2048

---

apiVersion: networking.k8s.io/v1

kind: Ingress

metadata:

  namespace: game-2048

  name: ingress-2048

  annotations:

    alb.ingress.kubernetes.io/scheme: internet-facing

    alb.ingress.kubernetes.io/target-type: ip

spec:

  ingressClassName: alb

  rules:

    - http:

        paths:

        - path: /

          pathType: Prefix

          backend:

            service:

              name: service-2048

              port:

                number: 80



11

# 생성 확인

k ns game-2048


kubectl get-all -n game-2048

kubectl get ingress,svc,ep,pod -n game-2048

kubectl get targetgroupbindings -n game-2048

NAME                               SERVICE-NAME   SERVICE-PORT   TARGET-TYPE   AGE

k8s-game2048-service2-e48050abac   service-2048   80             ip            87s


# Ingress 확인

kubectl describe ingress -n game-2048 ingress-2048



12

# 게임 접속 : ALB 주소로 웹 접속

kubectl get ingress -n game-2048 ingress-2048 -o jsonpath={.status.loadBalancer.ingress[0].hostname} | awk '{ print "Game URL = http://"$1 }'

kubectl get logs -n game-2048 -l app=game-2048



13

# 파드 IP 확인

kubectl get pod -n game-2048 -owide

NAME                               READY   STATUS    RESTARTS   AGE     IP              NODE                  NOMINATED NODE   READINESS GATES

deployment-2048-6bc9fd6bf5-42v9n   1/1     Running   0          6m36s   172.30.88.130   i-07fac859b8896addd   <none>           <none>

deployment-2048-6bc9fd6bf5-8p7pq   1/1     Running   0          6m36s   172.30.47.18    i-05f82825145ee0009   <none>           <none>



콘솔에서 확인하자 

AWS 로드밸런서에서 POD IP 확인하자.



14

# 터미널1

watch kubectl get pod -n game-2048



# 터미널2 : 파드 3개로 증가

kubectl scale deployment -n game-2048 deployment-2048 --replicas 3




15

# 터미널2 : 파드 1개로 감소

kubectl scale deployment -n game-2048 deployment-2048 --replicas 1



16

삭제


kubectl delete ingress ingress-2048 -n game-2048

kubectl delete svc service-2048 -n game-2048 && kubectl delete deploy deployment-2048 -n game-2048 && kubectl delete ns game-2048




<17>  Ingress with ExternalDNS


1

# 변수 지정 - 자신의 full 도메인

WEBDOMAIN=<각자편한웹서버도메인>

WEBDOMAIN=albweb.$KOPS_CLUSTER_NAME


2

# 게임 파드와 Service, Ingress 배포

cat ~/pkos/3/ingress2.yaml | yh

WEBDOMAIN=$WEBDOMAIN envsubst < ~/pkos/3/ingress2.yaml | kubectl apply -f -


3

# 확인

kubectl get ingress,svc,ep,pod -n game-2048



4

# AWS R53 적용 확인

dig +short $WEBDOMAIN

dig +short $WEBDOMAIN @8.8.8.8




# 외부단말(집PC 등)에서 접속 확인 : curl or 웹브라우저


5

# 로그 확인

kubectl logs -n kube-system -f $(kubectl get po -n kube-system | egrep -o 'external-dns[A-Za-z0-9-]+')



6

콘솔 route53에서  도메인 등록된것을 확인하자.



7

숙제

ingress에서 /tetris  /mario에 따라  1개 로드밸런서로 서비스 되도록 해보자.

구글에서 aws kops pkos ingress 검색해서 자료 확인



8

# 삭제

kubectl delete ingress ingress-2048 -n game-2048

kubectl delete svc service-2048 -n game-2048 && kubectl delete deploy deployment-2048 -n game-2048 && kubectl delete ns game-2048



9

msa  sample

https://www.notion.so/gasidaseo/MSA-13-382799b72d5d49a9a15dcafd123c1aa8





<18> 정리


CloudFormation으로 실습 환경 한번에 구축하기

pod간 통신은 직접 통신 한다는것을 인지한다.

서버 별로 Pod생성수 제한이 있다는것을 이해한다.

Pod생성수 제한 해결법을 실습한다.

Service (LoadBalancer Controller) 사용해본다.

NLB에 TLS 적용하기

NLB에서 바로 파드로 인입 및 ClientIP 확인 설정

ingress 이해




다음과정

https://brunch.co.kr/@topasvga/3108



https://brunch.co.kr/@topasvga/3144


감사합니다.

                   

                    

매거진의 이전글 쿠버4탄-1. K8S-kOps로 쿠버네티스설치-2023
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari