์ฟ ๋ฒ๋คํฐ์ค ๋คํธ์ํฌ
ใ
ใ
ใ
ใ
ใ
ใ
ใ
ใ
์ด๋ฒ 2์ฃผ์ฐจ ์คํฐ๋์์๋ ์ฟ ๋ฒ๋คํฐ์ค ๋คํธ์ํฌ์ ๋ํด์ ํ์ต ํ ์์ ์ด๋ค.
๋ํ ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉํ๋ CNI(calico, weave net, Flannel)๊ฐ ์๋ AWS VPC๋ฅผ ์ฌ์ฉํ๋ฉด์ ์ผ๋ฐ์ ์ธ CNI์ ์ฐจ์ด์ ์ ๋ํด์ ํ์ต ํ ์์ ์ด๋ค.
์ถ๊ฐ์ ์ผ๋ก AWS ELB๋ฅผ ์ฟ ๋ฒ๋คํฐ์ค์์ ์ด๋ป๊ฒ ์ค์ ํ๊ณ ์ฌ์ฉํ๋์ง ํ์ต ํ ์์ ์ด๋ค.
CNI(Container Network Interface)๋ Pod๊ฐ ๋คํธ์ํฌ ํ๊ฒฝ์, ์ฆ ํต์ ํ๊ฒฝ์ ๊ตฌ์ฑํด ์ค๋ค. ์ผ๋ฐ์ ์ผ๋ก ๋ง์ด ์ฌ์ฉ๋๋ CNI๋ calico, weave net, Flannel ๋ฑ์ด ์๋ค.
์ด๋ฒ ์คํฐ๋์์ ์ฌ์ฉํ๋ KOPS์์๋ AWS์์ ๊ตฌ์ฑ๋์๊ณ , CNI๋ํ AWS VPC๋ฅผ ์ฌ์ฉํ๋ค.
AWS VPC๊ฐ ๋ค๋ฅธ CNI์ ๋ค๋ฅธ ์ ์ ๋
ธ๋์ ํ๋์ ๋คํธ์ํฌ ๋์ญ์ด ๊ฐ์ ํต์ ์ํฉ์ด ํจ์ฌ ๊ฐ๊ฒฐํ๋ค๋ ๋ถ๋ถ์ด๋ค.
# CNI ์ ๋ณด ํ์ธ
kubectl describe daemonset aws-node --namespace kube-system | grep Image | cut -d "/" -f 2
amazon-k8s-cni-init:v1.11.4
amazon-k8s-cni:v1.11.4
# ๋
ธ๋ 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
# ํ๋ IP ํ์ธ
kubectl get pod -n kube-system -o=custom-columns=NAME:.metadata.name,IP:.status.podIP,STATUS:.status.phase
[Node2์ ๋คํธ์ํฌ ์ ๋ณด]
ํ์ฌ NIC๊ฐ 2๊ฐ(ens5, ens6), ๋
ผ๋ฆฌ NIC๊ฐ 2๊ฐ
ํ๋๊ฐ ํต์ ํ๋ฆ : ๋ณ๋์ ์ค๋ฒ๋ ์ด(Overlay) ํต์ ๊ธฐ์ ์์ด, VPC Native ํ๊ฒ ํ๋๊ฐ ์ง์ ํต์ ์ด ๊ฐ๋ฅํ๋ค
# ํ๋ IP ๋ณ์ ์ง์
POD1=$(kubectl get pod pod-1 -o jsonpath={.status.podIP})
POD2=$(kubectl get pod pod-2 -o jsonpath={.status.podIP})
# ํ๋1 Shell ์์ ํ๋2๋ก ping ํ
์คํธ
kubectl exec -it pod-1 -- ping -c 2 $POD2
# ํ๋2 Shell ์์ ํ๋1๋ก ping ํ
์คํธ
kubectl exec -it pod-2 -- ping -c 2 $POD1
#๊ฐ ๋
ธ๋์์ tcpdump ๋ชจ๋ํฐ๋ง
sudo tcpdump -i any -nn icmp
[TIP] ๋ ๋ฒ์งธ ENI์์ ํ ๋น๋ ๋ณด์กฐ IP๋ฅผ ์ฌ์ฉํ๋๋ผ๋ ๋ฌด์กฐ๊ฑด ์ฒซ๋ฒ์งธ ENI๋ฅผ ํตํด ํต์ ์ด ๋๋๋ก ์ค์ ๋์ด ์์. ๋ฐ๋ผ์ ens6์ ping์ tcpdump์์ ํ์ธ ํ ์ ์์!!
ํ๋์์ ์ธ๋ถ ํต์ ํ๋ฆ : iptable ์ SNAT ์ ํตํ์ฌ ๋
ธ๋์ eth0 IP๋ก ๋ณ๊ฒฝ๋์ด์ ์ธ๋ถ์ ํต์ ๋จ
kubectl exec -it pod-1 -- curl -s ipinfo.io/ip : echo
#node1
curl -s ipinfo.io/ip : echo
#์ถ๋ ฅ๋๋ ๊ณต์ธ IP ํ์ธ
Node1์ Public IP ์ถ๋ ฅ!
# ํ๋๊ฐ ์ธ๋ถ์ ํต์ ์์๋ ์๋ ์ฒ๋ผ 'AWS-SNAT-CHAIN-0, AWS-SNAT-CHAIN-1' ๋ฃฐ(rule)์ ์ํด์ SNAT ๋์ด์ ์ธ๋ถ์ ํต์ !
# ์ฐธ๊ณ ๋ก ๋ค IP๋ eth0(ENI ์ฒซ๋ฒ์งธ)์ IP ์ฃผ์์ด๋ค
# --random-fully ๋์ - ๋งํฌ1 ๋งํฌ2
sudo iptables -t nat -S | grep 'A AWS-SNAT-CHAIN'
-A AWS-SNAT-CHAIN-0 ! -d 172.30.0.0/16 -m comment --comment "AWS SNAT CHAIN" -j AWS-SNAT-CHAIN-1
-A AWS-SNAT-CHAIN-1 ! -o vlan+ -m comment --comment "AWS, SNAT" -m addrtype ! --dst-type LOCAL -j SNAT --to-source 172.30.85.242 --random-fully
## ์๋ 'mark 0x4000/0x4000' ๋งค์นญ๋์ง ์์์ RETURN ๋จ!
-A KUBE-POSTROUTING -m mark ! --mark 0x4000/0x4000 -j RETURN
-A KUBE-POSTROUTING -j MARK --set-xmark 0x4000/0x0
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE --random-fully
...
# ์นด์ดํธ ํ์ธ ์ AWS-SNAT-CHAIN-0, AWS-SNAT-CHAIN-1 ์ ๋งค์นญ๋์ด, ๋ชฉ์ ์ง๊ฐ 172.30.0.0/16 ์๋๊ณ ์ธ๋ถ ๋น ์ ธ๋๊ฐ๋ SNAT 172.30.85.242 ๋ณ๊ฒฝ๋์ด ๋๊ฐ๋ค!
sudo iptables -t filter --zero; sudo iptables -t nat --zero; sudo iptables -t mangle --zero; sudo iptables -t raw --zero
watch -d 'sudo iptables -v --numeric --table nat --list AWS-SNAT-CHAIN-0; echo ; sudo iptables -v --numeric --table nat --list AWS-SNAT-CHAIN-1; echo ; sudo iptables -v --numeric --table nat --list KUBE-POSTROUTING'
# conntrack ํ์ธ
sudo conntrack -L -n |grep -v '169.254.169'
conntrack v1.4.5 (conntrack-tools):
icmp 1 28 src=172.30.66.58 dst=8.8.8.8 type=8 code=0 id=34392 src=8.8.8.8 dst=172.30.85.242 type=0 code=0 id=50705 mark=128 use=1
tcp 6 23 TIME_WAIT src=172.30.66.58 dst=34.117.59.81 sport=58144 dport=80 src=34.117.59.81 dst=172.30.85.242 sport=80 dport=44768 [ASSURED] mark=128 use=1
Secondary IPv4 addresses : ์ธ์คํด์ค ์ ํ์ ์ต๋ ENI ๊ฐฏ์์ ํ ๋น ๊ฐ๋ฅ IP ์๋ฅผ ์กฐํฉํ์ฌ ์ ์
์์ปค ๋ ธ๋์ ์ธ์คํด์ค ํ์ ๋ณ ํ๋ ์์ฑ ๊ฐฏ์ ์ ํ
์ต๋ ํ๋ ์์ฑ ๊ฐฏ์ : (Number of network interfaces for the instance type ร (the number of IP addressess per network interface - 1)) + 2
# t3 ํ์
์ ์ ๋ณด(ํํฐ) ํ์ธ
aws ec2 describe-instance-types --filters Name=instance-type,Values=t3.* \
--query "InstanceTypes[].{Type: InstanceType, MaxENI: NetworkInfo.MaximumNetworkInterfaces, IPv4addr: NetworkInfo.Ipv4AddressesPerInterface}" \
--output table
# ํ๋ ์ฌ์ฉ ๊ฐ๋ฅ ๊ณ์ฐ ์์ : 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
AWS NLB์ ํ๊ฒ ๊ทธ๋ฃน์ Pod์ IP๊ฐ ์ง์ ๋ฐ์ธ๋ฉ ๋์ด ํต์ , iptable์ Rule์ ํ์ง ์์!!
๋ก๋๋ฐธ๋ฐ์ค ์ปจํธ๋กค๋ฌ๊ฐ Endpint์ ์ ๋ณด๋ฅผ ์ฆ Pod์ ์ ๋ณด๋ฅผ KOPS๋ฅผ ํตํด์ ์ฃผ๊ธฐ์ ์ผ๋ก ๋ชจ๋ํฐ๋งํด์ NLB์ ํด๋น ์ ๋ณด๋ฅผ ์ ๊ณต!
# kOps ํด๋ฌ์คํฐ ํธ์ง : ์๋ ๋ด์ฉ ์ถ๊ฐ
kops edit cluster
-----
spec:
awsLoadBalancerController:
enabled: true
-----
# ์
๋ฐ์ดํธ ์ ์ฉ : ์ ์ฉ์ด ์๋ ๊ฒฝ์ฐ ํ๋ฒ ๋ ์๋ ๋ช
๋ น ์คํ
kops update cluster --yes && echo && sleep 5 && kops rolling-update cluster
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
NLB=$(kubectl get svc svc-nlb-ip-type -o jsonpath={.status.loadBalancer.ingress[0].hostname})
for i in {1..100}; do curl -s $NLB | grep Hostname ; done | sort | uniq -c | sort -nr
kubectl scale deployment deploy-echo --replicas=1
kubectl scale deployment deploy-echo --replicas=3
K8S ์๋น์ค/์ธ๊ทธ๋ ์ค ์์ฑ ์ ๋๋ฉ์ธ์ ์ค์ ํ๋ฉด, AWS(Route 53), Azure(DNS), GCP(Cloud DNS) ์ A ๋ ์ฝ๋(TXT ๋ ์ฝ๋)๋ก ์๋ ์์ฑ/์ญ์
# ์ค์น
kops edit cluster
--------------------------
spec:
externalDns:
provider: external-dns
--------------------------
# ์
๋ฐ์ดํธ ์ ์ฉ
kops update cluster --yes && echo && sleep 5 && kops rolling-update cluster
# ๋ฒ์ ํ์ธ : v0.12.2
kubectl describe deploy -n kube-system external-dns | grep Image | cut -d "/" -f 3
# externalDns ์ปจํธ๋กค๋ฌ ํ๋ ํ์ธ
kubectl get pod -n kube-system -l k8s-app=external-dns
NAME READY STATUS RESTARTS AGE
external-dns-7bf9bd8994-f2r58 1/1 Running 0 16s
kubectl apply -f ~/pkos/2/echo-service-nlb.yaml
MyDOMAIN1=<๊ฐ์ ์์ ์ nginx ๋๋ฉ์ธ ์ง์ >
MyDOMAIN1=nginx.burst89.com
kubectl annotate service svc-nlb-ip-type "external-dns.alpha.kubernetes.io/hostname=$MyDOMAIN1."
kubectl describe svc svc-nlb-ip-type | grep Annotations: -A5
# ํ์ธ
dig +short $MyDOMAIN1
# ๋ถ์ฐ ์ ์ ํ์ธ
curl -s $MyDOMAIN1
for i in {1..100}; do curl -s $MyDOMAIN1 | grep Hostname ; done | sort | uniq -c | sort -nr
[๊ณผ์ 1] ํ๋ ๊ฐ ํต์ ์ tcpdump ๋ด์ฉ์ ํ์ธํ๊ณ ๊ด๋ จ ์ค์ท์ ์ฌ๋ ค์ฃผ์ธ์.
#k get nodes -o wide(๋
ธ๋ ์ ๋ณด / ๋นจ๊ฐ Box๊ฐ Pod๊ฐ ์์ฑ๋ Node)
#k get pods -o wide
#kubectl exec -it pod-1 โ ping -c 2 $POD2
// Pod1์์ Pod2๋ก Ping ํต์
#sudo tcpdump -i ens5 -nn icmp
// Node1์์ ens5 ์ธํฐํ์ด์ค๋ฅผ ํตํด tcpdump -> ํต์ ํ์ธ
172.30.49.61 : Pod-1 IP / 172.30.71.69 : Pod-2 IP
ํด๋น IP๋ฅผ ํตํด ๋ณ๋์ NAT ๋์ ์์ด ํต์ ํ๋ ๊ฒ์ ํ์ธ ํ ์ ์์
-> ์ด์ ๋ VPC CNI๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์!!
#sudo tcpdump -i ens5 -nn icmp
/ Node2์์ ens5 ์ธํฐํ์ด์ค๋ฅผ ํตํด tcpdump -> ํต์ ํ์ธ
[๊ณผ์ 2] ์ด๋ค ๋ฐฉ์์ ์ฌ์ฉํ๋๋ผ๊ณ ์ข์ผ๋, ์์ปค ๋
ธ๋ 1๋์ 100๋์ ํ๋๊ฐ ๋ฐฐํฌ๋๊ฒ ์ค์ ํ๊ณ ๊ด๋ จ ์ค์ท์ ์ฌ๋ ค์ฃผ์ธ์.
์ด๊ธฐ kops ํด๋ฌ์คํฐ ๊ตฌ์ฑ์ c5.large๋ก ํ๊ณ worker node์ ์๋ฅผ 1๋ก ์ค์ ํ์ฌ ํด๋ฌ์คํฐ๋ฅผ ๊ตฌ์ฑํ์๋ค.
#๊ตฌ์ฑ ํ ์ต๋ Pod์๋ฅผ๋ณด๋ฉด 29์ธ ๊ฒ์ ๋ณผ ์ ์๋ค.
VPC CNI Nerwork ์ค์
kubelet์ maxPods์๋ฅผ ์ค์ / networking์ WARM_PRENFIX_TARGET / PREFIX_DELEGATION ์ค์
kops edit cluster --state s3://๋ฒํท์ด๋ฆ
์ค์ ํ cluster ์
๋ฐ์ดํธ
์
๋ฐ์ดํธ ์ Master Node ์์ฒด๊ฐ ๋ณ๊ฒฝ๋์ด IP๋ ๋ณ๊ฒฝ๋๋ค. ๋ฐ๋ผ์ ๋๋ฉ์ธ์ api ์ฃผ์๋ ๋ณ๊ฒฝํด์ค์ผ ํจ. -> ํด๋น ์์
์ด ์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆผ
(์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆฌ๋ฉด ์์์ ์ด ๋ถ๋ถ๋ ๋ณ๊ฒฝ๋๋ ๊ฐ๋ค.)
Worker node๊ฐ ๋ณ๊ฒฝ ํ์ธ
๋
ธ๋ ์ต๋ Pod ์ ๋ณ๊ฒฝ ํ์ธ
PREFIX_DELEGATION ๋ฐ WARM_PREFIX_TARGET ์ค์ ํ์ธ
LimitRange ์ค์ ๋ณ๊ฒฝ
๊ธฐ์กด limits๋ผ๋ LimitRange ์ค๋ธ์ ํธ๊ฐ ์กด์ฌํ๋ฉฐ, ํ์ฌ cpu 100m์ผ๋ก ์ค์ ๋์ด ์๋ค.
์ค๋ธ์ ํธ์ editํ์ฌ cpu 100m ์ค์ ์ญ์
Pod100๊ฐ ๋ฐฐํฌ ๋ฐ ํ์ธ
kubectl apply -f ~/pkos/2/nginx-dp.yaml
kubectl scale deployment nginx-deployment --replicas=100
์ถ๊ฐ์ ์ผ๋ก t3.medium ์ธ์คํด์ค์์๋ Test๋ฅผ ์งํํ์๋ค. ํด๋ฌ์คํฐ ๊ตฌ์ฑ ์ , maxpod ์ ํ์ธ : 110๊ฐ(c5.large)์ ๋์ผ
์ ๊ณผ์ ์ ๋์ผํ๊ฒ ์งํ ํ ๋จ์ผ ๋
ธ๋(t3.medium)์ Pod 100๊ฐ ๋ฐฐํฌ ๋ฐ ํ์ธ
[๊ณผ์ 3] ์๋น์ค(NLB)/ํ๋ ๋ฐฐํฌ ์ ExternalDNS ์ค์ ํด์, ๊ฐ์ ์์ ์ ๋๋ฉ์ธ์ผ๋ก NLB๋ฅผ ํตํด ์ ํ๋ฆฌ์ผ์ด์ (ํ๋)๋ก ์ ์ํด๋ณด๊ณ ๊ด๋ จ ์ค์ท์ ์ฌ๋ ค์ฃผ์ธ์. ํผ๋ธ๋ฆญ ๋๋ฉ์ธ์ด ์๋ ๋ฉค๋ฒ๋ถ๋ค์, ExternalDNS ์ ์ธํ๊ณ NLB ๋๋ฉ์ธ์ผ๋ก ์ ์ํ ๊ฒฐ๊ณผ๋ฅผ ์ฌ๋ ค์ฃผ์ธ์.
#nginx.burst89.com
์ฌ์ค ์ด๋ฒ ์คํฐ๋ ๋ด์ฉ์ด ์กฐ๊ธ์ ์ด๋ ค์ ๋ค. ์๋ ๋ด์ฉ๋ ์์์ง๋ง, Service์ ๋ด์ฉ์ด ๋ง์ด ํท๊ฐ๋ ธ๋ค... ํต์ฌ์ AWS VPC CNI๋ฅผ ์ฌ์ฉํ๋ฉด, ๋
ธ๋์ IP์ Pod์ IP๊ฐ ๊ฐ์ ๋์ญ์ ์ฌ์ฉํ๋ค.
๋ํ ๋ก๋๋ฐธ๋ฐ์ ์ปจํธ๋กค๋ฌ๋ฅผ ์ฌ์ฉํ๋ฉด ๋ก๋๋ฐธ๋ฐ์ค ํ๊ฒ๋์์ Pod์ IP๊ฐ ์ง์ ์ฐ๊ฒฐ๋๋ฉฐ, ์ปจํธ๋กค๋ฌ๊ฐ ๊ณ์ํด์ ๋ชจ๋ํฐ๋ง์ ํ๊ณ ํด๋น ๋ด์ฉ์ ๋ก๋๋ฐธ๋ฐ์์๊ฒ ์ ๋ฌํ์ฌ ํ๊ฒ์ ์ ๋ณด๋ฅผ ํ์ธ ํ์ฌ ๋ณด๋ค ํจ๊ณผ์ ์ผ๋ก Service๋ฅผ ์ด์ํ ์ ์๋ค๋ ๋ด์ฉ์ด๋ค!!
์ถ๊ฐ์ ์ผ๋ก ๋
ธ๋์ ์ต๋ Pod ์ ๊ณผ์ ๋ ์ง์ง ์ด๋ ค์ ๋ค......ใ
ใ
3์ผ์ ๊ฑธ๋ ค์ ํด๋น ๊ณผ์ ๋ฅผ ํด๊ฒฐํ ์ ์์๋ค. ์ ์ ๋์ด๋๊ฐ ์ด๋ ค์ ์ง๋ ๋๋์ด ๋ ๋ค.. ๊ทธ๋๋ ํ์ดํ
!!!!!!!