ArgoCD Fails to create a clusterrole/clusterrolebinding.

In some cases, Cluster RBAC does not work with ArgoCD. Control cluster resources with โ€œCLUSTER RESOURCE ALLOW LISTโ€. When you create a new ArgoCD project, it has no permissions by default, so it can only operate within the namespace to NOT create cluster RBAC.

October 31, 2023 ยท 1 min ยท ๐Ÿ“ Kubernetes ยท ๐Ÿท๏ธ argocd, project, RBAC

helm-sentry-install-fail

helm install sentry sentry/sentry coalesce.go:175: warning: skipped value for kafka.config: Not a table. coalesce.go:175: warning: skipped value for kafka.zookeeper.topologySpreadConstraints: Not a table. W1023 08:00:35.276931 15594 warnings.go:70] spec.template.spec.containers[0].env[39]: hides previous definition of "KAFKA_ENABLE_KRAFT" Error: INSTALLATION FAILED: failed post-install: 1 error occurred: * job failed: DeadlineExceeded ```bash job failed: DeadlineExceeded ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ์ด job์€ DB๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์˜ฌ๋ผ์™”๋Š”์ง€ ํ™•์ธํ•˜๋Š” job์ด๋‹ค. ```bash k get job NAME COMPLETIONS DURATION AGE sentry-db-check 0/1 5m23s 5m23s ```bash ์ด Job์€ ๋‹ค์Œ์„ ๊ฒ€์ฆํ•œ๋‹ค. ```bash name: sentry-db-check namespace: sentry resourceVersion: "4700657" uid: 12533bba-b35b-4b7d-9007-8c625b389a98 spec: activeDeadlineSeconds: 1000 backoffLimit: 6 completionMode: NonIndexed completions: 1 parallelism: 1 selector: matchLabels: batch.kubernetes.io/controller-uid: 12533bba-b35b-4b7d-9007-8c625b389a98 suspend: false template: metadata: creationTimestamp: null labels: app: sentry batch.kubernetes.io/controller-uid: 12533bba-b35b-4b7d-9007-8c625b389a98 batch.kubernetes.io/job-name: sentry-db-check controller-uid: 12533bba-b35b-4b7d-9007-8c625b389a98 job-name: sentry-db-check release: sentry name: sentry-db-check spec: containers: - command: - /bin/sh - -c - | echo "Checking if clickhouse is up" CLICKHOUSE_STATUS=0 while [ $CLICKHOUSE_STATUS -eq 0 ]; do CLICKHOUSE_STATUS=1 CLICKHOUSE_REPLICAS=3 i=0; while [ $i -lt $CLICKHOUSE_REPLICAS ]; do CLICKHOUSE_HOST=sentry-clickhouse-$i.sentry-clickhouse-headless if ! nc -z "$CLICKHOUSE_HOST" 9000; then CLICKHOUSE_STATUS=0 echo "$CLICKHOUSE_HOST is not available yet" fi i=$((i+1)) done if [ "$CLICKHOUSE_STATUS" -eq 0 ]; then echo "Clickhouse not ready. Sleeping for 10s before trying again" sleep 10; fi done echo "Clickhouse is up" echo "Checking if kafka is up" KAFKA_STATUS=0 while [ $KAFKA_STATUS -eq 0 ]; do KAFKA_STATUS=1 KAFKA_REPLICAS=3 i=0; while [ $i -lt $KAFKA_REPLICAS ]; do KAFKA_HOST=sentry-kafka-$i.sentry-kafka-headless if ! nc -z "$KAFKA_HOST" 9092; then KAFKA_STATUS=0 echo "$KAFKA_HOST is not available yet" fi i=$((i+1)) done if [ "$KAFKA_STATUS" -eq 0 ]; then echo "Kafka not ready. Sleeping for 10s before trying again" sleep 10; fi done echo "Kafka is up" image: subfuzion/netcat:latest imagePullPolicy: IfNotPresent name: db-check resources: limits: memory: 64Mi requests: cpu: 100m memory: 64Mi terminationMessagePath: /dev/termination-log terminationMessagePolicy: File dnsPolicy: ClusterFirst restartPolicy: Never schedulerName: default-scheduler securityContext: {} terminationGracePeriodSeconds: 30 ```bash Clickhouse / Kafka ๊ฐ€ ์‹คํ–‰๋˜์–ด์•ผ job์€ ์ •์ƒํ™” ๊ฐ€๋Šฅํ•˜๋‹ค. ์‹œ๊ฐ„์ด ์˜ค๋ž˜๊ฑธ๋ฆฌ๋Š” ์ž‘์—…์ด๋ฏ€๋กœ, hook ์˜ ์‹œ๊ฐ„์„ ๋Š˜๋ ค์ฃผ๋ฉด job์€ ๋” ๊ธด์‹œ๊ฐ„ ๋Œ€๊ธฐํ•œ๋‹ค helm ์˜ values.yaml ์—์„œ activeDeadlineSeconds๋ฅผ ๋Š˜๋ ค์ฃผ๋ฉด ๋œ๋‹ค. ```bash hooks: enabled: true removeOnSuccess: true activeDeadlineSeconds: 1000 ```bash ์ด ์‹œ๊ฐ„์„ ๋Š˜๋ ค๋„ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธด๋‹ค๋ฉด ๋ณดํ†ต kafka์˜ pv๊ฐ€ ์ƒ์„ฑ๋˜์ง€ ์•Š๋Š”๊ฒฝ์šฐ๋‹ค. CSI ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ํ™•์ธํ•ด ๋ณด๋Š”๊ฒŒ ์ข‹๋‹ค.

October 23, 2023 ยท 2 min ยท ๐Ÿ“ Kubernetes

๊ฐœ๋ฐœ์ž ๋‘๋ช…์ด ์ž๋ฆฌ๋ฅผ ๋ฐ”๊พธ๋Š”๋ฐ ํ•„์š”ํ•œ ์˜์ž ๊ฐฏ์ˆ˜๋Š”?

๋ณดํ†ต ๊ฐœ๋ฐœ์ž์˜ ์ž๋ฆฌ์ด๋™์€ ์„ธ๊ฐœ์˜ ์˜์ž๊ฐ€ ์žˆ์–ด์•ผ์ง€๋งŒ ๊ฐ€๋Šฅํ•˜๋‹ค. ๋นˆ์˜์ž = ๊ฐœ๋ฐœ์ž1 ๊ฐœ๋ฐœ์ž1 = ๊ฐœ๋ฐœ์ž2 ๊ฐœ๋ฐœ์ž1 = ๋นˆ์˜์ž ```bash ๊ทธ๋Ÿฐ๋ฐ XOR๋ฅผ ์ด์šฉํ•˜๋ฉด ๋‘๊ฐœ์˜ ์˜์ž ๋งŒ์œผ๋กœ๋„ ์ด๋™์ด ๊ฐ€๋Šฅํ•˜๋‹ค. ```bash ๊ฐœ๋ฐœ์ž1 ^= ๊ฐœ๋ฐœ์ž2 ๊ฐœ๋ฐœ์ž2 ^= ๊ฐœ๋ฐœ์ž1 ๊ฐœ๋ฐœ์ž1 ^= ๊ฐœ๋ฐœ์ž2 ```bash ![](/images/2023/08/image-1-1024x978.png) GPT์˜ ๋‹ต๋ณ€์ด๋‹ค. ๋‚˜๋Š” ์ด๋Ÿฐ ๋ฐฉ๋ฒ•์ด ์žˆ์„๊ฑฐ๋ผ ์ƒ๊ฐ๋„ ๋ชปํ–ˆ์—ˆ๋‹ค. ๊ทธ๋Ÿฌ๋˜์ค‘ ํ˜„๋Œ€์˜ ์ปดํŒŒ์ผ๋Ÿฌ์—์„  XOR๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์ง€๋งŒ ๋ณ‘๋ ฌ์ฒ˜๋ฆฌ์—์„œ์˜ ๋ฌธ์ œ๋กœ ์„ฑ๋Šฅ์ด ๋–จ์–ด์ง„๋‹ค๋Š” ์ด์•ผ๊ธฐ๋ฅผ ๋“ค์—ˆ๋‹ค. ![](/images/2023/08/KakaoTalk_Snapshot_20230808_000456-1024x371.png) ํ•ญ์ƒ ์ž์„ธํ•œ ์„ค๋ช…๊ณผ ํ•จ๊ป˜ ๋„์›€์ฃผ์‹œ๋Š” pr0gr4m ๋‹˜. ๋А๋ ค์ง€๋Š”๊ฒŒ ๋งž๋‹ค๊ณ  ํ•˜์…”์„œ ๊ถ๊ธˆํ•ด์„œ ๋Œ๋ ค๋ดค๋‹ค. ```bash import timeit # temp ์‚ฌ์šฉ def swap_temp(): a = 5 b = 10 temp = a a = b b = temp return a, b # XOR ์‚ฌ์šฉ def swap_xor(): a = 5 b = 10 a ^= b b ^= a a ^= b return a, b # ์„ฑ๋Šฅ ํ…Œ์ŠคํŠธ temp_time = timeit.timeit("swap_temp()", setup="from __main__ import swap_temp", number=1000000) xor_time = timeit.timeit("swap_xor()", setup="from __main__ import swap_xor", number=1000000) print(f"Using temp: {temp_time} seconds") print(f"Using XOR: {xor_time} seconds") ```bash ์ฝ”๋“œ๋ฅผ ์—ฌ๋Ÿฌ๋ฒˆ ์‹คํ–‰ํ•ด ๋ดค๊ณ  ๊ฒฐ๋ก ์„ ์–ป์—ˆ๋‹ค. ```bash linus@Linusui-MacBookPro python % /opt/homebrew/bin/python3 /Users/linus/Desktop/python/test.py Using temp: 0.04701741598546505 seconds Using XOR: 0.06559245800599456 seconds linus@Linusui-MacBookPro python % /opt/homebrew/bin/python3 /Users/linus/Desktop/python/test.py Using temp: 0.04990166565403342 seconds Using XOR: 0.06569029204547405 seconds linus@Linusui-MacBookPro python % /opt/homebrew/bin/python3 /Users/linus/Desktop/python/test.py Using temp: 0.04502225015312433 seconds Using XOR: 0.0672295419499278 seconds linus@Linusui-MacBookPro python % /opt/homebrew/bin/python3 /Users/linus/Desktop/python/test.py Using temp: 0.045115040615200996 seconds Using XOR: 0.06622312497347593 seconds linus@Linusui-MacBookPro python % /opt/homebrew/bin/python3 /Users/linus/Desktop/python/test.py Using temp: 0.044884291011840105 seconds Using XOR: 0.06595424981787801 seconds linus@Linusui-MacBookPro python % /opt/homebrew/bin/python3 /Users/linus/Desktop/python/test.py Using temp: 0.04486312484368682 seconds Using XOR: 0.06613395782187581 seconds linus@Linusui-MacBookPro python % /opt/homebrew/bin/python3 /Users/linus/Desktop/python/test.py Using temp: 0.04502458404749632 seconds Using XOR: 0.06623658305034041 seconds linus@Linusui-MacBookPro python % /opt/homebrew/bin/python3 /Users/linus/Desktop/python/test.py Using temp: 0.044890208169817924 seconds Using XOR: 0.0665586250834167 seconds linus@Linusui-MacBookPro python % /opt/homebrew/bin/python3 /Users/linus/Desktop/python/test.py Using temp: 0.045562250073999166 seconds Using XOR: 0.06695195799693465 seconds linus@Linusui-MacBookPro python % /opt/homebrew/bin/python3 /Users/linus/Desktop/python/test.py Using temp: 0.04477795818820596 seconds Using XOR: 0.06620474997907877 seconds ```bash ์•„ ๊ถ๊ธˆํ•จ์ด ํ’€๋ ธ๋‹ค. ๊ฒฐ๋ก  ## **๊ฐœ๋ฐœ์ž ๋‘๋ช…์€ ์˜์ž ๋‘๊ฐœ๋กœ ์ž๋ฆฌ ์ด๋™์ด ๊ฐ€๋Šฅํ•˜์ง€๋งŒ ๋А๋ฆฌ๋‹ค.** ๋˜, ![](/images/2023/08/KakaoTalk_Snapshot_20230808_092052-1024x760.png) Pr0gr4m์˜ ์ถ”๊ฐ€ ๋‹ต๋ณ€์ด ์žˆ์—ˆ๋‹ค. ์•Œ์ˆ˜๋ก ์–ด๋ ค์šด ์ปดํŒŒ์ผ๋Ÿฌ์˜ ์„ธ๊ณ„๋‹ค.

August 8, 2023 ยท 2 min ยท ๐Ÿ“ ๊ธฐํƒ€ ยท ๐Ÿท๏ธ XOR

AWS-User-Notifications-Hacking-Detection

์•„์ง ์ด๊ฑธ ์„ค์ • ์•ˆํ–ˆ๋‹ค๋ฉด ๋ฐ˜๋“œ์‹œ ํ•˜๊ธธ ๋ฐ”๋ž€๋‹ค. ์šฐ๋ฆฌ๋Š” AWS๋ฅผ ๋‹ค๋ฃจ๋ฉด ํ•ญ์ƒ ํ•ดํ‚น์˜ ์œ„ํ—˜์— ๋‹น๋ฉดํ•œ๋‹ค. ๋ฏธ๋ฆฌ ๋ง‰๋Š”๋‹ค๋ฉด ๋„ˆ๋ฌด์ข‹์€ ์ผ์ด๊ฒ ์œผ๋‚˜, ๊ทธ๋ ‡์ง€ ๋ชปํ•œ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค. ํ•ดํ‚น์„ ๋‹นํ•œ๋‹ค ํ•˜์—ฌ๋„ ๋ฌธ์ œ๋“ค์„ ๊ฐ„๋‹จํ•˜๊ฒŒ ์บ์น˜ํ• ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค. ๋ณดํ†ต AWS๊ณ„์ •์ด ํ•ดํ‚น๋‹นํ•˜๋ฉด ํ•ด์ปค์˜ ๋‹ˆ์ฆˆ๋Š” ์ปดํ“จํŒ… ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฑ„๊ตด์„ ๋Œ๋ฆฌ๋ ค๊ณ  ํ•œ๋‹ค. ์ด ๊ณผ์ •์—์„œ EC2๋ฅผ ๋งŒ๋“ค๊ฒŒ ๋˜๊ณ , EC2์˜ ์ƒ์„ฑ์„ ๋ชจ๋‹ˆํ„ฐ๋ง ํ• ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค๋ฉด, ์กฐ๊ธฐ์— ํ•ดํ‚น์„ ์ง„์••ํ• ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค. ์ด๋ฒˆ์— ๋‚˜์˜จAWS User Notifications ์„œ๋น„์Šค๊ฐ€ ๊ทธ ๋‹ˆ์ฆˆ์— ์™„๋ฒฝํ•˜๊ฒŒ ๋ถ€ํ•ฉํ•˜๋‹ค. ์ด๋ฏธ์ง€ ๋Œ€๋กœ ์ƒ์„ฑํ•˜์ž, ํ™œ์„ฑํ™”๋˜์ง€ ์•Š์€ ๊ณ„์ •์˜ ๋ฆฌ์ „๋“ค์€ ์„œ๋น„์Šค๋…ธํ‹ฐ๋„ ์•ˆ๋˜๊ฑฐ๋‚˜ ์„œ๋น„์Šค๊ฐ€ ๋Ÿฐ์นญ๋˜์ง€ ์•Š์•„์„œ ๋ฆฌ์ „์—์„œ ์ œ์™ธํ•ด์•ผํ•œ๋‹ค. ์ดˆ๊ธฐ ํ•œ๊ตญ๊ณ„์ •์œผ๋กœ ์„ ํƒ๋˜์ง€ ์•Š์€ ๋ฆฌ์ „์ด๋‹ค. ...

May 25, 2023 ยท 1 min ยท ๐Ÿ“ AWS

EKS-NodeLess-08-AWS-Karpenter-topologySpreadConstraints

topologySpreadConstraints ์„ ์‚ฌ์šฉํ•œ Karpenter ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๊ฒ ๋‹ค. topologySpreadConstraints ํ…Œ์ŠคํŠธ๋Š” Topology Aware Hint ๋ฅผ ์˜ˆ๋น„ํ•œ ํ…Œ์ŠคํŠธ๋‹ค. https://aws.amazon.com/ko/blogs/tech/amazon-eks-reduce-cross-az-traffic-costs-with-topology-aware-hints/ ์ฐธ๊ณ ํ•  ๋ถ€๋ถ„์ด ์žˆ๋‹ค๋ฉด ์ด ๊ธ€์„ ์ฐธ๊ณ ํ•˜๊ธธ ๋ฐ”๋ž€๋‹ค. ๊ฐ„๋žตํ•˜๊ฒŒ ์„ค๋ช…ํ•˜์ž๋ฉด Kubernetes ์—์„œ Cross Zone Traffic ์˜ ๋ฌธ์ œ๋กœ ๋น„์šฉ์ด ๋ง‰๋Œ€ํ•˜๊ฒŒ ๋ฐœ์ƒํ• ์ˆ˜ ์žˆ๋‹ค. ๋˜ํ•œ Cross-AZ๋กœ ์ธํ•˜์—ฌ ์•ฝ๊ฐ„์˜ ๋ ˆ์ดํ„ด์‹œ๊ฐ€ ๋ฐœ์ƒํ• ์ˆ˜๋„ ์žˆ๊ธฐ๋•Œ๋ฌธ์— Topology Aware Hint๋Š” ์—ฌ๋Ÿฌ ๋ฌธ์ œ์ ๋“ค์„ ์ค„์—ฌ์ฃผ๋Š” ์—ญํ• ์„ ํ•œ๋‹ค. ์กฐ๊ฑด์€ ๋ช‡๊ฐ€์ง€๊ฐ€ ์žˆ๋Š”๋ฐ, Service ๋กœ ์—ฐ๊ฒฐ๋˜ AZ๊ฐ€ ์ˆ˜ํ‰์ ์œผ๋กœ ๋™์ผํ•˜๊ฒŒ ๋…ธ๋“œ๊ฐ€ ๋ฐฐํฌ๋˜์–ด์žˆ๊ณ  ์„œ๋น„์Šค์— apiVersion: v1 kind: Service metadata: name: service annotations: service.kubernetes.io/topology-aware-hints: auto ```bash ๋‹ค์Œ๊ณผ ๊ฐ™์€ annotations ๋ถ™์–ด์žˆ์–ด์•ผ ํ•œ๋‹ค. ๊ทธ๋Ÿผ๋จผ์ € ์šฐ๋ฆฌ๋Š” Provisioner๊ฐ€ ์ž๋™์œผ๋กœ ๋…ธ๋“œ๋ฅผ Deprovisioning ํ•˜๋„๋ก ์„ค์ •ํ•˜์ž. ```bash apiVersion: karpenter.sh/v1alpha5 kind: Provisioner metadata: name: default spec: consolidation: enabled: true requirements: - key: karpenter.k8s.aws/instance-category operator: In values: [ t, m, c ] providerRef: name: default --- apiVersion: karpenter.k8s.aws/v1alpha1 kind: AWSNodeTemplate metadata: name: default spec: subnetSelector: karpenter.sh/discovery: "${CLUSTER_NAME}" securityGroupSelector: karpenter.sh/discovery: "${CLUSTER_NAME}" ```bash consolidation enabled ์˜ต์…˜์€ Pod ์˜ ๋ฆฌ์†Œ์Šค ์š”๊ตฌ์กฐ๊ฑด์— ๋”ฐ๋ผ์„œ Karpenter ๊ฐ€ ์•Œ์•„์„œ ๋…ธ๋“œ๋ฅผ ์Šค์ผ€์ค„๋งํ•œ๋‹ค. ```bash apiVersion: apps/v1 kind: Deployment metadata: name: host-spread spec: replicas: 20 selector: matchLabels: app: host-spread template: metadata: labels: app: host-spread spec: containers: - image: public.ecr.aws/eks-distro/kubernetes/pause:3.2 name: host-spread resources: requests: cpu: "1" memory: 256M topologySpreadConstraints: - labelSelector: matchLabels: app: host-spread maxSkew: 2 topologyKey: kubernetes.io/hostname whenUnsatisfiable: DoNotSchedule - labelSelector: matchLabels: app: host-spread maxSkew: 5 topologyKey: topology.kubernetes.io/zone whenUnsatisfiable: DoNotSchedule ```bash topologyKey: kubernetes.io/zone maxSkew: 2๋Š” ํ•˜๋‚˜์˜ ํ˜ธ์ŠคํŠธ ์ฆ‰ ๋…ธ๋“œ๊ฐ„ ํŒŒ๋“œ์˜ ์ฐจ์ด๋Š” maxSkew: 2 ๋ฅผ ์ดˆ๊ณผํ• ์ˆ˜ ์—†๋‹ค. topologyKey: topology.kubernetes.io/zone maxSkew: 5 zone ๊ฐ„ pod์˜ ๊ฐฏ์ˆ˜๋Š” maxSkew: 5 ์ดˆ๊ณผ ํ• ์ˆ˜ ์—†์œผ๋ฏ€๋กœ ํ•˜๋‚˜์˜ zone์—์„œ๋งŒ pod๊ฐ€ ์Šค์ผ€์ค„๋ง๋œ๋‹ค๋ฉด 20๊ฐœ์˜ replicas ๋ฅผ ์š”์ฒญํ•œ๋‹ค ํ•ด๋„ 5๊ฐœ์˜ pod ๋งŒ ์Šค์ผ€์ค„๋ง ๋œ๋‹ค. AZ๋ณ„๋กœ ์ œ๊ณตํ•˜๋Š” ์œ ํ˜•์˜ ์ธ์Šคํ„ด์Šค ํŽ˜์ผ๋ฆฌ๊ฐ€ ๋‹ฌ๋ผ์„œ ํŠน์ • ์œ ํ˜•๋งŒ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ•˜๋ฉด ํ”„๋กœ๋น„์ €๋‹ ์กฐ๊ฑด์— ๊ฑธ๋ ค์„œ ์Šค์ผ€์ค„๋ง์ด ์‰ฝ์ง€ ์•Š๋‹ค. karpenter ์˜ ๊ฐ•๋ ฅํ•จ์€ ํ…Œ์ŠคํŠธ์ค‘์— ํ™•์ธํ• ์ˆ˜ ์žˆ๋Š”๋ฐ, 42s ๋งŒ์— Pod ๊ฐ€ Running ๋œ๋‹ค. 42์ดˆ์•ˆ์— Node๋„ ํ”„๋กœ๋น„์ €๋‹ ๋œ๋‹ค๋Š” ๋ง์ด๋‹ค. ```bash 2023-05-20T11:03:34.806Z\tERROR\tcontroller.provisioner\tCould not schedule pod, incompatible with provisioner "default", no instance type satisfied resources {"cpu":"1","memory":"256M","pods":"1"} and requirements karpenter.k8s.aws/instance-category In [c m t], kubernetes.io/os In [linux], kubernetes.io/arch In [amd64], karpenter.sh/provisioner-name In [default], karpenter.sh/capacity-type In [on-demand], topology.kubernetes.io/zone In [ap-northeast-2a]\t{"commit": "d7e22b1-dirty", "pod": "default/host-spread-fbbf7c9d9-x4lfd"} ```bash topologySpreadConstraints ์˜ต์…˜์„ ํ…Œ์ŠคํŠธํ•˜๋ฉด์„œ ๋А๊ผˆ๋Š”๋ฐ, ์—ฌ๋Ÿฌ ์š”์ธ๋“ค๋กœ ์ž˜ ์Šค์ผ€์ค„๋งํ•˜์ง€ ๋ชปํ•œ๋‹ค. ๋‘๊ฐ€์ง€ ์กฐ๊ฑด์— ์˜ํ•ด์„œ pod๋Š” ๋ชจ๋‘๋‹ค ์Šค์ผ€์ค„๋ง ๋˜์ง€ ๋ชปํ•˜๋Š”๋ฐ, ๋…ธ๋“œ๋ฅผ ์Šค์ผ€์ค„๋งํ•˜์ง€ ๋ชปํ•ด์„œ ๊ฑธ๋ฆฌ๊ธฐ๋„ ํ•œ๋‹ค. ์กฐ๊ฑด์€ ํ™•์‹คํžˆ ๊ฑธ๋ฆฌ๊ธดํ•œ๋‹ค. ```bash k get node --show-labels | grep -v fargate | awk -F"topology.kubernetes.io/" '{print $3}' | sort zone=ap-northeast-2a zone=ap-northeast-2a zone=ap-northeast-2a zone=ap-northeast-2b zone=ap-northeast-2b zone=ap-northeast-2b zone=ap-northeast-2c ```bash ๋‹ค์Œ๊ณผ๊ฐ™์ด ๋…ธ๋“œ๊ฐ€ a 3๋Œ€ b 3๋Œ€ c 1๋Œ€ ์Šค์ผ€์ค„๋ง ๋˜๋ฉด ๋ชจ๋‘ 14๊ฐœ์˜ pod๊ฐ€ ์Šค์ผ€์ค„๋ง๋œ๋‹ค. C zone๋•Œ๋ฌธ์— ๋‘๋ฒˆ์งธ ์กฐ๊ฑด์— ๊ฑธ๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋‹ค์–‘ํ•œ ์กฐ๊ฑด์„ ์‚ฌ์šฉํ•˜๋ฉด ์ด์™€ ๊ฐ™์ด ๊ท ๋“ฑํ•˜๊ฒŒ zone ์— ์Šค์ผ€์ค„๋ง ํ•˜๊ธด ์–ด๋ ค์šด์ ์ด ์žˆ๋‹ค. ์ ๋‹นํžˆ ์กฐ๊ฑด์„ ๊ฑธ์–ด์ฃผ๋ฉด ์ž˜ ์ž‘๋™ํ•œ๋‹ค. ```bash - labelSelector: matchLabels: app: host-spread maxSkew: 2 topologyKey: kubernetes.io/hostname whenUnsatisfiable: DoNotSchedule ```bash ์ด ์กฐ๊ฑด์„ ์‚ญ์ œํ•˜๋ฉด topology.kubernetes.io/zone maxSkew 5 ๋งŒ ๋‚จ๊ฒจ์„œ ํ”„๋กœ๋น„์ €๋‹ ํ•ด๋ณด๋ฉด ๋น„๋Œ€์นญ์œผ๋กœ az ์— node๊ฐ€ ํ”„๋กœ๋น„์ €๋‹ ๋˜์ง€๋งŒ ์กฐ๊ฑด์—๋งŒ ๋งž๋Š”๋‹ค๋ฉด pod๋ฅผ ๋ชจ๋‘ ์ƒ์„ฑํ•œ๋‹ค. ```bash k get pod NAME READY STATUS RESTARTS AGE host-spread-dd5f6c569-49ps7 1/1 Running 0 115s host-spread-dd5f6c569-8772p 1/1 Running 0 115s host-spread-dd5f6c569-9q2hn 1/1 Running 0 115s host-spread-dd5f6c569-b68k2 1/1 Running 0 115s host-spread-dd5f6c569-bfhv5 1/1 Running 0 115s host-spread-dd5f6c569-bqqz2 1/1 Running 0 116s host-spread-dd5f6c569-bsp8m 1/1 Running 0 115s host-spread-dd5f6c569-dh8wx 1/1 Running 0 115s host-spread-dd5f6c569-ffjdg 1/1 Running 0 115s host-spread-dd5f6c569-jghmr 1/1 Running 0 115s host-spread-dd5f6c569-jhbxg 1/1 Running 0 116s host-spread-dd5f6c569-kf69q 1/1 Running 0 115s host-spread-dd5f6c569-ksktv 1/1 Running 0 115s host-spread-dd5f6c569-lbqmv 1/1 Running 0 115s host-spread-dd5f6c569-mbf2g 1/1 Running 0 116s host-spread-dd5f6c569-pd92p 1/1 Running 0 115s host-spread-dd5f6c569-pgphc 1/1 Running 0 115s host-spread-dd5f6c569-ph59g 1/1 Running 0 115s host-spread-dd5f6c569-sdp7d 1/1 Running 0 115s host-spread-dd5f6c569-tf8v9 1/1 Running 0 115s (user-linuxer@myeks:default) [root@myeks-bastion-EC2 EKS]# k get node --show-labels | grep -v fargate | awk -F"topology.kubernetes.io/" '{print $3}' | sort zone=ap-northeast-2a zone=ap-northeast-2a zone=ap-northeast-2a zone=ap-northeast-2b zone=ap-northeast-2b zone=ap-northeast-2c ```bash AZ ๋ณ„๋กœ ๊ท ๋“ฑํ•˜๊ฒŒ node๋ฅผ ํ”„๋กœ๋น„์ €๋‹ ํ•ด์•ผํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ•˜๋‹ค. <https://github.com/aws/karpenter/issues/2572> ์ผ๋‹จ ํ…Œ์ŠคํŠธํ•œ ๊ฒฐ๊ณผ์™€ git issues ๋ฅผ ๋ณด๋ฉด karpenter ๊ฐ€ topologySpreadConstraints ์— ์ ์ ˆํžˆ ๋Œ€์‘๋˜์ง€ ์•Š๋Š”๊ฒƒ์„ ๋А๋‚„์ˆ˜ ์žˆ์—ˆ๋‹ค. ๋”ฐ๋ผ์„œ minDomains ์˜ต์…˜์œผ๋กœ 3๊ฐœ์˜ zone์„ ์ง€์ •๋„ ํ•ด๋ณด์•˜์œผ๋‚˜ ์ฉ ์ข‹์€ ๊ฒฐ๊ณผ๋Š” ์—†์—ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋‹ค์ด๋‚˜๋ฏนํ•˜๊ฒŒ Node๋ฅผ ํ”„๋กœ๋น„์ €๋‹ํ•˜๋ฉด์„œ ์‚ฌ์šฉํ• ์ˆ˜๋Š” ์—†์„๊ฒƒ๊ฐ™๊ณ , ๋ฏธ๋ฆฌ Node๋ฅผ ํ”„๋กœ๋น„์ €๋‹ ํ•˜๋Š” ๊ตฌ์„ฑ์—์„  ๋ ๋ฒ•ํ•œ๋ฐ, ๊ทธ๊ฑด Karpenter ์˜ ํŒจํ„ด์€ ์•„๋‹ˆ๋ผ๊ณ  ๋А๊ผˆ๋‹ค.

May 20, 2023 ยท 3 min ยท ๐Ÿ“ AWS, Kubernetes ยท ๐Ÿท๏ธ EKS, karpenter, topologySpreadConstraints

EKS-NodeLess-07-AWS-Karpenter-CRD

์ด์ œ ์นดํŽœํ„ฐ์˜ CRD๋ฅผ ์ •๋ฆฌํ•˜๊ณ  ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š”์ง€ ์ด์•ผ๊ธฐ๋ฅผ ํ•ด๋ณด๋ ค๊ณ  ํ•œ๋‹ค. ๊ฑฐ์˜ ๋์— ๋‹ค์™”๋‹ค. https://linuxer.name/2023/05/eks-nodeless-05-aws-karpenter-component/ Karpenter Component ๋ฅผ ์„ค๋ช…ํ• ๋•Œ CRD๋ฅผ ์„ค๋ช…ํ–ˆ์—ˆ๋‹ค. ๋‹ค์‹œ ์ด์•ผ๊ธฐ ํ•˜์ž๋ฉด provisioners.karpenter.sh - provisioners - / awsnodetemplates.karpenter.k8s.aws -awsnodetemplates - ๋‘๊ฐ€์ง€๋ฅผ ์…‹ํŒ…ํ•ด์•ผ ํ•œ๋‹ค. ๋จผ์ € provisioners ๋ฅผ ์ด์•ผ๊ธฐ ํ•ด๋ณผ๊นŒ ํ•œ๋‹ค. apiVersion: karpenter.sh/v1alpha5 kind: Provisioner metadata: name: default spec: requirements: - key: karpenter.k8s.aws/instance-category operator: In values: [c, m, r] - key: karpenter.k8s.aws/instance-generation operator: Gt values: ["2"] providerRef: name: default ```bash <https://karpenter.sh/v0.27.3/concepts/provisioners/> <https://github.com/aws/karpenter/tree/main/examples> **`provisioners`** ์˜ ์‚ฌ์šฉ์€ ์ด ๋‘๊ฐ€์ง€ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ•˜๋ฉด ๋Œ€๋ถ€๋ถ„ ํ• ์ˆ˜์žˆ๋Š”๋ฐ, ๊ฐ„๋‹จํ•˜๊ฒŒ **`provisioners`**๋ฅผ ์„ค๋ช…ํ•˜์ž๋ฉด ๋…ธ๋“œ๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ ์กฐ๊ฑด์„ ์ •์˜ํ•˜๋Š”๊ฑฐ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์ž๋ฉด ์ธ์Šคํ„ด์Šค ํŽ˜๋ฐ€๋ฆฌ / ์ธ์Šคํ„ด์Šค CPU ๊ฐฏ์ˆ˜ / ํ•˜์ดํผ๋ฐ”์ด์ € ์œ ํ˜• / AZ / kubeletConfiguration ๋“ฑ์„ ์„ค์ •ํ• ์ˆ˜ ์žˆ๋‹ค. ํ”„๋กœ๋น„์ €๋„ˆ๋Š” ๋…ธ๋“œ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋˜๋Š” CRD๋‹ค <https://karpenter.sh/v0.27.5/concepts/node-templates/> ```bash apiVersion: karpenter.k8s.aws/v1alpha1 kind: AWSNodeTemplate metadata: name: default spec: subnetSelector: karpenter.sh/discovery: "${CLUSTER_NAME}" securityGroupSelector: karpenter.sh/discovery: "${CLUSTER_NAME}" ```bash **`awsnodetemplates`** ์€ ํ•„์ˆ˜ ์š”์†Œ๋“ค์ด ์žˆ๋‹ค. ๊ทธ๊ฒƒ์ด Subnet / SecurityGroup ๋‹ค. ์„œ๋ธŒ๋„ท ์…€๋ ‰ํ„ฐ๋Š” subnet-id ํ˜น์€ ์„œ๋ธŒ๋„ท์— ์—ฐ๊ฒฐ๋œ ํŠน์ • ํƒœ๊ทธ๋กœ ๋™์ž‘ํ•œ๋‹ค. ๋ณด์•ˆ๊ทธ๋ฃน๋˜ํ•œ IDํ˜น์€ ํŠน์ • ํƒœ๊ทธ๋‹ค. **`awsnodetemplates`**์€ ami / userdata ebs ๋“ฑ๋“ค์„ ์ปจํŠธ๋กคํ•˜๋ ค ์›ํ•˜๋Š” ๋…ธ๋“œ์˜ OS๋ฅผ ์„ ํƒํ• ์ˆ˜๋„ ์žˆ๋‹ค.

May 20, 2023 ยท 1 min ยท ๐Ÿ“ AWS, Kubernetes

EKS-NodeLess-06-AWS-Karpenter-Install

์ด๋ฒˆ ํฌ์ŠคํŒ…์€ Karpenter ์„ค์น˜๋‹ค. ์„ค์น˜ํ•˜๋‹ค ๋ง‰ํžˆ๋ฉด ๊ฐ€์ด๋“œ๋ฅผ ๋ณด์ž. https://karpenter.sh/v0.27.3/getting-started/migrating-from-cas/ karpenter ๋ฅผ ์„ค์น˜ํ•˜๊ธฐ ์ „์— ๋จผ์ € ์…‹ํŒ…ํ•ด์•ผ ํ• ๊ฒƒ๋“ค์ด ์žˆ๋‹ค. CLUSTER_NAME=myeks # your clouster name AWS_PARTITION="aws" # aws or aws-gov or aws-cn AWS_REGION="$(aws configure list | grep region | tr -s " " | cut -d" " -f3)" OIDC_ENDPOINT="$(aws eks describe-cluster --name ${CLUSTER_NAME} \\ --query "cluster.identity.oidc.issuer" --output text)" AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query 'Account' \\ --output text) export KARPENTER_VERSION=v0.27.3 # latast version ```bash ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์„ค์ •์ด๋‹ค. ํด๋Ÿฌ์Šคํ„ฐ ์ด๋ฆ„ / ๋ฆฌ์ „ / OIDC ENDPOINT / ์–ด์นด์šดํŠธ ๋„˜๋ฒ„ / karpenter ๋ฒ„์ „์ด ๊ทธ๊ฒƒ์ด๋‹ค. Karpenter ๋ฅผ ์„ค์น˜ํ• ๋•Œ๋Š” ๋งŽ์€ ๊ถŒํ•œ์„ ์š”๊ตฌ๋กœ ํ•œ๋‹ค. ```bash echo '{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "ec2.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }' > node-trust-policy.json aws iam create-role --role-name "KarpenterNodeRole-${CLUSTER_NAME}" \\ --assume-role-policy-document file://node-trust-policy.json aws iam attach-role-policy --role-name "KarpenterNodeRole-${CLUSTER_NAME}" \\ --policy-arn arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy aws iam attach-role-policy --role-name "KarpenterNodeRole-${CLUSTER_NAME}" \\ --policy-arn arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy aws iam attach-role-policy --role-name "KarpenterNodeRole-${CLUSTER_NAME}" \\ --policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly aws iam attach-role-policy --role-name "KarpenterNodeRole-${CLUSTER_NAME}" \\ --policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore aws iam create-instance-profile \\ --instance-profile-name "KarpenterNodeInstanceProfile-${CLUSTER_NAME}" aws iam add-role-to-instance-profile \\ --instance-profile-name "KarpenterNodeInstanceProfile-${CLUSTER_NAME}" \\ --role-name "KarpenterNodeRole-${CLUSTER_NAME}" cat << EOF > controller-trust-policy.json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::${AWS_ACCOUNT_ID}:oidc-provider/${OIDC_ENDPOINT#*//}" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "${OIDC_ENDPOINT#*//}:aud": "sts.amazonaws.com", "${OIDC_ENDPOINT#*//}:sub": "system:serviceaccount:karpenter:karpenter" } } } ] } EOF aws iam create-role --role-name KarpenterControllerRole-${CLUSTER_NAME} \\ --assume-role-policy-document file://controller-trust-policy.json cat << EOF > controller-policy.json { "Statement": [ { "Action": [ "ssm:GetParameter", "ec2:DescribeImages", "ec2:RunInstances", "ec2:DescribeSubnets", "ec2:DescribeSecurityGroups", "ec2:DescribeLaunchTemplates", "ec2:DescribeInstances", "ec2:DescribeInstanceTypes", "ec2:DescribeInstanceTypeOfferings", "ec2:DescribeAvailabilityZones", "ec2:DeleteLaunchTemplate", "ec2:CreateTags", "ec2:CreateLaunchTemplate", "ec2:CreateFleet", "ec2:DescribeSpotPriceHistory", "pricing:GetProducts" ], "Effect": "Allow", "Resource": "*", "Sid": "Karpenter" }, { "Action": "ec2:TerminateInstances", "Condition": { "StringLike": { "ec2:ResourceTag/karpenter.sh/provisioner-name": "*" } }, "Effect": "Allow", "Resource": "*", "Sid": "ConditionalEC2Termination" }, { "Effect": "Allow", "Action": "iam:PassRole", "Resource": "arn:${AWS_PARTITION}:iam::${AWS_ACCOUNT_ID}:role/KarpenterNodeRole-${CLUSTER_NAME}", "Sid": "PassNodeIAMRole" }, { "Effect": "Allow", "Action": "eks:DescribeCluster", "Resource": "arn:${AWS_PARTITION}:eks:${AWS_REGION}:${AWS_ACCOUNT_ID}:cluster/${CLUSTER_NAME}", "Sid": "EKSClusterEndpointLookup" } ], "Version": "2012-10-17" } EOF aws iam put-role-policy --role-name KarpenterControllerRole-${CLUSTER_NAME} \\ --policy-name KarpenterControllerPolicy-${CLUSTER_NAME} \\ --policy-document file://controller-policy.json ```bash ํ™˜๊ฒฝ ์„ค์ •๊ณผ ์ ์ ˆํ•œ ๊ถŒํ•œ์ด ์ฃผ์–ด์ ธ ์žˆ๋‹ค๋ฉด ์ด๊ณผ์ •์—์„œ ์—๋Ÿฌ๋Š” ๋‚˜์ง€ ์•Š๋Š”๋‹ค. IAM๊นŒ์ง€ ํ–ˆ๋‹ค๋ฉด ๊ฑฐ์˜ ๋‹คํ•œ๊ฑฐ๋‹ค. IAM์—๋Š” KarpenterNodeRole ์„ ๋งŒ๋“ค๊ณ  ๊ถŒํ•œ๋ถ€์—ฌํ•˜๊ณ  KarpenterNodeInstanceProfile ์„ Role์— ์ถ”๊ฐ€ํ•œ๋‹ค. ์ด๋ฆ„๊ณผ๋„ ๊ฐ™์ด ํ”„๋กœ๋น„์ €๋‹๋œ Karpenter Node๊ฐ€ ๊ฐ€์ง€๊ฒŒ ๋  Role ์ด๋‹ค. ๋˜ KarpenterControllerRole ์€ IRSA๋กœ Karpenter Pod์— ๋ถ€์—ฌ๋  Role์ด๋‹ค. ๊ทธ๋‹ค์Œ์— ํ•„์ˆ˜๋กœ ์žˆ์–ด์•ผํ•˜๋Š”๊ฑด ์„œ๋ธŒ๋„ท๊ณผ ๋ณด์•ˆ๊ทธ๋ฃน์ด๋‹ค. ์ธ์Šคํ„ด์Šค๊ฐ€ ํ”„๋กœ๋น„์ €๋‹ ๋˜๊ธฐ์œ„ํ•œ ํ•„์ˆ˜ ์กฐ๊ฑด์ด ๋ฐ”๋กœ ์ด๊ฒƒ์ด๋‹ค. ์ด ์‹ค์Šต์—์„  Karpenter์˜ ๊ธฐ๋ณธ์„ค์ •์„ ๋”ฐ๋ผ๊ฐ€์ง€๋งŒ ์ดํ•ด๋ฅผ ๋•๊ธฐ์œ„ํ•ด ์ง์ ‘ ํƒœ๊น…์„ ์ถ”๊ฐ€ํ•œ๋‹ค. ๋งŒ์ผ NodeGroup๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๊ณ  ์ „ํ™˜ํ•˜๊ธธ ์›ํ•œ๋‹ค๋ฉด ๊ฐ€์ด๋“œ์— ๋‚˜์˜จ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ฌ์šฉํ•ด๋„ ์ข‹๋‹ค. ![](/images/2023/05/image-4.png) ๋‚˜๋Š” ์ด๋ ‡๊ฒŒ ์ถ”๊ฐ€ํ–ˆ๋‹ค **karpenter.sh/discovery = myeks** ๋‹ค ๊ทธ๋‹ค์Œ์—” ๋ณด์•ˆ๊ทธ๋ฃน์— ํƒœ๊ทธ๋ฅผ ์ถ”๊ฐ€ํ•ด์ค€๋‹ค ![](/images/2023/05/image-5.png) ์„œ๋ธŒ๋„ท๊ณผ ๋™์ผํ•˜๊ฒŒ ํ–ˆ๋‹ค. ์‹ค์ œ๋กœ ์‚ฌ์šฉํ• ๋•Œ์— AWSNodeTemplate ์„ ์ž‘์„ฑํ• ๋•Œ ์‚ฌ์šฉํ•  ํƒœ๊ทธ์ด๋‹ค. ์ด๋ ‡๊ฒŒ ์ง„ํ–‰ํ–ˆ๋‹ค๋ฉด ์ด์ œ Karpenter ์—์„œ ํ”„๋กœ๋น„์ €๋‹ํ•œ ๋…ธ๋“œ๊ฐ€ ํด๋Ÿฌ์Šคํ„ฐ์— Join์ด ๊ฐ€๋Šฅํ•˜๋„๋ก ํ—ˆ์šฉํ•ด์ค˜์•ผ ํ•œ๋‹ค. ```bash kubectl edit configmap aws-auth -n kube-system apiVersion: v1 data: mapRoles: | - groups: - system:bootstrappers - system:nodes rolearn: arn:aws:iam::${AWS_ACCOUNT_ID}:role/KarpenterNodeRole-${CLUSTER_NAME} username: system:node:{{EC2PrivateDNSName}} ```bash mapRoles ์•„๋ž˜์— ๋„ฃ๋Š”๋‹ค. ๋ณ€์ˆ˜๋ถ€๋ถ„ ์ˆ˜์ •ํ•ด์„œ ๋„ฃ์–ด์•ผํ•œ๋‹ค. ์ด์ œ ๋“œ๋””์–ด ์นดํŽœํ„ฐ๋ฅผ ์„ค์น˜ํ•œ๋‹ค. ์ด๊ณผ์ •์—๋Š” ํ—ฌ๋ฆ„์ด ํ•„์ˆ˜๋‹ค. ```bash helm template karpenter oci://public.ecr.aws/karpenter/karpenter \\ --version ${KARPENTER_VERSION} \\ --namespace karpenter \\ --set clusterName=${CLUSTER_NAME} \\ --set settings.aws.clusterName=${CLUSTER_NAME} \\ --set clusterEndpoint=${CLUSTER_ENDPOINT} \\ --set settings.aws.defaultInstanceProfile=KarpenterNodeInstanceProfile-${CLUSTER_NAME} \\ --set serviceAccount.annotations."eks\\.amazonaws\\.com/role-arn"="arn:${AWS_PARTITION}:iam::${AWS_ACCOUNT_ID}:role/KarpenterControllerRole-${CLUSTER_NAME}" \\ --set controller.resources.requests.cpu=1 \\ --set controller.resources.requests.memory=1Gi \\ --set controller.resources.limits.cpu=1 \\ --set controller.resources.limits.memory=1Gi > karpenter.yaml ```bash settings.aws.clusterName / clusterName ์ด๋‘๊ฐ€์ง€ ์˜ต์…˜์€ ๋‹ค๋ฅธ์˜ต์…˜์ด๋‹ค. ํ—ท๊ฐˆ๋ฆฌ์ง€ ๋ง์ž. ์šฐ๋ฆฌ๋Š” NodeLess ๋ฅผ ์ง„ํ–‰์ค‘์ด๊ธฐ ๋•Œ๋ฌธ์— ์—ฌ๊ธฐ์„œ Karpneter ๊ฐ€์ด๋“œ์™€ ๋‹ค๋ฅด๊ฒŒ ๊ฐ„๋‹ค. ```bash aws eks create-fargate-profile --fargate-profile-name karpenter --cluster-name myeks --pod-execution-role-arn arn:aws:iam::${AWS_ACCOUNT_ID}:role/AmazonEKSFargatePodExecutionRole --subnets "subnet-1" "subnet-2" "subnet-3" ```bash ์ด๋ ‡๊ฒŒ karpenter Fargate Profile์„ ์ƒ์„ฑํ•˜์˜€๋‹ค๋ฉด ์ด์ œ Karpenter์˜ ์ปดํฌ๋„ŒํŠธ์™€ CRD๋ฅผ ๊ฐ™์ด ๋ฐฐํฌํ•ด์ค„ ๋•Œ๋‹ค. ```bash kubectl create namespace karpenter kubectl create -f \\ https://raw.githubusercontent.com/aws/karpenter/${KARPENTER_VERSION}/pkg/apis/crds/karpenter.sh_provisioners.yaml kubectl create -f \\ https://raw.githubusercontent.com/aws/karpenter/${KARPENTER_VERSION}/pkg/apis/crds/karpenter.k8s.aws_awsnodetemplates.yaml kubectl apply -f karpenter.yaml ```bash ์ด๋ ‡๊ฒŒ ๋ฐฐํฌํ•˜๋ฉด ํŒŒ๊ฒŒ์ดํŠธ์— ๋ฐฐํฌ๋œ Karpenter ๋ฅผ ๋งŒ๋‚ ์ˆ˜ ์žˆ๋‹ค. ```bash k get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES karpenter-5bffc6f5d8-p2pxh 1/1 Running 0 9d 192.168.12.183 fargate-ip-192-168-12-183.ap-northeast-2.compute.internal <none> <none> karpenter-5bffc6f5d8-qgcwn 1/1 Running 0 9d 192.168.13.157 fargate-ip-192-168-13-157.ap-northeast-2.compute.internal <none> <none> ```bash Karpenter๋Š” ๋ฒ„์ „์— ๋”ฐ๋ผ Pod๋‚ด์— Container ๊ฐ€ 2๊ฐœ์ธ ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋‹ค. ์ด๊ฒฝ์šฐ์—” ์ปจํŠธ๋กค๋Ÿฌ์™€ ์›นํ›…์šฉ๋„์˜ ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ๋‘๊ฐœ๊ฐ€ ๋™์ž‘ํ•œ๋‹ค. ์ผ์ •๋ฒ„์ „ ์ด์ƒ์—์„œ๋งŒ Fargate์— ํ”„๋กœ๋น„์ €๋‹ ๋œ๋‹ค. ๊ทธ๋ƒฅ v0.27.3๋ฒ„์ „ ์ด์ƒ์“ฐ์ž. ํ•˜๋‹ค๊ฐ€ ์•ˆ๋˜๋ฉด ๋Œ€๋ถ€๋ถ„ ์œ ์ € ๋ฌธ์ œ๋‹ค. <https://karpenter.sh/v0.27.3/troubleshooting/> ์„๋ณด์ž. ์„ค์น˜๊ฐ€ ๋“œ๋””์–ด ์™„๋ฃŒ๋ฌ๋‹ค. ๋‹ค์Œ์€ Karpenter ์˜ ๋‘๊ฐ€์ง€ CRD์— ๋Œ€ํ•œ ์„ค๋ช…์„ ํ• ๊ฒƒ์ด๋‹ค.

May 17, 2023 ยท 3 min ยท ๐Ÿ“ AWS, Kubernetes ยท ๐Ÿท๏ธ EKS, nodeless, karpenter

EKS-NodeLess-05-AWS-Karpenter-component

์ด์ œ์•ผ ๋“œ๋””์–ด Karpenter๊นŒ์ง€ ์™”๋‹ค. Karpenter์˜ ๊ตฌ์„ฑ์š”์†Œ๋ถ€ํ„ฐ ์‚ดํŽด๋ณด์ž! PodDisruptionBudget: PodDisruptionBudget์€ ํด๋Ÿฌ์Šคํ„ฐ์˜ ์•ˆ์ •์„ฑ์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋œ๋‹ค. ํŠน์ • ์„œ๋น„์Šค๋ฅผ ์ค‘๋‹จํ•˜์ง€ ์•Š๊ณ  ๋™์‹œ์— ์ข…๋ฃŒํ•  ์ˆ˜ ์žˆ๋Š” Pod์˜ ์ตœ๋Œ€ ์ˆ˜๋ฅผ ์ง€์ •ํ•œ๋‹ค. ServiceAccount: Karpenter๊ฐ€ ๋™์ž‘ํ•˜๋ ค๋ฉด ํ•ด๋‹น ๊ถŒํ•œ์„ ๊ฐ€์ง„ Kubernetes์˜ ServiceAccount๊ฐ€ ํ•„์š”ํ•˜๋‹ค. ServiceAccount๋Š” Kubernetes ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ API ์ ‘๊ทผ ๊ถŒํ•œ์„ ์ œ๊ณตํ•œ๋‹ค. Secret-webhook-cert: Karpenter์˜ ์›นํ›…์— ์‚ฌ์šฉ๋˜๋Š” TLS ์ธ์ฆ์„œ๋ฅผ ์ €์žฅํ•˜๋Š” Secret์ด๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์›นํ›…์ด ์•ˆ์ „ํ•˜๊ฒŒ ํ†ต์‹ ํ•  ์ˆ˜ ์žˆ๋‹ค. ConfigMap-logging: Karpenter์˜ ๋กœ๊น… ์„ค์ •์„ ์ €์žฅํ•˜๋Š” ConfigMap์ด๋‹ค. ๋กœ๊น… ์ˆ˜์ค€, ์ถœ๋ ฅ ํ˜•์‹ ๋“ฑ์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. ...

May 15, 2023 ยท 3 min ยท ๐Ÿ“ AWS, Kubernetes ยท ๐Ÿท๏ธ EKS, nodeless, karpenter

EKS-NodeLess-04-AWS-LoadBalancer-Controller

AWS LoadBalancer Controller ๋„ Fargate์— ์˜ฌ๋ ค์•ผ ํ•œ๋‹ค. ๋น„๊ต์  ๊ฐ„๋‹จํ•œ๋ฐ, Controller Pod์— annotations ํ•œ์ค„๋งŒ ์ถ”๊ฐ€ํ•˜๋ฉด๋œ๋‹ค. ๋จผ์ € ์ถ”๊ฐ€ํ• ๋•Œ Policy ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. VPC_NAME=myeks-VPC // VPC NAME ์œผ๋กœ ๋ณ€๊ฒฝ CLUSTER_NAME=myeks REGION=ap-northeast-2 curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.4.7/docs/install/iam_policy.json aws iam create-policy \\ --policy-name AWSLoadBalancerControllerIAMPolicy \\ --policy-document file://iam_policy.json POLICY_ARN=`aws iam list-policies | grep Arn | grep AWSLoadBalancerControllerIAMPolicy | awk -F\\" '{print $4}'` VPC_ID=$(aws ec2 describe-vpcs --query 'Vpcs[?contains(Tags[?Key==`Name`].Value[], `'$VPC_NAME'`) == `true`].[VpcId]' --output text) ```bash ์ด Policy๋ฅผ ์ด์šฉํ•˜์—ฌ eksctl์—์„œ ์‚ฌ์šฉํ• ๊ฑฐ๋‹ค. POLICY_ARN์€ ์ „์ฒด Policy ์—์„œ AWSLoadBalancerControllerIAMPolicy ์˜ arn์„ ์ถ”์ถœํ•œ๋‹ค. ```bash eksctl create iamserviceaccount \\ --cluster=myeks \\ --namespace=kube-system \\ --name=aws-load-balancer-controller \\ --role-name AmazonEKSLoadBalancerControllerRole \\ --attach-policy-arn=$POLICY_ARN \\ --approve ```bash ```bash helm install aws-load-balancer-controller eks/aws-load-balancer-controller \\ -n kube-system \\ --set clusterName=$CLUSTER_NAME \\ --set serviceAccount.create=false \\ --set serviceAccount.name=aws-load-balancer-controller \\ --set region=$REGION \\ --set vpcId=$VPC_ID ```bash ๋กœ ๋ณดํ†ต AWS LoadBalancer Controller ๋ฅผ ์„ค์น˜ํ•ด ์ค˜์•ผ ํ•˜์ง€๋งŒ ์šฐ๋ฆฌ๋Š” Fargate annotations ์ถ”๊ฐ€ ํ•œ๋‹จ๊ณ„๋ฅผ ๋” ๊ฑฐ์ณ์•ผ ํ•œ๋‹ค. ```bash kubectl patch deployment aws-load-balancer-controller -n kube-system --type=json -p='[{"op": "add", "path": "/spec/template/metadata/annotations/eks.amazonaws.com~1fargate-profile", "value":"kube-system"}]' kubectl rollout restart deployment aws-load-balancer-controller -n kube-system ```bash ๋‹ค์Œ๊ณผ ๊ฐ™์ด patch ๋ฅผ ํ•˜๊ณ  rollout restart ๊นŒ์ง€ ํ•˜๋ฉด pod๊ฐ€ Fargate ๋กœ ์ƒ์„ฑ๋œ๋‹ค. ```bash k get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES aws-load-balancer-controller-76db948d9b-qzpsd 1/1 Running 0 46s 192.168.11.65 fargate-ip-192-168-11-65.ap-northeast-2.compute.internal <none> <none> aws-load-balancer-controller-76db948d9b-t26qt 1/1 Running 0 88s 192.168.11.180 fargate-ip-192-168-11-180.ap-northeast-2.compute.internal <none> <none> ```bash ์‹œ๊ฐ„๋‚ ๋•Œ๋งˆ๋‹ค Fargate ๋กœ ์ถ”๊ฐ€๋˜์–ด์•ผ ํ•˜๋Š” ์—๋“œ์˜จ๋“ค์„ Fargate ๋กœ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ž‘์„ฑํ•˜๊ฒ ๋‹ค. ์ฝ์–ด์ค˜์„œ ๊ฐ์‚ฌํ•˜๋‹ค!

May 14, 2023 ยท 2 min ยท ๐Ÿ“ AWS, Kubernetes

FinOps Certified Practitioner (FOCP) -Review

๋ฐ”์œ ์™€์ค‘์— ์š”์ฆ˜ ์ž๊ฒฉ์ฆ ์ถ”๊ฐ€๊ฐ€ ์ข€ ๋œธํ•œ๊ฑฐ ๊ฐ™์•„์„œ 2022๋…„ ๋ง์— ๋„์ „ํ–ˆ๋‹ค๊ฐ€ ๋–จ์–ด์ง„ FOCP๋ฅผ ๋‹ค์‹œ ๋„์ „ํ•˜์˜€๋‹ค. FOCP์˜ ๊ฒฝ์šฐ์—๋Š” Practitioner ์ž๊ฒฉ์ด๋ผ ๋‚œ์ด๋„๊ฐ€ ๋†’์ง€๋Š” ์•Š๋‹ค. ํ•˜์ง€๋งŒ ์ž๊ฒฉ์ฆ์—์„œ ์š”๊ตฌํ•˜๋Š” ๋ฐ”๊ฐ€ ์ผ๋ฐ˜์ ์ธ IT์˜ ์‹œ๊ฐ์ด ์•„๋‹ˆ๋‹ค. FinOps๋Š” ์žฌ๋ฌด์™€์˜ ์—ฐ๊ฒฐ๋„ ํฌํ•จํ•˜๊ณ ์žˆ์–ด์„œ ๋‹จ์ˆœํžˆ DevOps๋กœ์„œ์˜ ์‚ฌ์ผ๋กœ ๋ฟ๋งŒ์•„๋‹ˆ๋ผ ์กฐ์ง์— ๋Œ€ํ•œ ์‚ฌ์ผ๋กœ ๊นŒ์ง€ ์—†์• ๋ ค๋Š” ๋…ธ๋ ฅ์„ ํ•ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์‹œํ—˜์˜ ๋ชจ๋“ ๋‚ด์šฉ์€ FinOps Foundation ์— ๊ณต๊ฐœ๋˜์–ด์žˆ๋‹ค. ๊ทธ๋ ‡๊ธฐ์— ์–ด๋А์ •๋„ FinOps๋ฌธํ™”๋ฅผ ์ดํ•ดํ•  ์ค€๋น„๊ฐ€ ๋˜์—ˆ๋‹ค๋ฉด ์‹œํ—˜์„ ๋ณผ๋งŒํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•œ๋‹ค. ๋ฌธ์ œ๊ฐ€ ๋˜์—ˆ๋˜ ์žฅ๋ฒฝ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค. ์‹œํ—˜๊ฐ€๊ฒฉ $300 ์‹œํ—˜๊ฐ€๊ฒฉ $300 ...

May 13, 2023 ยท 1 min ยท ๐Ÿ“ FinOps ยท ๐Ÿท๏ธ FinOps, fin, Finance