EKS Cluster Endpoint Access
EKS 환경에서 컨트롤 플레인 영역은 AWS 관리형 서비스로 동작합니다.
이에 따라 쿠버네티스 API 서버의 접근에 대한 방법으로 Endpoint Access를 3가지 형태로 정의하고 있습니다.
[출처: ongja blog]
Endpoint Access 설정 | 설명 | 보안 수준 |
Public Access | 인터넷에서 접근 가능 (IP 제한 가능) | 낮음 |
Private Access | VPC 내부에서만 접근 가능 | 높음 |
Public + Private (혼합) | VPC 내부 + 특정 Public IP에서 접근 가능 | 중간 |
1. Public Cluster Endpoint Access
- 인터넷을 통해 모든 IP 또는 IP 제한을 하지 않을 경우 보안에 취약
- kubectl을 사용하여 aws 외부에서 EKS 클러스터 관리에 용이
✅ 장점
- 외부에서 쉽게 접근 가능
- VPC 외부에서 관리할 수 있어 편리
❌ 단점
- 보안에 취약함 (IP 제한을 설정하지 않았을 경우)
Public Cluster Endpoint Access 아키텍처
Public Only Access가 필요한 사례
- 단기 테스트 환경
- 빠르게 EKS를 생성하고, 일시적 테스트 수행 시
- 보안보다 운영의 편의성이 우선될 경우
- 특정 시간 후 삭제될 것이 확정적일 경우 - Kubernetes 교육 및 실습 환경
- EKS를 교육 목적으로 사용하는 경우
- 여러 명의 사용자가 서로 다른 지역에서 kubectl을 사용해야 하는 경우
- 내부 네트워크 없이 빠르게 접근이 필요한 경우
2. Private Cluster Endpoint Access
- EKS API 서버에 VPC 내부의 프라이빗 네트워크에서만 접근 가능
(ex. 같은 대역의 VPC 또는 Peer VPC와 같이 사설 통신이 가능한 구간에서만 접근 가능) - 인터넷(공개망)에서는 API 서버에 접근 불가
- VPC 내에서 AWS PrivateLink를 통해 접근 가능
✅ 장점
- API 서버가 인터넷에 노출되지 않아 보안적인 구성
- AWS 내부 서비스와 통신 시 안전한 네트워크 환경 사용 가능
❌ 단점
- VPC 외부에서 kubectl 명령어로 클러스트 접근 불가
- 사용자 입장에서는 다소 불편함이 존재
Private Cluster Endpoint Access 아키텍처
Private Only Access가 필요한 사례
- 프로적션 환경
- 운영 환경에서는 보안이 중요한 요소이므로 Private 환경 권장
- 접근 시 bastion 또는 vpn을 통해 접근 - 온프레미스와 연동되는 경우
- 회사 내부에서 운영되는 Private Cluster와 EKS를 연동하는 경우 보안을 위해 인터넷망 접근 차단
- ERP, CRM 등 내부 시스템과 같이 외부 공개가 필요 없는 서비스
- VPC Peer, Direct Connect로 연결된 사설망에서만 접근하도록 구성
2. Public & Private Cluster Endpoint Access
- API 서버가 인터넷과 VPC 내부 모두에서 접근 가능
- Public Access를 활성화하되 특정 IP 대역에서만 허용
✅ 장점
- 내부 네트워크에서 접근 가능하며, 외부에서도 접근 가능한 요건 충족
❌ 단점
- Public Access 설정이 잘못되면 보안 위협 발생
- 설정 관리가 복잡
Public & Private Cluster Endpoint Access 아키텍처
Public & Private 가 필요한 사례
- CI/CD 파이프라인이 AWS 외부에서 실행될 때
- CI/CD가 AWS 외부에서 실행하고, 별도의 Direct 구성이 없을 경우 - 외주 개발사가 외부에서 작업하는 경우
- 내부망이 아닌 외부에서 접근해야하는 경우라면 IP 허용을 통해 Public Access 설정
[데이터 플레인] 노드 정보 상세 확인
Worker Node SSH 접속
- Worker Node에 대한 정보 확인
## AWS CLI를 통해 Instance 별 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
-----------------------------------------------------------------------------
| DescribeInstances |
+-----------------------------+----------------+----------------+-----------+
| InstanceName | PrivateIPAdd | PublicIPAdd | Status |
+-----------------------------+----------------+----------------+-----------+
| myeks-myeks-nodegroup-Node | 192.168.2.218 | 43.200.171.47 | running |
| myeks-host | 192.168.1.100 | 3.34.192.233 | running |
| myeks-myeks-nodegroup-Node | 192.168.1.181 | 43.202.59.138 | running |
+-----------------------------+----------------+----------------+-----------+
## zone 정보를 node 조회 컬럼에 추가
$ k get node --label-columns=topology.kubernetes.io/zone
NAME STATUS ROLES AGE VERSION ZONE
ip-192-168-1-181.ap-northeast-2.compute.internal Ready <none> 3h13m v1.31.4-eks-aeac579 ap-northeast-2a
ip-192-168-2-218.ap-northeast-2.compute.internal Ready <none> 3h13m v1.31.4-eks-aeac579 ap-northeast-2c
## 추가된 컬럼 중 ap-northeast-2a node 조회
$ k get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2a
NAME STATUS ROLES AGE VERSION ZONE
ip-192-168-1-181.ap-northeast-2.compute.internal Ready <none> 3h15m v1.31.4-eks-aeac579 ap-northeast-2a
## 추가된 컬럼 중 ap-northeast-2c node 조회
$ k get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2c
NAME STATUS ROLES AGE VERSION ZONE
ip-192-168-2-218.ap-northeast-2.compute.internal Ready <none> 3h17m v1.31.4-eks-aeac579 ap-northeast-2c
## 각 NODE의 사설 IP 변수 지정
N1=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2a -o jsonpath={.items[0].status.addresses[0].address})
N2=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2c -o jsonpath={.items[0].status.addresses[0].address})
echo $N1, $N2
- 각 Node로 통신 테스트
## 각 NODE로 Ping 통신
ping -c 1 $N1
--- 192.168.1.181 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms
ping -c 1 $N2
--- 192.168.2.218 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms
통신이 실패하는 이유는 Worker node에 ICMP 관련 정책이 없기 때문입니다.
정책을 추가하고 다시 한번 테스트해봅니다.
## Worker node group SG ID 확인
$ aws ec2 describe-security-groups --filters Name=group-name,Values=*nodegroup* --query "SecurityGroups[*].[GroupId]" --output text
sg-0e8897e77d594038b
## SG ID 변수 지정
$ NGSGID=$(aws ec2 describe-security-groups --filters Name=group-name,Values=*nodegroup* --query "SecurityGroups[*].[GroupId]" --output text)
echo $NGSGID
sg-0e8897e77d594038b
## Nodegroup SG에 정책 추가
$ aws ec2 authorize-security-group-ingress --group-id $NGSGID --protocol '-1' --cidr $(ifconfig eth0 | grep 'inet ' | awk '{print $2}')/32
{
"Return": true,
"SecurityGroupRules": [
{
"SecurityGroupRuleId": "sgr-06208997dc6860bbf",
"GroupId": "sg-0e8897e77d594038b",
"GroupOwnerId": "",
"IsEgress": false,
"IpProtocol": "-1",
"FromPort": -1,
"ToPort": -1,
"CidrIpv4": "192.168.1.100/32",
"SecurityGroupRuleArn": "arn:aws:ec2:ap-northeast-2::security-group-rule/sgr-06208997dc6860bbf"
}
]
}
- 다시 PING 테스트
$ ping -c 1 $N1
--- 192.168.1.181 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.361/0.361/0.361/0.000 ms
$ ping -c 1 $N2
--- 192.168.2.218 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 1.030/1.030/1.030/0.000 ms
방화벽 정책 추가 후 정상적으로 통신이 되는 것을 확인할 수 있습니다.
- Worker Node SSH 접속
## worker node 1번의 hostname 및 ssh 통신 확인
$ ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no ec2-user@$N1 hostname
ip-192-168-1-181.ap-northeast-2.compute.internal
$ ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no ec2-user@$N2 hostname
ip-192-168-2-218.ap-northeast-2.compute.internal
## SSH 접속
$ ssh ec2-user@$N1
$ ssh ec2-user@$N2
- Node 네트워크 정보 확인
## 네임스페이스 이동
k ns kube-system
## Daemonset 확인
$ k get ds aws-node
## aws-node에 대한 ECR 주소와 이미지 버전 확인
$ k describe daemonset aws-node | grep Image
Image: 602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/amazon-k8s-cni-init:v1.19.0-eksbuild.1
Image: 602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/amazon-k8s-cni:v1.19.0-eksbuild.1
Image: 602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/amazon/aws-network-policy-agent:v1.1.5-eksbuild.1
## 이미지 버전만 확인
$ k describe daemonset aws-node | grep Image | cut -d "/" -f 2
amazon-k8s-cni-init:v1.19.0-eksbuild.1
amazon-k8s-cni:v1.19.0-eksbuild.1
amazon
## kube-system ns의 pod ip 확인
$ k get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
aws-node-cqqfl 2/2 Running 0 5h1m 192.168.2.218 ip-192-168-2-218.ap-northeast-2.compute.internal <none> <none>
aws-node-jsmpn 2/2 Running 0 5h1m 192.168.1.181 ip-192-168-1-181.ap-northeast-2.compute.internal <none> <none>
coredns-9b5bc9468-bs7kp 1/1 Running 0 5h5m 192.168.1.130 ip-192-168-1-181.ap-northeast-2.compute.internal <none> <none>
coredns-9b5bc9468-zbmh9 1/1 Running 0 5h5m 192.168.1.152 ip-192-168-1-181.ap-northeast-2.compute.internal <none> <none>
kube-proxy-68tw2 1/1 Running 0 5h1m 192.168.1.181 ip-192-168-1-181.ap-northeast-2.compute.internal <none> <none>
kube-proxy-b4z9b 1/1 Running 0 5h1m 192.168.2.218 ip-192-168-2-218.ap-northeast-2.compute.internal <none> <none>
metrics-server-86bbfd75bb-46nrw 1/1 Running 0 5h5m 192.168.1.190 ip-192-168-1-181.ap-northeast-2.compute.internal <none> <none>
metrics-server-86bbfd75bb-zqrn7 1/1 Running 0 5h5m 192.168.1.241 ip-192-168-1-181.ap-northeast-2.compute.internal <none> <none>
## kube-system의 pod 중 k8s-app=kube-dns 라벨이 지정된 pod 확인
$ k get pod -l k8s-app=kube-dns -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
coredns-9b5bc9468-bs7kp 1/1 Running 0 5h6m 192.168.1.130 ip-192-168-1-181.ap-northeast-2.compute.internal <none> <none>
coredns-9b5bc9468-zbmh9 1/1 Running 0 5h6m 192.168.1.152 ip-192-168-1-181.ap-northeast-2.compute.internal <none> <none>
- Node의 IP 관련 정보 확인
## node ip로 hostname 확인
$ for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i hostname; echo; done
>> node 192.168.1.181 <<
ip-192-168-1-181.ap-northeast-2.compute.internal
>> node 192.168.2.218 <<
ip-192-168-2-218.ap-northeast-2.compute.internal
## node IP 정보 확인
### NODE 1번의 eni는 VPC CNI로 Netowkr NS를 쓰고있고, kube-system에서 사용하는 codedns, kube-proxy, metric-server에서 사용하고 있음
$ for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i sudo ip -c addr; echo; done
>> node 192.168.1.181 <<
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
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP group default qlen 1000
link/ether 02:d1:7f:74:5c:91 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.181/24 brd 192.168.1.255 scope global dynamic eth0
valid_lft 3092sec preferred_lft 3092sec
inet6 fe80::d1:7fff:fe74:5c91/64 scope link
valid_lft forever preferred_lft forever
3: eni125fa0cc687@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP group default
link/ether 7e:81:20:4e:5a:c1 brd ff:ff:ff:ff:ff:ff link-netns cni-fb4ca3a9-2abe-e0fb-789d-ecfaa99ff186
inet6 fe80::7c81:20ff:fe4e:5ac1/64 scope link
valid_lft forever preferred_lft forever
4: eni69b746e079a@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP group default
link/ether d2:fa:8d:a6:61:9f brd ff:ff:ff:ff:ff:ff link-netns cni-58834fda-58fe-54d7-f891-d13d07c69a73
inet6 fe80::d0fa:8dff:fea6:619f/64 scope link
valid_lft forever preferred_lft forever
5: eni37a762f65bf@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP group default
link/ether 9a:12:2e:40:74:d6 brd ff:ff:ff:ff:ff:ff link-netns cni-eb165745-28f9-1aed-19af-08471f9cefe4
inet6 fe80::9812:2eff:fe40:74d6/64 scope link
valid_lft forever preferred_lft forever
6: eni08441b122c2@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP group default
link/ether 22:66:dc:6f:58:96 brd ff:ff:ff:ff:ff:ff link-netns cni-a1baa08a-9751-ea2e-9334-9d280a235624
inet6 fe80::2066:dcff:fe6f:5896/64 scope link
valid_lft forever preferred_lft forever
7: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP group default qlen 1000
link/ether 02:9d:39:97:be:9b brd ff:ff:ff:ff:ff:ff
inet 192.168.1.9/24 brd 192.168.1.255 scope global eth1
valid_lft forever preferred_lft forever
inet6 fe80::9d:39ff:fe97:be9b/64 scope link
valid_lft forever preferred_lft forever
>> node 192.168.2.218 <<
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
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP group default qlen 1000
link/ether 0a:ff:46:23:52:ed brd ff:ff:ff:ff:ff:ff
inet 192.168.2.218/24 brd 192.168.2.255 scope global dynamic eth0
valid_lft 3343sec preferred_lft 3343sec
inet6 fe80::8ff:46ff:fe23:52ed/64 scope link
valid_lft forever preferred_lft forever
## node route 정보 확인
$ for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i sudo ip -c route; echo; done
>> node 192.168.1.181 <<
default via 192.168.1.1 dev eth0
169.254.169.254 dev eth0
192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.181
192.168.1.130 dev eni08441b122c2 scope link
192.168.1.152 dev eni125fa0cc687 scope link
192.168.1.190 dev eni69b746e079a scope link
192.168.1.241 dev eni37a762f65bf scope link
>> node 192.168.2.218 <<
default via 192.168.2.1 dev eth0
169.254.169.254 dev eth0
192.168.2.0/24 dev eth0 proto kernel scope link src 192.168.2.218
## node iptables 확인
$ for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i sudo iptables -t nat -S; echo; done
IPTABLES 룰셋 간략 설명
- prerouting
- 트래픽이 들어오면 kube-services로 포워딩
- eni+ 인터페이스를 통해 들어오는 트래픽은 aws-connmark-chain-0으로 포워딩
- output
- worker node 에서 나가는 kubernetes 서비스 트래픽은 kube-services로 포워딩
- aws 관련
- 192.168.0.0/16 으로 향하는 트래픽은 connmark 처리를 하지 않음
- 내부로 가는 패킷은 SNAT 적용하지 않음
- kubernetes 관련
- 10.100.93.201:443 을 호출하면 metrics-server로 포워딩
- 10.100.0.1:443을 호출하면 api-server로 포워딩
- 10.100.0.10:53을 호출하면 kube-dns로 포워딩
NODE 프로세스 정보 확인
Dockershim과 cir-containerd의 차이
1. Dockershim
- Kubelet이 CRI를 통해 dockershim과 통신
- dockershim이 docker와 통신
- docker가 containerd와 통신
- containerd가 최종적으로 컨테이너 관리
2. cri-containerd
- Kubelet이 CRI를 통해 직접 cri-containerd와 통신
- cri-containerd가 containerd와 직접 통신
- containerd가 최종적으로 컨테이너 관리
dockershim과 cir-containerd의 차이는 docker 레이어를 제거하고, 간단한 구조를 갖고 있습니다.
쿠버네티스에서도 docker의 지원을 중단하고 containerd와 같은 컨테이너 런타임을 권장하게된 이유 중 하나입니다.
각 worker node에서 실행 중인 프로세스와 데몬 확인
## kubelet daemon status
$ for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i sudo systemctl status kubelet; echo; done
● kubelet.service - Kubernetes Kubelet
Loaded: loaded (/etc/systemd/system/kubelet.service; enabled; vendor preset: disabled)
Drop-In: /etc/systemd/system/kubelet.service.d
└─10-kubelet-args.conf, 30-kubelet-extra-args.conf
Active: active (running) since Sat 2025-02-08 05:28:13 UTC; 4min 14s ago
Docs: https://github.com/kubernetes/kubernetes
Process: 2892 ExecStartPre=/sbin/iptables -P FORWARD ACCEPT -w 5 (code=exited, status=0/SUCCESS)
Main PID: 2899 (kubelet)
Tasks: 12
Memory: 94.6M
CGroup: /runtime.slice/kubelet.service
## 프로세스 리스트, 시스템 파드가 실행되고 있는 node에 따라 약간의 차이가 있다.
$ for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i sudo pstree; echo; done
systemd-+-2*[agetty]
|-amazon-ssm-agen-+-ssm-agent-worke---8*[{ssm-agent-worke}]
| `-8*[{amazon-ssm-agen}]
|-auditd---{auditd}
|-chronyd
|-containerd---12*[{containerd}]
|-containerd-shim-+-aws-vpc-cni-+-aws-k8s-agent---7*[{aws-k8s-agent}]
| | `-3*[{aws-vpc-cni}]
| |-controller---6*[{controller}]
| |-pause
| `-11*[{containerd-shim}]
|-containerd-shim-+-kube-proxy---4*[{kube-proxy}]
| |-pause
| `-10*[{containerd-shim}]
|-containerd-shim-+-metrics-server---7*[{metrics-server}]
| |-pause
| `-10*[{containerd-shim}]
|-crond
|-dbus-daemon
|-2*[dhclient]
|-gssproxy---5*[{gssproxy}]
|-irqbalance---{irqbalance}
|-kubelet---11*[{kubelet}]
|-lvmetad
|-master-+-pickup
| `-qmgr
|-rngd
|-rpcbind
|-rsyslogd---2*[{rsyslogd}]
|-sshd---sshd---sshd---sudo---pstree
|-systemd-journal
|-systemd-logind
`-systemd-udevd
>> node 192.168.2.247 <<
systemd-+-2*[agetty]
|-amazon-ssm-agen-+-ssm-agent-worke---9*[{ssm-agent-worke}]
| `-8*[{amazon-ssm-agen}]
|-auditd---{auditd}
|-chronyd
|-containerd---12*[{containerd}]
|-containerd-shim-+-aws-vpc-cni-+-aws-k8s-agent---7*[{aws-k8s-agent}]
| | `-3*[{aws-vpc-cni}]
| |-controller---6*[{controller}]
| |-pause
| `-11*[{containerd-shim}]
|-containerd-shim-+-kube-proxy---4*[{kube-proxy}]
| |-pause
| `-11*[{containerd-shim}]
|-2*[containerd-shim-+-coredns---7*[{coredns}]]
| |-pause]
| `-11*[{containerd-shim}]]
|-containerd-shim-+-metrics-server---7*[{metrics-server}]
| |-pause
| `-10*[{containerd-shim}]
## contaierd 기반으로 vpc-cni나 kube-proxy, coredns와 같은 시스템 파드가 실행 중인 것을 확인할 수 있다.
$ for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i ps afxuwww; echo; done
root 2893 1.1 2.2 2145936 89704 ? Ssl 05:28 0:04 /usr/bin/kubelet --config /etc/kubernetes/kubelet/kubelet-config.json --kubeconfig /var/lib/kubelet/kubeconfig --container-runtime-endpoint unix:///run/containerd/containerd.sock --image-credential-provider-config /etc/eks/image-credential-provider/config.json --image-credential-provider-bin-dir /etc/eks/image-credential-provider --node-ip=192.168.2.247 --pod-infra-container-image=602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/eks/pause:3.5 --v=2 --hostname-override=ip-192-168-2-247.ap-northeast-2.compute.internal --cloud-provider=external --node-labels=eks.amazonaws.com/sourceLaunchTemplateVersion=1,alpha.eksctl.io/cluster-name=myeks,alpha.eksctl.io/nodegroup-name=myeks-nodegroup,eks.amazonaws.com/nodegroup-image=ami-005cddfeed40e0e49,eks.amazonaws.com/capacityType=ON_DEMAND,eks.amazonaws.com/nodegroup=myeks-nodegroup,eks.amazonaws.com/sourceLaunchTemplateId=lt-0892413185f7d8935 --max-pods=17
root 2974 0.1 0.4 1238536 15804 ? Sl 05:28 0:00 /usr/bin/containerd-shim-runc-v2 -namespace k8s.io -id 6f6c6277dc64b07c0659e57f5662659073ba228cdd92c17215f6095961f3bee7 -address /run/containerd/containerd.sock
65535 3015 0.0 0.0 972 4 ? Ss 05:28 0:00 \_ /pause
root 3355 0.0 0.2 1237964 11488 ? Ssl 05:28 0:00 \_ /app/aws-vpc-cni
root 3370 0.0 1.6 1300896 65228 ? Sl 05:28 0:00 | \_ ./aws-k8s-agent
root 3490 0.0 1.3 1754792 52004 ? Ssl 05:28 0:00 \_ /controller --enable-ipv6=false --enable-network-policy=false --enable-cloudwatch-logs=false --enable-policy-event-logs=false --log-file=/var/log/aws-routed-eni/network-policy-agent.log --metrics-bind-addr=:8162 --health-probe-bind-addr=:8163 --conntrack-cache-cleanup-period=300
root 2975 0.0 0.3 1238280 13452 ? Sl 05:28 0:00 /usr/bin/containerd-shim-runc-v2 -namespace k8s.io -id 821ea44197613de30a7270bc6c62779d8f2270f3e5d6310d154abd4059af7727 -address /run/containerd/containerd.sock
65535 3023 0.0 0.0 972 4 ? Ss 05:28 0:00 \_ /pause
root 3109 0.0 1.3 1290936 54940 ? Ssl 05:28 0:00 \_ kube-proxy --v=2 --config=/var/lib/kube-proxy-config/config --hostname-override=ip-192-168-2-247.ap-northeast-2.compute.internal
root 3603 0.0 0.3 1238536 13104 ? Sl 05:28 0:00 /usr/bin/containerd-shim-runc-v2 -namespace k8s.io -id daf91e701a0a2e3f8a4ee00e06b1d2934ea249e336af4ac6c8eab65833a5bcf7 -address /run/containerd/containerd.sock
65535 3646 0.0 0.0 972 4 ? Ss 05:28 0:00 \_ /pause
65532 3739 0.1 1.3 1286092 52372 ? Ssl 05:28 0:00 \_ /coredns -conf /etc/coredns/Corefile
root 3640 0.0 0.3 1238280 13952 ? Sl 05:28 0:00 /usr/bin/containerd-shim-runc-v2 -namespace k8s.io -id 28d470d9078b1b3968bfcc3560c092f1d5d1f156608a90b86f00d286e1d8ecf8 -address /run/containerd/containerd.sock
65535 3675 0.0 0.0 972 4 ? Ss 05:28 0:00 \_ /pause
65532 3723 0.1 1.3 1286092 52020 ? Ssl 05:28 0:00 \_ /coredns -conf /etc/coredns/Corefile
root 3862 0.0 0.3 1238280 13712 ? Sl 05:28 0:00 /usr/bin/containerd-shim-runc-v2 -namespace k8s.io -id c0ce02949b3ac70c3e13f46aa23d54f29100bd3a437d88a7873fe9e1e8cb9353 -address /run/containerd/containerd.sock
65535 3884 0.0 0.0 972 4 ? Ss 05:28 0:00 \_ /pause
ec2-user 3967 0.3 1.4 1283328 56144 ? Ssl 05:28 0:01 \_ /metrics-server --secure-port=10250 --cert-dir=/tmp --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname --kubelet-use-node-status-port --metric-resolution=15s
## containerd 프로세스 확인
$ for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i ps axf | grep /usr/bin/containerd; echo; done
$ for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i ls /etc/kubernetes/manifests/; echo; done
$ for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i ls /etc/kubernetes/kubelet/; echo; done
## kubelet 관련 설정을 확인할 수 있ㄷ고, coredns의 IP도 포함되어 있다.
$ for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i cat /etc/kubernetes/kubelet/kubelet-config.json | jq; echo; done
{
"kind": "KubeletConfiguration",
"apiVersion": "kubelet.config.k8s.io/v1beta1",
"address": "0.0.0.0",
"authentication": {
"anonymous": {
"enabled": false
},
"webhook": {
"cacheTTL": "2m0s",
"enabled": true
},
"x509": {
"clientCAFile": "/etc/kubernetes/pki/ca.crt"
}
},
"authorization": {
"mode": "Webhook",
"webhook": {
"cacheAuthorizedTTL": "5m0s",
"cacheUnauthorizedTTL": "30s"
}
},
"clusterDomain": "cluster.local",
"hairpinMode": "hairpin-veth",
"readOnlyPort": 0,
"cgroupDriver": "systemd",
"cgroupRoot": "/",
"featureGates": {
"RotateKubeletServerCertificate": true
},
"protectKernelDefaults": true,
"serializeImagePulls": false,
"serverTLSBootstrap": true,
"tlsCipherSuites": [
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
"TLS_RSA_WITH_AES_256_GCM_SHA384",
"TLS_RSA_WITH_AES_128_GCM_SHA256"
],
"clusterDNS": [
"10.100.0.10"
],
"evictionHard": {
"memory.available": "100Mi",
"nodefs.available": "10%",
"nodefs.inodesFree": "5%"
},
"kubeReserved": {
"cpu": "70m",
"ephemeral-storage": "1Gi",
"memory": "442Mi"
},
"providerID": "aws:///ap-northeast-2a/i-053e81a385db36779",
"systemReservedCgroup": "/system",
"kubeReservedCgroup": "/runtime"
}
### 노트 스토리지 정보 확인
## worker에 연결된 디스크와 파티션 정보를 볼 수 있다.
$ for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i lsblk; echo; done
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
nvme0n1 259:0 0 30G 0 disk
├─nvme0n1p1 259:1 0 30G 0 part /
└─nvme0n1p128 259:2 0 1M 0 part
$ for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i df -hT /; echo; done
EKS owned ENI 확인
kubelet과 kube-proxy의 peer IP 확인 시 Cluster Endpoint의 IP와 동일한 것을 확인할 수 있습니다.
## TCP 연결 상태 확인
$ for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i sudo ss -tnp; echo; done
>> node 192.168.1.150 <<
ESTAB 0 0 192.168.1.150:58154 15.164.36.37:443 users:(("kubelet",pid=2899,fd=26))
ESTAB 0 0 192.168.1.150:44058 3.35.198.51:443 users:(("kube-proxy",pid=3114,fd=9))
ESTAB 0 0 [::ffff:192.168.1.150]:10250 [::ffff:192.168.1.122]:35932 users:(("kubelet",pid=2899,fd=11))
ESTAB 0 0 [::ffff:192.168.1.150]:10250 [::ffff:192.168.2.138]:60894 users:(("kubelet",pid=2899,fd=13))
>> node 192.168.2.247 <<
ESTAB 0 0 192.168.2.247:34094 15.164.36.37:443 users:(("kube-proxy",pid=3109,fd=9))
ESTAB 0 0 192.168.2.247:53436 3.35.198.51:443 users:(("kubelet",pid=2893,fd=24))
ESTAB 0 0 [::ffff:192.168.2.247]:10250 [::ffff:192.168.2.138]:55108 users:(("kubelet",pid=2893,fd=15))
ESTAB 0 0 [::ffff:192.168.2.247]:10250 [::ffff:192.168.1.122]:50386 users:(("kubelet",pid=2893,fd=12))
## cluster endpoint
$ APIDNS=$(aws eks describe-cluster --name $CLUSTER_NAME | jq -r .cluster.endpoint | cut -d '/' -f 3)
$ dig +short $APIDNS
15.164.36.37
3.35.198.51
(참고) ss와 netstat의 차이
- ss와 netstat 명령어의 차이
- ss는 직접 커널 공간에서 정보를 가져옴
- netstat은 /proc 파일시스템을 읽어서 정보를 가져옴
- 그래서 일반적으로 ss가 더 빠름
- 메모리 사용률도 ss가 효율적으로 사용
최근 리눅스 진영에서는 ss 사용을 권장하고 있으나,
여전히 레거시 시스템에서는 netstat가 많이 사용되고 있습니다.
pod 하나를 생성한 후에 peer ip를 조회 확인해보면 IP가 하나 추가되었고,
AWS 콘솔에서 확인하면 eni 소유자는 내 계정 ID eni가 연결된 인스턴스의 소유자는 aws 인 것을 확인할 수 있습니다.
## 단일 파드 생성 및 IP 확인
$ k run -it --rm netdebug --image=nicolaka/netshoot --restart-Never -- zsh
ESTAB 0 0 [::ffff:192.168.1.150]:10250 [::ffff:192.168.1.206]:47528 users:(("kubelet",pid=2899,fd=23))
$ aws ec2 describe-network-interfaces | grep "192.168.1.206"
"PrivateDnsName": "ip-192-168-1-206.ap-northeast-2.compute.internal",
"PrivateIpAddress": "192.168.1.206",
"PrivateDnsName": "ip-192-168-1-206.ap-northeast-2.compute.internal",
"PrivateIpAddress": "192.168.1.206"
## work node 에서 eni 관련 룰셋도 확인할 수 있습니다.
$ iptables -t nat -S | grep 206
-A KUBE-SEP-MWCUR6JQA32SA6AO -s 192.168.1.206/32 -m comment --comment "default/kubernetes:https" -j KUBE-MARK-MASQ
-A KUBE-SEP-MWCUR6JQA32SA6AO -p tcp -m comment --comment "default/kubernetes:https" -m tcp -j DNAT --to-destination 192.168.1.206:443
-A KUBE-SVC-NPX46M4PTMTKRN6Y -m comment --comment "default/kubernetes:https -> 192.168.1.206:443" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-MWCUR6JQA32SA6AO
'Cloud > AWS' 카테고리의 다른 글
[AWS] EKS Networkings (1) (0) | 2025.02.15 |
---|---|
[AWS] EKS 설치 및 기본 사용 (3) (0) | 2025.02.08 |
[AWS] EKS 설치 및 기본 사용 (1) (0) | 2025.02.06 |
[AWS] EKS에 대하여 (0) | 2025.02.05 |
[AWS] Terraform으로 Karpenter 설치하고 노드 증설하기 (2) | 2024.11.05 |