AWS

AWS-ALL-Certification-Review

50일간의 챌린지를 끝냈다.

근래의 나는 다시금 내한계를 부수고 성장하는 과정을 거쳤다. 어느 순간부터 일하는것도 너무 쉬웠다.
공부하는건 시험이라는 부담감은 있었지만 공부가 어렵진 않았다.

50일간의 긴 시간이었다. 평균 5일에 1개의 자격증을 취득했다.

2023.12 CKAD: Certified Kubernetes Application Developer
2023.12 AWS Certified cloud practitioner
2023.12 AWS Certified Solutions Architect - Associate
2023.12 AWS Certified Developer – Associate
2023.12 AWS Certified SysOps Administrator – Associate
--------------------------------2024----------------------------------
2024.01 AWS Certified Database - Specialty
2024.01 AWS Certified Security - Specialty
2024.01 AWS Certified Advanced Networking - Specialty
2024.01 AWS Certified Solutions Architect - Professional
2024.01 AWS Certified: SAP on AWS - Specialty
2024.02 AWS Certified DevOps Engineer – Professional

시험응시료만 1,609,128원을 사용했다. 업무와 공부를 병행하는것도 어려웠다. 새벽 2시까지 매일같이 ChatGPT와 공부했다.

먼저 내가 공부한 방법을 설명하겠다. 나는 집중한 시간만 공부한 시간으로 잡았다. 자격증 평균 10시간정도의 공부시간을 가졌다. 공부시간은 스탑워치를 켜고 집중이 깨지면 스탑워치를 멈췄다. 평균 12분정도의 집중을 가질수 있었다.

그리고 공부는 보통은 이해를 하기위해 시험안내서를 읽었다. 공부의 시작과 끝은 시험안내서였다.

https://aws.amazon.com/ko/certification/certified-cloud-practitioner/

자격증 소개 페이지에 시험안내서가 있다. 이 시험안내서를 기반으로 분석한다.

여기 링크를 다보면 시험을 볼준비가 30%정도 완료 된거다. 그러면 이제 어떤 공부를 하냐?
안내서엔 도메인과 서비스가 있다.

태스크 설명 1.1: AWS 클라우드의 이점 정의.
관련 지식:

  • AWS 클라우드 가치 제안
    기술:
    • 규모의 경제에 대한 이해(예: 비용 절감)
    • 글로벌 인프라의 이점 이해(예: 배포 속도, 글로벌 도달 범위)
    • 고가용성, 탄력성 및 민첩성의 장점 이해

도메인은 다음과 같은 설명을 해주는데 그럼 이제 한줄한줄을 가지고 ChatGPT와 이야기를 하며 내가 모르는 키워드를 정리한다.

https://chat.openai.com/share/e84fb046-f996-4938-bd2d-c1526e3ee2fe
잠깐 예를들어서 질문을 한내용을 첨부한다. 내가 사용하는 프롬프트는 주로 자세하게 / 쉽게 / 키워드 추출 / 시험 내용 추천 / 등이다.

물론 나는 이미 한번 시험을 모두 본터라, 그동안 안다뤄본 서비스들을 따라가는 시간이라 좀더 수월함이 있었다.

그래도 나는 갱신의 시간을 가지면서 그동안 못다뤄본 서비스를을 만들어보거나 어떤방식으로 구성된지 확인하는 시간을 거치며 한층더 촘촘한 아키텍처구상력을 가지게 되었다.

올해의 첫 목표는 2달정도 빠르게 끝냈다. 이제 좀 쉬고 다음 목표를 향해 달려보려한다.

이글이 도움이 되면 좋겠다.
읽어줘서 감사하다.

좋은저녁 되시라!

AWS-User-Notifications-Hacking-Detection

아직 이걸 설정 안했다면 반드시 하길 바란다.

우리는 AWS를 다루면 항상 해킹의 위험에 당면한다.
미리 막는다면 너무좋은 일이겠으나, 그렇지 못한경우가 많다.

해킹을 당한다 하여도 문제들을 간단하게 캐치할수 있는 방법이 있다.

보통 AWS계정이 해킹당하면 해커의 니즈는 컴퓨팅 리소스를 사용하여 채굴을 돌리려고 한다. 이 과정에서 EC2를 만들게 되고, EC2의 생성을 모니터링 할수 있는 방법이 있다면, 조기에 해킹을 진압할수 있을 것이다.

이번에 나온AWS User Notifications 서비스가 그 니즈에 완벽하게 부합하다.

이미지 대로 생성하자, 활성화되지 않은 계정의 리전들은 서비스노티도 안되거나 서비스가 런칭되지 않아서 리전에서 제외해야한다. 초기 한국계정으로 선택되지 않은 리전이다.

케이프타운 / 홍콩 / 멜버른 / 자카르타 / 하이데라바드 / 뭄바이 / 밀라노 / 바레인 / 프랑크푸르트 / 바레인 / UAE / 취리히

[af-south-1, ap-east-1, ap-southeast-4, ap-southeast-3, ap-south-2, eu-south-1, eu-south-2, eu-central-2, me-south-1, me-central-1]

리전선택하고 이메일 넣고 생성해 주자

태그기반으로 예외할 인스턴스의 정책이 있다면 좋겠는데 그런정책은 아직없다.
하지만 간단히 활성화된 모든리전의 EC2의 상태변경 노티를 받아볼수 있다는 장점은 어마어마하다.

개인계정이라면 반드시 활성화해서 사용하길 바란다!

좋은하루 되시라!

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

다음과 같은 annotations 붙어있어야 한다.

그럼먼저 우리는 Provisioner가 자동으로 노드를 Deprovisioning 하도록 설정하자.

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}"

consolidation enabled 옵션은 Pod 의 리소스 요구조건에 따라서 Karpenter 가 알아서 노드를 스케줄링한다.

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

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도 프로비저닝 된다는 말이다.

2023-05-20T11:03:34.806Z	ERROR	controller.provisioner	Could 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]	{"commit": "d7e22b1-dirty", "pod": "default/host-spread-fbbf7c9d9-x4lfd"}

topologySpreadConstraints 옵션을 테스트하면서 느꼈는데, 여러 요인들로 잘 스케줄링하지 못한다.

두가지 조건에 의해서 pod는 모두다 스케줄링 되지 못하는데, 노드를 스케줄링하지 못해서 걸리기도 한다. 조건은 확실히 걸리긴한다.

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

다음과같이 노드가 a 3대 b 3대 c 1대 스케줄링 되면 모두 14개의 pod가 스케줄링된다. C zone때문에 두번째 조건에 걸리기 때문이다. 다양한 조건을 사용하면 이와 같이 균등하게 zone 에 스케줄링 하긴 어려운점이 있다. 적당히 조건을 걸어주면 잘 작동한다.

      - labelSelector:
          matchLabels:
            app: host-spread
        maxSkew: 2
        topologyKey: kubernetes.io/hostname
        whenUnsatisfiable: DoNotSchedule

이 조건을 삭제하면 topology.kubernetes.io/zone maxSkew 5 만 남겨서 프로비저닝 해보면 비대칭으로 az 에 node가 프로비저닝 되지만 조건에만 맞는다면 pod를 모두 생성한다.

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

AZ 별로 균등하게 node를 프로비저닝 해야하는 방법이 필요하다.

https://github.com/aws/karpenter/issues/2572

일단 테스트한 결과와 git issues 를 보면 karpenter 가 topologySpreadConstraints 에 적절히 대응되지 않는것을 느낄수 있었다. 따라서 minDomains 옵션으로 3개의 zone을 지정도 해보았으나 썩 좋은 결과는 없었다.

따라서 다이나믹하게 Node를 프로비저닝하면서 사용할수는 없을것같고, 미리 Node를 프로비저닝 하는 구성에선 될법한데, 그건 Karpenter 의 패턴은 아니라고 느꼈다.

EKS-NodeLess-07-AWS-Karpenter-CRD

이제 카펜터의 CRD를 정리하고 어떻게 사용해야 하는지 이야기를 해보려고 한다. 거의 끝에 다왔다.

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

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/

apiVersion: karpenter.k8s.aws/v1alpha1
kind: AWSNodeTemplate
metadata:
  name: default
spec:
  subnetSelector:
    karpenter.sh/discovery: "${CLUSTER_NAME}"
  securityGroupSelector:
    karpenter.sh/discovery: "${CLUSTER_NAME}"

awsnodetemplates 은 필수 요소들이 있다. 그것이 Subnet / SecurityGroup 다.
서브넷 셀렉터는 subnet-id 혹은 서브넷에 연결된 특정 태그로 동작한다.
보안그룹또한 ID혹은 특정 태그다.

awsnodetemplates은 ami / userdata ebs 등들을 컨트롤하려 원하는 노드의 OS를 선택할수도 있다.

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

환경 변수 설정이다.

클러스터 이름 / 리전 / OIDC ENDPOINT / 어카운트 넘버 / karpenter 버전이 그것이다.

Karpenter 를 설치할때는 많은 권한을 요구로 한다.

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

환경 설정과 적절한 권한이 주어져 있다면 이과정에서 에러는 나지 않는다.

IAM까지 했다면 거의 다한거다.

IAM에는 KarpenterNodeRole 을 만들고 권한부여하고 KarpenterNodeInstanceProfile 을 Role에 추가한다. 이름과도 같이 프로비저닝된 Karpenter Node가 가지게 될 Role 이다.

또 KarpenterControllerRole 은 IRSA로 Karpenter Pod에 부여될 Role이다. 그다음에 필수로 있어야하는건 서브넷과 보안그룹이다. 인스턴스가 프로비저닝 되기위한 필수 조건이 바로 이것이다.

이 실습에선 Karpenter의 기본설정을 따라가지만 이해를 돕기위해 직접 태깅을 추가한다. 만일 NodeGroup를 사용하고 있고 전환하길 원한다면 가이드에 나온 스크립트를 사용해도 좋다.

나는 이렇게 추가했다 karpenter.sh/discovery = myeks

그다음엔 보안그룹에 태그를 추가해준다

서브넷과 동일하게 했다. 실제로 사용할때에 AWSNodeTemplate 을 작성할때 사용할 태그이다.

이렇게 진행했다면 이제 Karpenter 에서 프로비저닝한 노드가 클러스터에 Join이 가능하도록 허용해줘야 한다.

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}}

mapRoles 아래에 넣는다. 변수부분 수정해서 넣어야한다.

이제 드디어 카펜터를 설치한다. 이과정에는 헬름이 필수다.

 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

settings.aws.clusterName / clusterName 이두가지 옵션은 다른옵션이다. 헷갈리지 말자.

우리는 NodeLess 를 진행중이기 때문에 여기서 Karpneter 가이드와 다르게 간다.

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"

이렇게 karpenter Fargate Profile을 생성하였다면 이제 Karpenter의 컴포넌트와 CRD를 같이 배포해줄 때다.

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

이렇게 배포하면 파게이트에 배포된 Karpenter 를 만날수 있다.

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>

Karpenter는 버전에 따라 Pod내에 Container 가 2개인 경우가 있다. 이경우엔 컨트롤러와 웹훅용도의 컨테이너가 두개가 동작한다. 일정버전 이상에서만 Fargate에 프로비저닝 된다. 그냥 v0.27.3버전 이상쓰자.

하다가 안되면 대부분 유저 문제다.

https://karpenter.sh/v0.27.3/troubleshooting/

을보자.

설치가 드디어 완료됬다. 다음은 Karpenter 의 두가지 CRD에 대한 설명을 할것이다.