Argo-Rollouts-Pod-Lifecycle

Argo Rollouts 의 쿨다운에 대한 이야기를 하려고한다. 이글은 Argo Roullouts 의 scaleDownDelaySeconds 옵션부터 preStop terminationGracePeriodSeconds 까지의 과정을 다룬다. Argo Rollouts 는 배포를 도와주는 툴로 블루그린 카나리등과 같은 부분을 도와주는 도구이다. 간략하게 동작을 설명하겠다. 블루그린이 완료된이후 RS는 축소하지 않고 30초간 대기한다. 이 30초간 대기하는 옵션이 scaleDownDelaySeconds다. 혹시나모를 롤백 상황에 대해서 기다리는 옵션인것이다. 이시간이 종료되면 이제 RS는 replicas 를 0으로 수정해서 pod 들은 축소된다. replicas 가 0으로 수정되면 pod는 일반적인 pod 의 lifecycle 를 거친다. pod 는 여러 차례 말했지만 N+1개의 컨테이너의 집합이고 컨테이너는 프로세스이므로 프로세스의 종료 과정이 그대로 pod 의 lifecycle 를 따르나 쿠버네티스는 이 프로세스를 컨트롤하는 고도화된 툴이므로 다양한 과정을 컨트롤 할수있게 만들어져 있다. ...

December 28, 2023 · 1 min · 📁 Kubernetes · 🏷️ preStop, argo rollouts, terminationGracePeriodSeconds

CKAD: Certified Kubernetes Application Developer - Review

CKAD를 예약하면서 진짜 공부를 안했다. 정말 안했다. 모든 공부시간을 다 합쳐서도 5시간이 안됐다. 첫번째 시험.. 합격일줄알았는데..떨어졌다.ㅋㅋㅋㅋ 이럴수가ㅋㅋㅋㅋㅋㅋ경악을 금치못했고 공부는 또 안했다. 시험보면서 내가 Docs 에서 원하는 기능이 어디에 있는지 찾는 과정일 뿐 이었기 때문에 그냥 잘 검색하는 방법 yaml 을 좀더 빨리 만들수있게 예제가 있는 위치만 더 찾아봤다. 바로 다시 16일에 시험을 봤고, 합격했다. 고득점일줄 알았는데 나중에 복기해보니 틀린게 좀 있었다. 먼저 Cronjob 은 이제 완전히 옵션을 다 알았다. SecurityContext는 뭐 그럭저럭.. Docker save 명령어는 생각이 안나서 man docker 해서 봤다. Readiness 는 httpget이 Docs엔 안나와있는데 나중에 찾아보니 그냥 공통 구조체더라. ...

December 20, 2023 · 1 min · 📁 Kubernetes · 🏷️ ckad

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

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

EKS-NodeLess-03-Karpenter-01-intro

NodeLess 컨셉에서 제일 중요한 역할을 맡고 있는 Karpenter 다. Karpenter 의 기본적인 아키텍처 부터 리뷰해볼까 한다. 그렇다면 그전에 Cluster Autoscaler 부터 설명해야 한다. Cluster Autoscaler 는 보통 CA라 부른다. 간략하게 플로우를 설명하겠다. Kubernetes에 새로운 Pod 가 프로비저닝 되었을때 Pod는 노드그룹에 스케줄링 된다. 노드그룹에 자원이 부족하면 CA가 트리거 된다. CA는 AWS 의 ASG에 새로운 로드를 요청한다. ASG는 새로운노드를 생성하고 노드그룹에 추가한다. 새로 스케줄링된 노드에 Pod가 생성된다. 생략된 단계가 있지만 실제로 이 단계를 모두 거쳐야 인스턴스가 EKS에 연결되고 노드그룹에 인스턴스가 노출된다. 그렇다면 단순히 ASG에서 노드를 제거해본 경험이 있는가? 있다면 알것이다. 이건 가끔 커피한잔하고 와도 제거안된 인스턴스가 있는 경우도 있다. ...

May 12, 2023 · 1 min · 📁 AWS, Kubernetes · 🏷️ EKS, nodeless, karpenter