25๋ ๋ AWS EKS Hands-on Study ์คํฐ๋ ์ ๋ฆฌ ๋ด์ฉ์ ๋๋ค.
ARM, AMD
ARM๊ณผ AMD๋ CPU ์ํคํ ์ฒ ์ฒ๋ฆฌ ๋ฐฉ์์ด๋ค. ARM๊ณผ AMD์ ์ฐจ์ด๋ ์ํคํ ์ฒ ์ค๊ณ ์ฒ ํ์ด ๋ค๋ฅด๋ฉฐ, ์ฌ์ฉ์๊ฐ ์ด๋ค ์ฉ๋๋ก CPU๋ฅผ ์ฌ์ฉํ ์ง์ ๋ฐ๋ผ ์ ์ ํ ์ํคํ ์ฒ๋ฅผ ์ ํํ๋ ๊ฒ์ด ํ์ํ๋ค.
ARM์ RISC(Reduced Instruction Set Computing, ์ถ์ ๋ช ๋ น์ด ์งํฉ ์ปดํจํ ) ์ํคํ ์ฒ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ค๊ณ๋๋ค. ์ด ๋ฐฉ์์ ๋ช ๋ น์ด์ ์ข ๋ฅ๋ฅผ ๋จ์ํํ์ฌ CPU๊ฐ ๋ ๋น ๋ฅด๊ณ ํจ์จ์ ์ผ๋ก ์๋ํ๋๋ก ์ค๊ณ๋์๋ค. ๋ช ๋ น์ด๊ฐ ๊ฐ๋จํ๋ฉด ์คํ ์๋๊ฐ ๋นจ๋ผ์ง๊ณ ์ ๋ ฅ ์๋น๋ ์ค์ผ ์ ์๋๋ฐ ARM ๊ธฐ๋ฐ ํ๋ก์ธ์๋ ์ ์ ๋ ฅ, ๋์ ์ ๋ ฅ ํจ์จ์ฑ, ๋ฐ์ด์ด ์ ์ ํน์ฑ์ ๊ฐ๋๋ค. ์ด๋ฌํ ์ด์ ๋ก ์ค๋งํธํฐ, ํ๋ธ๋ฆฟ, ์๋ฒ ๋๋ ์์คํ , ์ ์ ๋ ฅ ์๋ฒ ๋ฑ์ ๋๋ฆฌ ์ฌ์ฉ๋๊ณ ๋ํ์ ์ผ๋ก ์ ํ์ M1, M2 ์นฉ๊ณผ ํ์ปด์ Snapdragon ํ๋ก์ธ์๊ฐ ๋ํ์ ์ธ ARM ๊ธฐ๋ฐ ์นฉ์ด๋ค.
AMD๋ CISC(Complex Instruction Set Computing, ๋ณตํฉ ๋ช ๋ น์ด ์งํฉ ์ปดํจํ ) ์ํคํ ์ฒ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๋ x86 ํ๋ก์ธ์๋ฅผ ์ค๊ณํ๋ค. CISC ๋ฐฉ์์ ๋ณต์กํ ๋ช ๋ น์ด๋ฅผ ํ ๋ฒ์ ์คํํ ์ ์์ด ๋ณด๋ค ๊ฐ๋ ฅํ ์ฐ์ฐ ๋ฅ๋ ฅ์ ์ ๊ณตํ๋ค. ํ์ง๋ง ๋ช ๋ น์ด๊ฐ ๋ณต์กํด์ง์๋ก ์ ๋ ฅ ์๋น๊ฐ ์ฆ๊ฐํ๊ณ ๋ฐ์ด์ด ๋ฐ์ํ๋ค. AMD์ CPU๋ ๊ณ ์ฑ๋ฅ ์ฐ์ฐ์ด ํ์ํ ํ๊ฒฝ์์ ๊ฐ์ ์ ๋ฐํํ๋ฉฐ, ๋ฐ์คํฌํฑ, ์๋ฒ, ๊ฒ์์ฉ PC, ๋ฐ์ดํฐ์ผํฐ ๋ฑ์ ๊ณ ์ฑ๋ฅ ์ปดํจํ ํ๊ฒฝ์์ ๋ง์ด ์ฌ์ฉ๋๋ค. ๋ํ์ ์ธ ์ ํ์ผ๋ก๋ ๋ผ์ด์ , EPYC ์๋ฒ ํ๋ก์ธ์ ๋ฑ์ด ์๋ค.
๋ ์ํคํ ์ฒ๋ ๊ฐ๊ธฐ ๋ค๋ฅธ ์ฉ๋์ ์ฅ์ ์ ๊ฐ๊ณ ์๋ค. ARM ๊ธฐ๋ฐ ์นฉ์ ์ ์ ๋ ฅ, ๊ธด ๋ฐฐํฐ๋ฆฌ ์๋ช , ๋ชจ๋ฐ์ผ ๋ฐ ์๋์ง ํจ์จ์ ์ธ ํ๊ฒฝ์์ ๊ฐ์ ์ ๋ณด์ด๋ฉฐ, AMD์ x86 ๊ธฐ๋ฐ ์นฉ์ ๊ณ ์ฑ๋ฅ ์ฐ์ฐ๊ณผ ๋ฉํฐํ์คํน์ด ํ์ํ ํ๊ฒฝ์์ ๋ ์ ํฉํ๋ค. ์ต๊ทผ์๋ ARM ๊ธฐ๋ฐ ์นฉ๋ ์ฑ๋ฅ์ ํฅ์์ํค๋ฉด์ ์๋ฒ์ ๋ฐ์คํฌํฑ ์์ฅ์ผ๋ก ํ์ฅํ๊ณ ์์ผ๋ฉฐ, ๋ฐ๋๋ก AMD๋ ์ ๋ ฅ ํจ์จ์ฑ์ ๊ฐ์ ํ๊ณ ์๋ค.
AWS graviton
AWS Graviton์ AWS๊ฐ ์์ฒด ์ค๊ณํ ARM ๊ธฐ๋ฐ์ ํ๋ก์ธ์๋ก, ๊ณ ์ฑ๋ฅ๊ณผ ์๋์ง ํจ์จ์ฑ์ ๋์์ ์ ๊ณตํ๋ค.
Graviton ํ๋ก์ธ์๋ ํด๋ผ์ฐ๋ ํ๊ฒฝ์์ ์ต์ ํ๋ ์ฑ๋ฅ๊ณผ ๋น์ฉ ํจ์จ์ฑ์ ์ ๊ณตํ๋๋ก ์ค๊ฒ๋์์ผ๋ฉฐ ์น ์ ํ๋ฆฌ์ผ์ด์ , ์ปจํ ์ด๋, ๋ง์ดํฌ๋ก์๋น์ค, ๋น ๋ฐ์ดํฐ ๋ถ์, ML ๋ฑ ๋ค์ํ ์ํฌ๋ก๋์์ ์ฐ์ํ ์ฑ๋ฅ์ ๋ฐํํ๋ค.
eksctl create nodegroup -c $CLUSTER_NAME -r ap-northeast-2 --subnet-ids "$PubSubnet1","$PubSubnet2","$PubSubnet3" \
-n ng3 -t t4g.medium -N 1 -m 1 -M 1 --node-volume-size=30 --node-labels family=graviton --dry-run > myng3.yaml
eksctl create nodegroup -f myng3.yaml
kubectl get nodes --label-columns eks.amazonaws.com/nodegroup,kubernetes.io/arch,eks.amazonaws.com/capacityType
NAME STATUS ROLES AGE VERSION NODEGROUP ARCH CAPACITYTYPE
ip-192-168-1-127.ap-northeast-2.compute.internal Ready <none> 2m24s v1.31.5-eks-5d632ec ng3 arm64 ON_DEMAND
...
kubectl describe nodes --selector family=graviton
...
System Info:
Machine ID: ec22fa7316c4486fe019bf98a12d486b
System UUID: ec22fa73-16c4-486f-e019-bf98a12d486b
Boot ID: 837ae6ee-0bb0-4615-bd23-da6bc27ecf56
Kernel Version: 5.10.233-224.894.amzn2.aarch64
OS Image: Amazon Linux 2
Operating System: linux
Architecture: arm64
Container Runtime Version: containerd://1.7.25
Kubelet Version: v1.31.5-eks-5d632ec
Kube-Proxy Version: v1.31.5-eks-5d632ec
ProviderID: aws:///ap-northeast-2a/i-008befacce404ca12
Non-terminated Pods: (4 in total)
Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits Age
--------- ---- ------------ ---------- --------------- ------------- ---
kube-system aws-node-f4kld 50m (2%) 0 (0%) 0 (0%) 0 (0%) 2m29s
kube-system ebs-csi-node-4wdqw 30m (1%) 0 (0%) 120Mi (3%) 768Mi (23%) 2m29s
kube-system efs-csi-node-kv8rj 0 (0%) 0 (0%) 0 (0%) 0 (0%) 2m29s
kube-system kube-proxy-gktwf 100m (5%) 0 (0%) 0 (0%) 0 (0%) 2m29s
Allocated resources:
(Total limits may be over 100 percent, i.e., overcommitted.)
Resource Requests Limits
-------- -------- ------
cpu 180m (9%) 0 (0%)
memory 120Mi (3%) 768Mi (23%)
ephemeral-storage 0 (0%) 0 (0%)
hugepages-1Gi 0 (0%) 0 (0%)
hugepages-2Mi 0 (0%) 0 (0%)
hugepages-32Mi 0 (0%) 0 (0%)
hugepages-64Ki 0 (0%) 0 (0%)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Starting 2m26s kube-proxy
Normal Starting 2m30s kubelet Starting kubelet.
Warning CgroupV1 2m30s kubelet Cgroup v1 support is in maintenance mode, please migrate to Cgroup v2.
Warning InvalidDiskCapacity 2m30s kubelet invalid capacity 0 on image filesystem
Normal NodeHasSufficientMemory 2m30s (x2 over 2m30s) kubelet Node ip-192-168-1-127.ap-northeast-2.compute.internal status is now: NodeHasSufficientMemory
Normal NodeHasNoDiskPressure 2m30s (x2 over 2m30s) kubelet Node ip-192-168-1-127.ap-northeast-2.compute.internal status is now: NodeHasNoDiskPressure
Normal NodeHasSufficientPID 2m30s (x2 over 2m30s) kubelet Node ip-192-168-1-127.ap-northeast-2.compute.internal status is now: NodeHasSufficientPID
Normal NodeAllocatableEnforced 2m30s kubelet Updated Node Allocatable limit across pods
Normal Synced 2m29s cloud-node-controller Node synced successfully
Normal RegisteredNode 2m27s node-controller Node ip-192-168-1-127.ap-northeast-2.compute.internal event: Registered Node ip-192-168-1-127.ap-northeast-2.compute.internal in Controller
Normal NodeReady 2m15s kubelet Node ip-192-168-1-127.ap-northeast-2.compute.internal status is now: NodeReady
aws eks update-nodegroup-config --cluster-name $CLUSTER_NAME --nodegroup-name ng3 \
--taints "addOrUpdateTaints=[{key=frontend, value=true, effect=NO_EXECUTE}]"
kubectl describe nodes --selector family=graviton | grep Taints
Taints: frontend=true:NoExecute
aws eks describe-nodegroup --cluster-name $CLUSTER_NAME --nodegroup-name ng3 | jq .nodegroup.taints[
{
"key": "frontend",
"value": "true",
"effect": "NO_EXECUTE"
}
]
๋ ธ๋์ taint ์ค์ ์ ๊ฑธ์ด์ค ํ ํ๋๋ฅผ ๋ฐฐํฌํ๋ค.
cat <<EOF | kubectl apply -f -
> apiVersion: v1
> kind: Pod
> metadata:
> name: busybox
> spec:
> terminationGracePeriodSeconds: 3
> containers:
> - name: busybox
> image: busybox
> command:
> - "/bin/sh"
> - "-c"
> - "while true; do date >> /home/pod-out.txt; cd /home; sync; sync; sleep 10; done"
> tolerations:
> - effect: NoExecute
> key: frontend
> operator: Exists
> nodeSelector:
> family: graviton
> EOF
pod/busybox created
kubectl get pod -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox 1/1 Running 0 6s 192.168.1.244 ip-192-168-1-127.ap-northeast-2.compute.internal <none> <none>
busybox๋ฅผ graviton ๋ ธ๋์ ๋์ด๋ค.
kubectl exec -it busybox -- arch
aarch64
kubectl exec -it busybox -- tail -f /home/pod-out.txt
Sat Feb 22 02:43:11 UTC 2025
Sat Feb 22 02:43:21 UTC 2025
Sat Feb 22 02:43:31 UTC 2025
Sat Feb 22 02:43:41 UTC 2025
Sat Feb 22 02:43:51 UTC 2025
Sat Feb 22 02:44:01 UTC 2025
Sat Feb 22 02:44:11 UTC 2025
busybox ํ๋๊ฐ x86์ด ์๋ ARM(Graviton)๊ธฐ๋ฐ์ ์ธ์คํด์ค์์ ์คํ๋๊ณ ์์์ ํ์ธํ ์ ์๋ค.
BottleRocket AMI
ํด๋ผ์ฐ๋ ํ๊ฒฝ์์ ์ปจํ ์ด๋๋ฅผ ์คํํ ๋ ์ผ๋ฐ์ ์ผ๋ก Amazon Linux, Ubuntu ๊ฐ์ ์ผ๋ฐ์ ์ธ ๋ฆฌ๋ ์ค ๋ฐฐํฌํ์ ์ฌ์ฉํ๋ค.
ํ์ง๋ง ์ด๋ฐ ์ด์์ฒด์ ๋ ์ปจํ ์ด๋๋ฅผ ์คํํ๋ ๊ฒ ์ธ์๋ ๋ง์ ์ฌ๋ฌ ํจํค์ง์ ์๋น์ค๊ฐ ํฌํจ๋์ด ์์ด ๋ณด์ ๊ด๋ฆฌ์ ์ ๋ฐ์ดํธ๊ฐ ๋ณต์กํ ์ ์๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด AWS์์๋ Bottlerocket์ด๋ผ๋ ์ปจํ ์ด์ ์ ์ฉ ์ด์์ฒด์ ๋ฅผ ๊ฐ๋ฐํ๋ค.
Bottlerocket์ ์ปจํ ์ด๋ ์คํ์ ํ์ํ ์ต์ํ์ ๊ตฌ์ฑ๋ง ํฌํจํ์ฌ ๊ฒฝ๋ํ๋ OS์ด๋ฉฐ ๋ณด์๊ณผ ์ฑ๋ฅ ์ต์ ํ์ ์ด์ ์ ๋ง์ถ์๋ค๊ณ ํ๋ค.
cat << EOF > ng-br.yaml
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: myeks
region: ap-northeast-2
version: "1.31"
managedNodeGroups:
- name: ng-bottlerocket
instanceType: m5.large
amiFamily: Bottlerocket
bottlerocket:
enableAdminContainer: true
settings:
motd: "Hello, eksctl!"
desiredCapacity: 1
maxSize: 1
minSize: 1
labels:
alpha.eksctl.io/cluster-name: myeks
alpha.eksctl.io/nodegroup-name: ng-bottlerocket
ami: bottlerocket
subnets:
- $PubSubnet1
- $PubSubnet2
- $PubSubnet3
tags:
alpha.eksctl.io/nodegroup-name: ng-bottlerocket
alpha.eksctl.io/nodegroup-type: managed
- name: ng-bottlerocket-ssh
instanceType: m5.large
amiFamily: Bottlerocket
desiredCapacity: 1
maxSize: 1
minSize: 1
ssh:
allow: true
publicKeyName: $SSHKEYNAME
labels:
alpha.eksctl.io/cluster-name: myeks
alpha.eksctl.io/nodegroup-name: ng-bottlerocket-ssh
ami: bottlerocket
subnets:
- $PubSubnet1
- $PubSubnet2
- $PubSubnet3
tags:
alpha.eksctl.io/nodegroup-name: ng-bottlerocket-ssh
alpha.eksctl.io/nodegroup-type: managed
EOF
eksctl create nodegroup -f ng-br.yaml
kubectl get node --label-columns=alpha.eksctl.io/nodegroup-name,ami,node.kubernetes.io/instance-type
kubectl get node --label-columns=alpha.eksctl.io/nodegroup-name,ami,node.kubernetes.io/instance-type
NAME STATUS ROLES AGE VERSION NODEGROUP-NAME AMI INSTANCE-TYPE
ip-192-168-1-13.ap-northeast-2.compute.internal Ready <none> 5d15h v1.31.5-eks-5d632ec ng1 t3.medium
ip-192-168-1-69.ap-northeast-2.compute.internal Ready <none> 2m40s v1.31.4-eks-0f56d01 ng-bottlerocket-ssh bottlerocket m5.large
ip-192-168-2-229.ap-northeast-2.compute.internal Ready <none> 5d15h v1.31.5-eks-5d632ec ng1 t3.medium
ip-192-168-2-249.ap-northeast-2.compute.internal Ready <none> 2m40s v1.31.4-eks-0f56d01 ng-bottlerocket bottlerocket m5.large
ip-192-168-3-122.ap-northeast-2.compute.internal Ready <none> 5d15h v1.31.5-eks-5d632ec ng1 t3.medium