2/11
CloudFormation으로 실습 환경 한번에 구축하기
pod간 통신은 직접 통신 한다는것을 인지한다.
서버 별로 Pod생성수 제한이 있다는것을 이해한다.
Service (LoadBalancer Controller) 사용.
NLB에 TLS 적용하기
NLB에서 바로 파드로 인입 및 ClientIP 확인 설정
ingress 이해
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
mykops
3
kops-ec2 에 로그온해서 master, node 서버들이 만들어지는지 모니터링 하자.
kops로 생성 모니터링
(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
오류로 안될때
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
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
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
1
K8S Calico CNI 와 AWS VPC CNI 차이
K8S Calico CNI 는 pod대역과 노드 대역이 다르다.
AWS VPC CNI는 워커 노드와 파드의 네트워크 대역을 동일하다.
네트워크 통신의 최적화(성능, 지연)
2
kops는 아직 Pod를 위한 보안그룹은 지원하지 않는다. 2023년 4월 현재.
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
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
5
node cpu mem, pod cpu mem 한눈에 보기 ?
kubectl ktop
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
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
1
파드간 통신 흐름 : AWS VPC CNI 경우 별도의 오버레이(Overlay) 통신 기술 없이, VPC Native 하게 파드간 직접 통신이 가능하다
1번 node , 2 node 간 pod 통신하자.
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가 찍힌다 !!!!
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는 어떤 주소인가?
콘솔에서 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
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
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
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 = 로드밸런서의 타켓 그룹
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
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
기본적으로 외부에서 접속하면 사용자 IP가 안보인다.
Client IP를 확인할수 있도록 미리 만들어놓은 이미지 , apache에 proxy 프로토콜로 들어오면 ip를 확인할수 있도록 미리 만들어놓은 이미지 사용한다.
로그 보자.
참고
https://canaryrelease.tistory.com/42
# 생성
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
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
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
CloudFormation으로 실습 환경 한번에 구축하기
pod간 통신은 직접 통신 한다는것을 인지한다.
서버 별로 Pod생성수 제한이 있다는것을 이해한다.
Pod생성수 제한 해결법을 실습한다.
Service (LoadBalancer Controller) 사용해본다.
NLB에 TLS 적용하기
NLB에서 바로 파드로 인입 및 ClientIP 확인 설정
ingress 이해
https://brunch.co.kr/@topasvga/3108
https://brunch.co.kr/@topasvga/3144
감사합니다.