brew install nvm
nvm install 14.17.4
nvm use v14.17.4
nvm list
##위와같이 nodejs 버전 관리는 nvm으로 하고 14버전 설치, 사용해준다.
pyenv install 2.7.18
pyenv global 2.7.18
pyenv versions
##마찬가지로 파이썬의 버전도 pyenv로 관리하고 2.7설치, 사용해준다.
brew update && brew install go
go install github.com/googlecodelabs/tools/claat@latest
##go와 claat 설치
## not required if you’re only using Go modules
export GOPATH=$HOME/go
export GOROOT=/usr/local/go
## 랜딩페이지 install
git clone https://github.com/googlecodelabs/tools
## navigate to folder
cd site/
## install dependencies
npm install
npm install -g gulp-cli
gulp serve
##localhost:8000으로 접속하면 페이지 확인
EKS Node Viewer 설치 : 노드 할당 가능 용량과 요청 request 리소스 표시, 실제 파드 리소스 사용량 X - 링크
It displays the scheduled pod resource requests vs the allocatable capacity on the node. It does not look at the actual pod resource usage.
# go 설치
yum install -y go
# EKS Node Viewer 설치 : 현재 ec2 spec에서는 **설치에 다소 시간이 소요됨** = **2분 이상**
go install github.com/awslabs/eks-node-viewer/cmd/eks-node-viewer@latest
# bin 확인 및 사용
tree ~/go/bin
**cd ~/go/bin**
**./eks-node-viewer**
3 nodes (875m/5790m) 15.1% cpu ██████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ $0.156/hour | $113.880/month
20 pods (0 pending 20 running 20 bound)
ip-192-168-3-196.ap-northeast-2.compute.internal cpu ████████░░░░░░░░░░░░░░░░░░░░░░░░░░░ 22% (7 pods) t3.medium/$0.0520 On-Demand
ip-192-168-1-91.ap-northeast-2.compute.internal cpu ████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 12% (6 pods) t3.medium/$0.0520 On-Demand
ip-192-168-2-185.ap-northeast-2.compute.internal cpu ████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 12% (7 pods) t3.medium/$0.0520 On-Demand
Press any key to quit
**명령 샘플**
# Standard usage
**./eks-node-viewer**
# Display both CPU and Memory Usage
**./eks-node-viewer --resources cpu,memory**
# Karenter nodes only
**./eks-node-viewer --node-selector "karpenter.sh/provisioner-name"**
# Display extra labels, i.e. AZ
**./eks-node-viewer --extra-labels topology.kubernetes.io/zone**
# Specify a particular AWS profile and region
AWS_PROFILE=myprofile AWS_REGION=us-west-2
**기본 옵션**
# select only Karpenter managed nodes
node-selector=karpenter.sh/provisioner-name
# display both CPU and memory
resources=cpu,memory
HPA, VPA, CA에 대한 설명 HPA - 스케일인/아웃, KEDA VPA - 스케일업/다운(사용 잘 안함) CA - 노드 확장/축소
HPA 실습 시작
# Run and expose php-apache server
curl -s -O <https://raw.githubusercontent.com/kubernetes/website/main/content/en/examples/application/php-apache.yaml>
cat php-apache.yaml | yh
**kubectl apply -f php-apache.yaml**
# 확인
kubectl exec -it deploy/php-apache -- **cat /var/www/html/index.php**
...
# 모니터링 : 터미널2개 사용
watch -d 'kubectl get hpa,pod;echo;kubectl top pod;echo;kubectl top node'
kubectl exec -it deploy/php-apache -- top
# 접속
PODIP=$(kubectl get pod -l run=php-apache -o jsonpath={.items[0].status.podIP})
curl -s $PODIP; echo
현재 노드 사용량은 위와같다.
# Create the HorizontalPodAutoscaler : requests.cpu=200m - [알고리즘](<https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#algorithm-details>)
# Since each pod requests **200 milli-cores** by kubectl run, this means an average CPU usage of **100 milli-cores**.
kubectl autoscale deployment php-apache **--cpu-percent=50** --min=1 --max=10
**kubectl describe hpa**
...
Metrics: ( current / target )
resource cpu on pods (as a percentage of request): 0% (1m) / 50%
Min replicas: 1
Max replicas: 10
Deployment pods: 1 current / 1 desired
...
# HPA 설정 확인
kubectl krew install neat
kubectl get hpa php-apache -o yaml
**kubectl get hpa php-apache -o yaml | kubectl neat | yh**
spec:
minReplicas: 1 # [4] 또는 최소 1개까지 줄어들 수도 있습니다
maxReplicas: 10 # [3] 포드를 최대 5개까지 늘립니다
**scaleTargetRef**:
apiVersion: apps/v1
kind: **Deployment**
name: **php-apache** # [1] php-apache 의 자원 사용량에서
**metrics**:
- type: **Resource**
resource:
name: **cpu**
target:
type: **Utilization**
**averageUtilization**: 50 # [2] CPU 활용률이 50% 이상인 경우
# 반복 접속 1 (파드1 IP로 접속) >> 증가 확인 후 중지
while true;do curl -s $PODIP; sleep 0.5; done
# 반복 접속 2 (서비스명 도메인으로 접속) >> 증가 확인(몇개까지 증가되는가? 그 이유는?) 후 중지 >> **중지 5분 후** 파드 갯수 감소 확인
# Run this in a separate terminal
# so that the load generation continues and you can carry on with the rest of the steps
kubectl run -i --tty load-generator --rm --image=**busybox**:1.28 --restart=Never -- /bin/sh -c "while sleep 0.01; do wget -q -O- ; done"
사용량 올라가는중
위와같이 파드가 오토스케일링된것을 확인할수있다.
이번엔 KEDA
HPA는 CPU, Memory 메트릭을 기반으로 스케일 인/아웃을 하는데 KEDA는 특정 이벤트를 기반으로 스케일여부를 결정한다.
지원 메트릭이 무지하게 많다.
KEDA with Helm : 특정 **이벤트(cron 등)**기반의 파드오토 스케일링 - ChartGrafanaCron
# KEDA 설치
cat < keda-values.yaml
metricsServer:
useHostNetwork: true
**prometheus**:
metricServer:
enabled: true
port: 9022
portName: metrics
path: /metrics
serviceMonitor:
# Enables ServiceMonitor creation for the Prometheus Operator
enabled: true
podMonitor:
# Enables PodMonitor creation for the Prometheus Operator
enabled: true
operator:
enabled: true
port: 8080
serviceMonitor:
# Enables ServiceMonitor creation for the Prometheus Operator
enabled: true
podMonitor:
# Enables PodMonitor creation for the Prometheus Operator
enabled: true
webhooks:
enabled: true
port: 8080
serviceMonitor:
# Enables ServiceMonitor creation for the Prometheus webhooks
enabled: true
EOT
kubectl create namespace **keda**
helm repo add kedacore <https://kedacore.github.io/charts>
helm install **keda** kedacore/keda --version 2.10.2 --namespace **keda -f** keda-values.yaml
# KEDA 설치 확인
kubectl **get-all** -n keda
kubectl get **all** -n keda
**kubectl get crd | grep keda**
# keda 네임스페이스에 디플로이먼트 생성
**kubectl apply -f php-apache.yaml -n keda
kubectl get pod -n keda**
# ScaledObject ****정책 생성 : cron
cat < keda-cron.yaml
apiVersion: keda.sh/v1alpha1
kind: **ScaledObject**
metadata:
name: php-apache-cron-scaled
spec:
minReplicaCount: 0
maxReplicaCount: 2
pollingInterval: 30
cooldownPeriod: 300
**scaleTargetRef**:
apiVersion: apps/v1
kind: Deployment
name: php-apache
**triggers**:
- type: **cron**
metadata:
timezone: Asia/Seoul
**start**: 00,15,30,45 * * * *
**end**: 05,20,35,50 * * * *
**desiredReplicas**: "1"
EOT
**kubectl apply -f keda-cron.yaml -n keda**
# 그라파나 대시보드 추가
# 모니터링
watch -d 'kubectl get ScaledObject,hpa,pod -n keda'
kubectl get ScaledObject -w
# 확인
kubectl get ScaledObject,hpa,pod -n keda
**kubectl get hpa -o jsonpath={.items[0].spec} -n keda | jq**
...
"metrics": [
{
"**external**": {
"metric": {
"name": "s0-cron-Asia-Seoul-**00,15,30,45**xxxx-**05,20,35,50**xxxx",
"selector": {
"matchLabels": {
"scaledobject.keda.sh/name": "php-apache-cron-scaled"
}
}
},
"**target**": {
"**averageValue**": "1",
"type": "AverageValue"
}
},
"type": "**External**"
}
# KEDA 및 deployment 등 삭제
kubectl delete -f keda-cron.yaml -n keda && kubectl delete deploy php-apache -n keda && helm uninstall keda -n keda
kubectl delete namespace keda
# 모니터링
kubectl get nodes -w
while true; do kubectl get node; echo "------------------------------" ; date ; sleep 1; done
while true; do aws ec2 describe-instances --query "Reservations[*].Instances[*].{PrivateIPAdd:PrivateIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output text ; echo "------------------------------"; date; sleep 1; done
# Deploy a Sample App
# We will deploy an sample nginx application as a ReplicaSet of 1 Pod
cat <<EoF> nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-to-scaleout
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
service: nginx
app: nginx
spec:
containers:
- image: nginx
name: nginx-to-scaleout
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 500m
memory: 512Mi
EoF
kubectl apply -f nginx.yaml
kubectl get deployment/nginx-to-scaleout
# Scale our ReplicaSet
# Let’s scale out the replicaset to 15
kubectl scale --replicas=15 deployment/nginx-to-scaleout && date
# 확인
kubectl get pods -l app=nginx -o wide --watch
kubectl -n kube-system logs -f deployment/cluster-autoscaler
# 노드 자동 증가 확인
kubectl get nodes
aws autoscaling describe-auto-scaling-groups \\
--query "AutoScalingGroups[? Tags[? (Key=='eks:cluster-name') && Value=='**myeks**']].[AutoScalingGroupName, MinSize, MaxSize,DesiredCapacity]" \\
--output table
**./eks-node-viewer**
42 pods (0 pending 42 running 42 bound)
ip-192-168-3-196.ap-northeast-2.compute.internal cpu ███████████████████████████████████ 100% (10 pods) t3.medium/$0.0520 On-Demand
ip-192-168-1-91.ap-northeast-2.compute.internal cpu ███████████████████████████████░░░░ 89% (9 pods) t3.medium/$0.0520 On-Demand
ip-192-168-2-185.ap-northeast-2.compute.internal cpu █████████████████████████████████░░ 95% (11 pods) t3.medium/$0.0520 On-Demand
ip-192-168-2-87.ap-northeast-2.compute.internal cpu █████████████████████████████░░░░░░ 84% (6 pods) t3.medium/$0.0520 On-Demand
ip-192-168-3-15.ap-northeast-2.compute.internal cpu █████████████████████████████░░░░░░ 84% (6 pods) t3.medium/$0.0520 On-Demand
# 디플로이먼트 삭제
kubectl delete -f nginx.yaml && date
# **노드 갯수 축소** : 기본은 10분 후 scale down 됨, 물론 아래 flag 로 시간 수정 가능 >> 그러니 **디플로이먼트 삭제 후 10분 기다리고 나서 보자!**
# By default, cluster autoscaler will wait 10 minutes between scale down operations,
# you can adjust this using the --scale-down-delay-after-add, --scale-down-delay-after-delete,
# and --scale-down-delay-after-failure flag.
# E.g. --scale-down-delay-after-add=5m to decrease the scale down delay to 5 minutes after a node has been added.
# 터미널1
watch -d kubectl get node
위와같이 배포를 진행하면
인스턴스가 생성된다. 즉 노드가 확장되는것이다.
이번엔 CPA
노드 수 증가에 비례하여 성능 처리가 필요한 애플리케이션(컨테이너/파드)를 수평으로 자동 확장하는 개념
파드가 요청한 자원 요구사항, 노드 선택자, 어피니티, 허용 조건, 그리고 토폴로지 분산 제약조건을 평가합니다.
파드 요구사항을 충족하는 노드를 프로비저닝합니다.
파드를 새로운 노드에 예약합니다.
더 이상 필요하지 않은 경우 노드를 제거합니다.
karpenter 실습은 새로 배포하여 실습한다.
# YAML 파일 다운로드
curl -O <https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/K8S/**karpenter-preconfig.yaml**>
# CloudFormation 스택 배포
예시) aws cloudformation deploy --template-file **karpenter-preconfig.yaml** --stack-name **myeks2** --parameter-overrides KeyName=**kp-gasida** SgIngressSshCidr=$(curl -s ipinfo.io/ip)/32 MyIamUserAccessKeyID=**AKIA5...** MyIamUserSecretAccessKey=**'CVNa2...'** ClusterBaseName=**myeks2** --region ap-northeast-2
# CloudFormation 스택 배포 완료 후 작업용 EC2 IP 출력
aws cloudformation describe-stacks --stack-name **myeks2** --query 'Stacks[*].**Outputs[0]**.OutputValue' --output text
# 작업용 EC2 SSH 접속
ssh -i **~/.ssh/kp-gasida.pem** ec2-user@$(aws cloudformation describe-stacks --stack-name **myeks2** --query 'Stacks[*].Outputs[0].OutputValue' --output text)
# IP 주소 확인 : 172.30.0.0/16 VPC 대역에서 172.30.1.0/24 대역을 사용 중
ip -br -c addr
# EKS Node Viewer 설치 : 현재 ec2 spec에서는 **설치에 다소 시간이 소요됨** = **2분 이상**
go install github.com/awslabs/eks-node-viewer/cmd/eks-node-viewer@latest
# [터미널1] bin 확인 및 사용
tree ~/go/bin
cd ~/go/bin
**./eks-node-viewer -h**
./eks-node-viewer # EKS 배포 완료 후 실행 하자
```bash
# 환경변수 정보 확인
export | egrep 'ACCOUNT|AWS_|CLUSTER' | egrep -v 'SECRET|KEY'
# 환경변수 설정
export KARPENTER_VERSION=v0.27.5
export TEMPOUT=$(mktemp)
**echo $KARPENTER_VERSION $CLUSTER_NAME $AWS_DEFAULT_REGION $AWS_ACCOUNT_ID $TEMPOUT**
# CloudFormation 스택으로 IAM Policy, Role, EC2 Instance Profile 생성 : **3분 정도 소요**
curl -fsSL https://karpenter.sh/"${KARPENTER_VERSION}"/getting-started/getting-started-with-karpenter/cloudformation.yaml > $TEMPOUT \
&& aws cloudformation deploy \
--stack-name "Karpenter-${CLUSTER_NAME}" \
--template-file "${TEMPOUT}" \
--capabilities CAPABILITY_NAMED_IAM \
--parameter-overrides "ClusterName=${CLUSTER_NAME}"
# 클러스터 생성 : myeks2 EKS 클러스터 생성 **19분 정도** 소요
**eksctl create cluster** -f - <<EOF
---
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: ${CLUSTER_NAME}
region: ${AWS_DEFAULT_REGION}
version: "1.24"
tags:
karpenter.sh/discovery: ${CLUSTER_NAME}
iam:
withOIDC: true
serviceAccounts:
- metadata:
name: karpenter
namespace: karpenter
roleName: ${CLUSTER_NAME}-karpenter
attachPolicyARNs:
- arn:aws:iam::${AWS_ACCOUNT_ID}:policy/KarpenterControllerPolicy-${CLUSTER_NAME}
roleOnly: true
iamIdentityMappings:
- arn: "arn:aws:iam::${AWS_ACCOUNT_ID}:role/KarpenterNodeRole-${CLUSTER_NAME}"
username: system:node:{{EC2PrivateDNSName}}
groups:
- system:bootstrappers
- system:nodes
managedNodeGroups:
- instanceType: m5.large
amiFamily: AmazonLinux2
name: ${CLUSTER_NAME}-ng
desiredCapacity: 2
minSize: 1
maxSize: 10
iam:
withAddonPolicies:
externalDNS: true
*## Optionally run on fargate
# fargateProfiles:
# - name: karpenter
# selectors:
# - namespace: karpenter*
EOF
**# eks 배포 확인**
eksctl get cluster
eksctl get nodegroup --cluster $CLUSTER_NAME
eksctl get **iamidentitymapping** --cluster $CLUSTER_NAME
eksctl get **iamserviceaccount** --cluster $CLUSTER_NAME
eksctl get addon --cluster $CLUSTER_NAME
# [터미널1] eks-node-viewer
cd ~/go/bin && ./eks-node-viewer
**# k8s 확인**
kubectl cluster-info
kubectl get node --label-columns=node.kubernetes.io/instance-type,eks.amazonaws.com/capacityType,topology.kubernetes.io/zone
kubectl get pod -n kube-system -owide
**kubectl describe cm -n kube-system aws-auth**
...
mapRoles:
----
- groups:
- system:bootstrappers
- system:**nodes**
**rolearn**: arn:aws:iam::911283464785:role/**KarpenterNodeRole-myeks2**
username: system:node:{{EC2PrivateDNSName}}
- groups:
- system:bootstrappers
- system:nodes
rolearn: arn:aws:iam::911283464785:role/eksctl-myeks2-nodegroup-myeks2-ng-NodeInstanceRole-1KDXF4FLKKX1B
username: system:node:{{EC2PrivateDNSName}}
...
# 카펜터 설치를 위한 환경 변수 설정 및 확인
export CLUSTER_ENDPOINT="$(aws eks describe-cluster --name ${CLUSTER_NAME} --query "cluster.endpoint" --output text)"
export KARPENTER_IAM_ROLE_ARN="arn:aws:iam::${AWS_ACCOUNT_ID}:role/${CLUSTER_NAME}-karpenter"
echo $CLUSTER_ENDPOINT $KARPENTER_IAM_ROLE_ARN
# EC2 Spot Fleet 사용을 위한 service-linked-role 생성 확인 : 만들어있는것을 확인하는 거라 아래 에러 출력이 정상!
# If the role has already been successfully created, you will see:
# An error occurred (InvalidInput) when calling the CreateServiceLinkedRole operation: Service role name AWSServiceRoleForEC2Spot has been taken in this account, please try a different suffix.
aws iam create-service-linked-role --aws-service-name spot.amazonaws.com || true
# docker logout : Logout of docker to perform an unauthenticated pull against the public ECR
docker logout public.ecr.aws
# karpenter 설치
helm upgrade --install karpenter oci://public.ecr.aws/karpenter/karpenter --version ${KARPENTER_VERSION} --namespace karpenter --create-namespace \
--set serviceAccount.annotations."eks\.amazonaws\.com/role-arn"=${KARPENTER_IAM_ROLE_ARN} \
--set settings.aws.clusterName=${CLUSTER_NAME} \
--set settings.aws.defaultInstanceProfile=KarpenterNodeInstanceProfile-${CLUSTER_NAME} \
--set settings.aws.interruptionQueueName=${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 \
--wait
# 확인
kubectl get-all -n karpenter
kubectl get all -n karpenter
kubectl get cm -n karpenter karpenter-global-settings -o jsonpath={.data} | jq
kubectl get crd | grep karpenter
```
3. Keycloak은 영역에 구성된 ID 공급자 목록이 있는 로그인 페이지를 표시합니다.
4. 사용자는 버튼 또는 링크를 클릭하여 ID 공급자 중 하나를 선택합니다.
5. Keycloak은 인증을 요청하는 대상 ID 공급자에게 인증 요청을 발급하고 사용자를 ID 공급자의 로그인 페이지로 리디렉션합니다. 관리자는 이미 관리 콘솔의 ID 공급자에 대한 연결 속성 및 기타 구성 옵션을 설정했습니다.
6. 사용자가 자격 증명을 제공하거나 ID 공급자에 인증하는 데 동의합니다.
7. ID 공급자가 인증에 성공하면 사용자는 인증 응답과 함께 Keycloak으로 다시 리디렉션됩니다. 일반적으로 이 응답에는 Keycloak에서 ID 공급자의 인증을 신뢰하고 사용자 정보를 검색하는 데 사용하는 보안 토큰이 포함됩니다.
8. Keycloak은 ID 공급자의 응답이 유효한지 확인합니다. 유효한 경우, 사용자가 아직 존재하지 않는 경우 Keycloak는 사용자를 가져와서 만듭니다. 토큰에 해당 정보가 포함되어 있지 않은 경우 Keycloak는 ID 공급자에게 추가 사용자 정보를 요청할 수 있습니다. 이 동작을 ID 페더레이션이라고 합니다. 사용자가 이미 존재하는 경우, Keycloak는 ID 공급자로부터 반환받은 ID를 기존 계정과 연결하도록 사용자에게 요청할 수 있습니다. 이 동작을 계정 연결이라고 합니다. Keycloak에서는 계정 연결을 구성하고 첫 로그인 플로우에서 계정 연결을 지정할 수 있습니다. 이 단계에서 Keycloak은 사용자를 인증하고 토큰을 발급하여 서비스 공급자의 요청된 리소스에 액세스할 수 있도록 합니다. 9. 사용자가 인증하면 Keycloak은 로컬 인증 중에 이전에 발급한 토큰을 전송하여 사용자를 서비스 공급자로 리디렉션합니다. 10. 서비스 공급자는 Keycloak으로부터 토큰을 받고 보호된 리소스에 대한 액세스를 허용합니다.
이 흐름의 변형이 가능합니다. 예를 들어, 클라이언트 애플리케이션에서 ID 공급자의 목록을 표시하지 않고 특정 공급자를 요청하거나, 사용자가 ID를 페더레이션하기 전에 추가 정보를 제공하도록 Keycloak을 설정할 수 있습니다.
인증 프로세스가 끝나면 Keycloak는 토큰을 클라이언트 애플리케이션에 발급합니다. 클라이언트 애플리케이션은 외부 ID 공급자와 분리되어 있으므로 클라이언트 애플리케이션의 프로토콜이나 사용자 신원을 검증하는 방법을 볼 수 없습니다. 공급자는 Keycloak에 대해서만 알면 됩니다.