실습
해당 실습을 AWS CloudShell에서 진행한다고 가정하고 작성되었습니다.
실습환경 구성
CLI 도구 설치
바이너리를 저장할 디렉토리 생성
{ mkdir ~/bin echo export PATH="$HOME/bin:$PATH" >> ~/.bashrc export PATH="$HOME/bin:$PATH" }eksctl 설치
{ curl -sL "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp sudo mv /tmp/eksctl $HOME/bin echo 'source <(eksctl completion bash)' >>~/.bashrc source <(eksctl completion bash) }helm 설치
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | HELM_INSTALL_DIR=$HOME/bin bashKrew 설치
{ curl -fsSLO "https://github.com/kubernetes-sigs/krew/releases/latest/download/krew-linux_amd64.tar.gz" mkdir krew && tar zvxf krew-linux_amd64.tar.gz -C krew ./krew/krew-linux_amd64 install krew rm krew-linux_amd64.tar.gz rm -rf krew echo export PATH="${KREW_ROOT:-$HOME/.krew}/bin:$PATH" >> ~/.bashrc export PATH="${KREW_ROOT:-$HOME/.krew}/bin:$PATH" }
EKS 클러스터 생성
ClusterConfig 생성
cat <<EOF > mycluster.yaml apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: mycluster region: $AWS_REGION version: "1.32" availabilityZones: - ${AWS_REGION}a - ${AWS_REGION}b - ${AWS_REGION}c - ${AWS_REGION}d managedNodeGroups: - name: nodegroup instanceType: t3.small minSize: 2 desiredCapacity: 2 maxSize: 5 volumeSize: 20 iam: attachPolicyARNs: - arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy - arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore addonsConfig: disableDefaultAddons: true addons: - name: vpc-cni - name: kube-proxy - name: coredns EOFEKS 클러스터 생성
eksctl create cluster --config-file=mycluster.yaml클러스터 생성 확인
kubectl get node
Authentication
kubeconfig 파일 리뷰
kubectl config viewkubeconfig에 명시된 users 확인 - https://kubernetes.io/docs/reference/access-authn-authz/authentication/#client-go-credential-plugins
kubectl config view -o=jsonpath='{.users}' | jquser에 명시된 명령어 실행
$(kubectl config view \ -o=jsonpath='{.users[0].user.exec.command} {.users[0].user.exec.args[*]}')토큰값을 환경변수로 지정 - Base64로 인코딩된 부분만 캡쳐
{ export TOKEN=$($(kubectl config view \ -o=jsonpath='{.users[0].user.exec.command} {.users[0].user.exec.args[*]}') \ | jq -r '.status.token' | grep -oP '(?<=k8s-aws-v1.).*') echo $TOKEN }Base64URL 유틸리티 설치
{ mkdir $HOME/node sudo npm install -g --prefix $HOME/node base64-url-cli echo export PATH="$HOME/node/bin:$PATH" >> ~/.bashrc export PATH="$HOME/node/bin:$PATH" }토큰값을 디코딩해서 환경변수로 지정
{ export DECODED_URL=$(base64url decode $TOKEN) echo $DECODED_URL }디코딩한 URL 호출
curl $DECODED_URLHTTP 헤더에 클러스터 이름 추가해서 디코딩한 URL 호출
{ export CLUSTER_NAME=$(kubectl get node \ -o=jsonpath='{.items[0].metadata.labels.alpha\.eksctl\.io\/cluster-name}') curl -H "x-k8s-aws-id: $CLUSTER_NAME" $DECODED_URL }현재 설정된 AWS 자격증명을 확인
aws sts get-caller-identityAPI 서버 주소를 확인하고 환경변수로 지정
{ export K8S_SERVER=$(kubectl config view \ -o=jsonpath='{.clusters[*].cluster.server}') echo $K8S_SERVER }Node 목록을 보는 API 호출
curl -k -X GET \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ $K8S_SERVER/api/v1/nodes토큰값을 환경변수로 지정
{ export TOKEN=$($(kubectl config view \ -o=jsonpath='{.users[0].user.exec.command} {.users[0].user.exec.args[*]}') \ | jq -r '.status.token') echo $TOKEN }Node 목록을 보는 API 호출
curl -k -X GET \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ $K8S_SERVER/api/v1/nodesIAM 유저를 생성하고 Access Key 발급
{ aws iam create-user --user-name john aws iam create-access-key --user-name john > key.txt cat key.txt }위에서 생성한 Access Key를 AWS CLI 자격증명 파일에 반영
{ mkdir -p ~/.aws touch ~/.aws/credentials touch ~/.aws/config cat <<EOF >> ~/.aws/credentials [john] aws_access_key_id=$(cat key.txt | jq -r '.AccessKey.AccessKeyId') aws_secret_access_key=$(cat key.txt | jq -r '.AccessKey.SecretAccessKey') EOF cat <<EOF >> ~/.aws/config [profile john] region = $AWS_REGION EOF }위에서 명시한 프로필을 통해서 AWS API 호출
aws sts get-caller-identity --profile johnkubeconfig 파일 삭제
rm -rf ~/.kube/config쿠버네티스 API 호출 시도
kubectl get pod -A새로 생성한 IAM 유저의 자격증명으로 AWS CLI를 이용해서 kubeconfig 파일 생성
aws eks update-kubeconfig --name $CLUSTER_NAME --profile johnIAM 유저에서 eks:DescribeCluster 권한 부여
aws iam put-user-policy --user-name john --policy-name eks-describe --policy-document \ '{ "Version": "2012-10-17", "Statement": [ { "Action": [ "eks:DescribeCluster" ], "Resource": "*", "Effect": "Allow" } ] }'새로 생성한 IAM 유저의 자격증명으로 AWS CLI를 이용해서 kubeconfig 파일 생성 - 정책 적용까지 시간이 걸릴수 있음
aws eks update-kubeconfig --name $CLUSTER_NAME --profile john새로 생성된 kubeconfig 파일 리뷰
kubectl config view쿠버네티스 API 호출 시도
kubectl get pod -A인증 토큰 검증
{ export AWS_PROFILE=john export TOKEN=$($(kubectl config view \ -o=jsonpath='{.users[0].user.exec.command} {.users[0].user.exec.args[*]}') \ | jq -r '.status.token' | grep -oP '(?<=k8s-aws-v1.).*') export DECODED_URL=$(base64url decode $TOKEN) curl -v -H "x-k8s-aws-id: $CLUSTER_NAME" $DECODED_URL }EKS 클러스터를 생성한 IAM 유저의 자격증명으로 AWS CLI를 이용해서 kubeconfig 파일 업데이트
{ rm -rf ~/.kube/config unset AWS_PROFILE aws eks update-kubeconfig --name $CLUSTER_NAME }
Authorization
EKS 클러스터에 설정된 Access Entry 확인
aws eks list-access-entries --cluster-name $CLUSTER_NAMEEKS 클러스터를 생성한 IAM 유저의 Access Entry 확인
aws eks describe-access-entry --cluster-name $CLUSTER_NAME \ --principal-arn $(aws sts get-caller-identity --query 'Arn' --output text)AWS Workshop Studio를 통해서 로그인할 경우에는 IAM 역할을 사용하므로 아래의 명령어 실행
aws eks describe-access-entry --cluster-name $CLUSTER_NAME \ --principal-arn $(aws sts get-caller-identity --query 'Arn' --output text |\ sed -e 's#assumed-role#role#' -e 's#/[^/]*$##' | sed -e 's#sts#iam#')EKS 클러스터를 생성한 IAM 유저에 부여된 Access Policy 확인
aws eks list-associated-access-policies --cluster-name $CLUSTER_NAME \ --principal-arn $(aws sts get-caller-identity --query 'Arn' --output text)AWS Workshop Studio를 통해서 로그인할 경우에는 IAM 역할을 사용하므로 아래의 명령어 실행
aws eks list-associated-access-policies --cluster-name $CLUSTER_NAME \ --principal-arn $(aws sts get-caller-identity --query 'Arn' --output text |\ sed -e 's#assumed-role#role#' -e 's#/[^/]*$##' | sed -e 's#sts#iam#')EKS Access Policy 목록 확인 - https://docs.aws.amazon.com/eks/latest/userguide/access-policy-permissions.html
현재 kubeconfig에 설정된 유저의 자격증명으로 수행할수 있는 API 목록 확인
kubectl auth can-i --listEKS 클러스터에 설정된 Access Entry 확인
aws eks list-access-entries --cluster-name $CLUSTER_NAMENode에 부여된 IAM 역할을 확인하고 환경변수로 지정
{ export INSTANCE_ID=$(kubectl get node -o jsonpath='{.items[0].spec.providerID}' \ | grep -oE "i-[a-z0-9]+") export INSTANCE_PROFILE=$(aws ec2 describe-instances --instance-ids $INSTANCE_ID \ --query 'Reservations[0].Instances[0].IamInstanceProfile.Arn' \ --output text | grep -oE "[a-z0-9-]+$") export INSTANCE_ROLE=$(aws iam get-instance-profile --instance-profile-name $INSTANCE_PROFILE \ --query 'InstanceProfile.Roles[0].Arn' --output text) echo $INSTANCE_ROLE }Node에 부여된 IAM 역할의 Access Entry 확인
aws eks describe-access-entry --cluster-name $CLUSTER_NAME \ --principal-arn $INSTANCE_ROLENode에 부여된 IAM 역할에 부여된 Access Policy 확인
aws eks list-associated-access-policies --cluster-name $CLUSTER_NAME \ --principal-arn $INSTANCE_ROLEKubernetes RBAC을 쉽게 확인할수 있는 플러그인 설치
kubectl krew install rbac-toolNode에 부여된 IAM 역할에 연동된 쿠버네티스 그룹에 부여된 권한 확인
kubectl rbac-tool lookup -e system:nodeseks:node-bootstrapper ClusterRole 리뷰
kubectl describe clusterrole eks:node-bootstrapper위에서 새로 생성한 IAM 유저에 EKS Access Entry 생성
{ export ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) aws eks create-access-entry --cluster-name $CLUSTER_NAME \ --principal-arn arn:aws:iam::$ACCOUNT_ID:user/john }IAM 유저에서 kube-system 네임스페이스에 대한 읽기 권한을 부여
aws eks associate-access-policy \ --cluster-name $CLUSTER_NAME \ --principal-arn arn:aws:iam::$ACCOUNT_ID:user/john \ --policy-arn arn:aws:eks::aws:cluster-access-policy/AmazonEKSAdminViewPolicy \ --access-scope type=namespace,namespaces=kube-systemIAM 유저의 자격증명으로 AWS CLI를 이용해서 kubeconfig 파일 업데이트
{ rm -rf ~/.kube/config aws eks update-kubeconfig --name $CLUSTER_NAME --profile john }클러스터에 생성된 모든 Pod 목록 확인
kubectl get pod -Akube-system 네임스페이스에 생성된 모든 Pod 목록 확인
kubectl get pod -n kube-systemkube-system 네임스페이스에 Pod 생성 시도
kubectl run nginx --image=nginx -n kube-systemIAM 역할 생성
{ cat > trust-policy.json <<EOF { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": [ "arn:aws:iam::$ACCOUNT_ID:root" ] }, "Action": "sts:AssumeRole" } ] } EOF aws iam create-role --role-name eks-admin-role \ --assume-role-policy-document file://trust-policy.json }위에서 새로 생성한 IAM 역할에 EKS Access Entry 생성
aws eks create-access-entry \ --cluster-name $CLUSTER_NAME \ --principal-arn arn:aws:iam::$ACCOUNT_ID:role/eks-admin-roleIAM 역할에 EKS 클러스터 어드민 권한 부여
aws eks associate-access-policy \ --cluster-name $CLUSTER_NAME \ --principal-arn arn:aws:iam::$ACCOUNT_ID:role/eks-admin-role \ --policy-arn arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy \ --access-scope type=clusterIAM 유저의 자격증명으로 위에서 생성한 IAM 역할 전환하는 설정 추가해서 kubeconfig 파일 업데이트
{ rm -rf ~/.kube/config aws eks update-kubeconfig --name $CLUSTER_NAME --profile john \ --role-arn arn:aws:iam::$ACCOUNT_ID:role/eks-admin-role }새로 생성된 kubeconfig 파일 리뷰
kubectl config view쿠버네티스 API 호출 시도
kubectl get pod -AIAM 유저에서 sts:AssumeRole 권한 부여
aws iam put-user-policy --user-name john --policy-name assume-role --policy-document \ '{ "Version": "2012-10-17", "Statement": [ { "Action": [ "sts:AssumeRole" ], "Resource": "*", "Effect": "Allow" } ] }'쿠버네티스 API 호출 시도 - 정책 적용까지 시간이 걸릴수 있음
kubectl get pod -AEKS 인증 토큰 확인
{ export AWS_PROFILE=john export TOKEN=$($(kubectl config view \ -o=jsonpath='{.users[0].user.exec.command} {.users[0].user.exec.args[*]}') \ | jq -r '.status.token' | grep -oP '(?<=k8s-aws-v1.).*') export DECODED_URL=$(base64url decode $TOKEN) curl -H "x-k8s-aws-id: $CLUSTER_NAME" $DECODED_URL }AWS 관리콘솔에 로그인된 IAM 자격증명으로 AWS CLI를 이용해서 kubeconfig 파일 업데이트
{ rm -rf ~/.kube/config unset AWS_PROFILE aws eks update-kubeconfig --name $CLUSTER_NAME }리소스 삭제
{ aws iam delete-access-key --user-name john --access-key-id $(cat key.txt | jq -r '.AccessKey.AccessKeyId') aws iam delete-user-policy --user-name john --policy-name eks-describe aws iam delete-user-policy --user-name john --policy-name assume-role aws iam delete-user --user-name john aws iam delete-role --role-name eks-admin-role aws eks delete-access-entry --cluster-name $CLUSTER_NAME \ --principal-arn arn:aws:iam::$ACCOUNT_ID:user/john aws eks delete-access-entry \ --cluster-name $CLUSTER_NAME \ --principal-arn arn:aws:iam::$ACCOUNT_ID:role/eks-admin-role rm ~/.aws/credentials ~/.aws/config rm key.txt trust-policy.json }
Scheduling
Manual Scheduling
Pod 생성
cat <<EOF | kubectl apply -f - apiVersion: v1 kind: Pod metadata: name: nginx spec: containers: - image: nginx name: nginx nodeName: worker-1 EOFPod 상태 확인
kubectl get pod nginx위의 명령어를 실행하면 아래와 같은 결과를 확인할수 있습니다.
NAME READY STATUS RESTARTS AGE nginx 0/1 Pending 0 4sPod 상태를 모니터링
watch kubectl get pod nginxKubernetes 공식문서 리뷰 - https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodename
Pod Garbage Collector 코드 리뷰 - https://github.com/kubernetes/kubernetes/blob/master/pkg/controller/podgc/gc_controller.go#L223
노드 목록 확인
kubectl get nodespec.nodeName에 위의 명령어의 결과로 나온 첫번째 노드 이름을 넣고 Pod를 생성
cat <<EOF | kubectl apply -f - apiVersion: v1 kind: Pod metadata: name: nginx spec: containers: - image: nginx name: nginx nodeName: $(kubectl get node -o=jsonpath='{.items[0].metadata.name}') EOFPod 상태 확인
kubectl get pod nginxspec.nodeName을 명시하지 않고 Pod 생성
cat <<EOF | kubectl apply -f - apiVersion: v1 kind: Pod metadata: name: httpd spec: containers: - image: httpd name: httpd EOFspec.nodeName을 명시하지 않고 생성한 Pod에 발생한 Event 확인
kubectl describe pod httpdspec.nodeName을 명시하고 생성한 Pod에 발생한 Event 확인
kubectl describe pod nginxPod 삭제
kubectl delete pod nginx httpdkube-scheduler 코드 리뷰 - https://github.com/kubernetes/kubernetes/blob/master/pkg/scheduler/schedule_one.go#L64
Node Selector
Pod 생성
cat <<EOF | kubectl apply -f - apiVersion: v1 kind: Pod metadata: name: nginx spec: containers: - image: nginx name: nginx nodeSelector: env: dev EOFPod 상태 확인
kubectl get pod nginx위의 명령어를 실행하면 아래와 같은 결과를 확인할수 있습니다.
NAME READY STATUS RESTARTS AGE nginx 0/1 Pending 0 16s아래의 명령어를 사용해서 Pod가 배포되지 않는 이유를 찾으세요.
kubectl describe pod nginxNode에 부여된 Label 확인
kubectl get node --show-labels두번째 노드에 키(Key)는 env 이고 값(Value)은 dev 인 Label 부여
{ kubectl label node \ $(kubectl get node -o=jsonpath='{.items[1].metadata.name}') env=dev kubectl get node --show-labels | grep -E 'env=dev|$' }Pending 상태였던 Pod가 배포됐는지 확인
kubectl get pod nginxPod에 발생한 Event 확인
kubectl describe pod nginxNode에 부여한 Label 삭제
kubectl label node \ $(kubectl get node -o=jsonpath='{.items[1].metadata.name}') env-Node에 Label이 삭제되었는지 확인
kubectl get node --show-labels | grep -E 'env=dev|$'Pod 상태 확인
kubectl get pod nginxPod 삭제
kubectl delete pod nginx
Spread Pod Across Cluster
Node에 부여된 Label을 통해서 Node가 생성된 가용영역 확인
kubectl get node \ -o custom-columns=NAME:.metadata.name,AvailabilityZone:".metadata.labels.topology\.kubernetes\.io/zone"nodeSelector를 명시한 Pod 생성
for s in web api storage database do cat <<EOF | kubectl apply -f - apiVersion: v1 kind: Pod metadata: name: ${s} labels: app: myapp spec: nodeSelector: topology.kubernetes.io/zone: $(kubectl get node -o=jsonpath='{.items[0].metadata.labels.topology\.kubernetes\.io/zone}') containers: - image: busybox name: busybox command: ["/bin/sleep"] args: ["infinity"] EOF done각 Pod가 배포된 Node 확인
kubectl get pod -l app=myapp -o wide -A --sort-by=.spec.nodeName각 Node별로 배포된 Pod 갯수 확인
kubectl describe node | grep -E "(^Name:|^Non-terminated)"nodeSelector를 명시하지 않은 Pod 생성
for i in {1..4} do cat <<EOF | kubectl apply -f - apiVersion: v1 kind: Pod metadata: name: nginx-${i} labels: app: nginx spec: containers: - image: nginx name: nginx EOF done각 Pod가 배포된 Node 확인
kubectl get pod -l app=nginx -o wide --sort-by=.spec.nodeName각 Node별로 배포된 Pod 갯수 확인
kubectl describe node | grep -E "(^Name:|^Non-terminated)"위에서 nodeSelector를 명시하지 않고 생성한 Pod 삭제
kubectl delete pod -l app=nginx각 Node별로 배포된 Pod 갯수 확인
kubectl describe node | grep -E "(^Name:|^Non-terminated)"Deployment 생성
cat <<EOF | kubectl apply -f - apiVersion: apps/v1 kind: Deployment metadata: labels: app: nginx name: nginx spec: replicas: 4 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - image: nginx name: nginx EOFDeployment를 통해서 생성된 Pod들이 배포된 Node 확인
kubectl get pod -l app=nginx -o wide --sort-by=.spec.nodeNameEKS 설정창에서 Scheduler의 로깅을 활성화하면 CloudWatch를 통해서 아래와 같은 구성으로 kube-scheduler가 구동되는 것을 확인 가능
apiVersion: kubescheduler.config.k8s.io/v1beta1 clientConnection: acceptContentTypes: "" burst: 100 contentType: application/vnd.kubernetes.protobuf kubeconfig: /etc/kubernetes/scheduler.conf qps: 50 enableContentionProfiling: true enableProfiling: true healthzBindAddress: 0.0.0.0:10251 kind: KubeSchedulerConfiguration leaderElection: leaderElect: true leaseDuration: 15s renewDeadline: 10s resourceLock: leases resourceName: kube-scheduler resourceNamespace: kube-system retryPeriod: 2s metricsBindAddress: 0.0.0.0:10251 parallelism: 16 percentageOfNodesToScore: 0 podInitialBackoffSeconds: 1 podMaxBackoffSeconds: 10 profiles: - pluginConfig: - args: apiVersion: kubescheduler.config.k8s.io/v1beta1 kind: DefaultPreemptionArgs minCandidateNodesAbsolute: 100 minCandidateNodesPercentage: 10 name: DefaultPreemption - args: apiVersion: kubescheduler.config.k8s.io/v1beta1 hardPodAffinityWeight: 1 kind: InterPodAffinityArgs name: InterPodAffinity - args: apiVersion: kubescheduler.config.k8s.io/v1beta1 kind: NodeAffinityArgs name: NodeAffinity - args: apiVersion: kubescheduler.config.k8s.io/v1beta1 kind: NodeResourcesFitArgs name: NodeResourcesFit - args: apiVersion: kubescheduler.config.k8s.io/v1beta1 kind: NodeResourcesLeastAllocatedArgs resources: - name: cpu weight: 1 - name: memory weight: 1 name: NodeResourcesLeastAllocated - args: apiVersion: kubescheduler.config.k8s.io/v1beta1 defaultingType: System kind: PodTopologySpreadArgs name: PodTopologySpread - args: apiVersion: kubescheduler.config.k8s.io/v1beta1 bindTimeoutSeconds: 600 kind: VolumeBindingArgs name: VolumeBinding plugins: bind: enabled: - name: DefaultBinder weight: 0 filter: enabled: - name: NodeUnschedulable weight: 0 - name: NodeName weight: 0 - name: TaintToleration weight: 0 - name: NodeAffinity weight: 0 - name: NodePorts weight: 0 - name: NodeResourcesFit weight: 0 - name: VolumeRestrictions weight: 0 - name: EBSLimits weight: 0 - name: GCEPDLimits weight: 0 - name: NodeVolumeLimits weight: 0 - name: AzureDiskLimits weight: 0 - name: VolumeBinding weight: 0 - name: VolumeZone weight: 0 - name: PodTopologySpread weight: 0 - name: InterPodAffinity weight: 0 permit: {} postBind: {} postFilter: enabled: - name: DefaultPreemption weight: 0 preBind: enabled: - name: VolumeBinding weight: 0 preFilter: enabled: - name: NodeResourcesFit weight: 0 - name: NodePorts weight: 0 - name: PodTopologySpread weight: 0 - name: InterPodAffinity weight: 0 - name: VolumeBinding weight: 0 - name: NodeAffinity weight: 0 preScore: enabled: - name: InterPodAffinity weight: 0 - name: PodTopologySpread weight: 0 - name: TaintToleration weight: 0 - name: NodeAffinity weight: 0 queueSort: enabled: - name: PrioritySort weight: 0 reserve: enabled: - name: VolumeBinding weight: 0 score: enabled: - name: NodeResourcesBalancedAllocation weight: 1 - name: ImageLocality weight: 1 - name: InterPodAffinity weight: 1 - name: NodeResourcesLeastAllocated weight: 1 - name: NodeAffinity weight: 1 - name: NodePreferAvoidPods weight: 10000 - name: PodTopologySpread weight: 2 - name: TaintToleration weight: 1 schedulerName: default-schedulerDeployment 삭제
kubectl delete deploy nginx각 Node별로 배포된 Pod 갯수 확인
kubectl describe node | grep -E "(^Name:|^Non-terminated)"podAntiAffinity를 명시하고 Pod 생성
for i in {1..4} do cat <<EOF | kubectl apply -f - apiVersion: v1 kind: Pod metadata: name: nginx-${i} labels: app: nginx spec: affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: app operator: In values: - nginx topologyKey: kubernetes.io/hostname containers: - image: nginx name: nginx EOF done위에서 생성한 Pod들이 배포된 Node 확인
kubectl get pod -l app=nginx -o wide --sort-by=.spec.nodeName위에서 생성한 Pod 삭제
kubectl delete pod -l app=nginxtopologySpreadConstraints를 명시하고 Pod 생성
for i in {1..4} do cat <<EOF | kubectl apply -f - apiVersion: v1 kind: Pod metadata: name: nginx-${i} labels: app: nginx spec: topologySpreadConstraints: - maxSkew: 3 topologyKey: topology.kubernetes.io/zone whenUnsatisfiable: ScheduleAnyway labelSelector: matchLabels: app: nginx containers: - image: nginx name: nginx EOF done위에서 생성한 Pod들이 배포된 Node 확인
kubectl get pod -l app=nginx -o wide --sort-by=.spec.nodeName리소스 삭제
kubectl delete pod -l 'app in (nginx,myapp)'
Scaling
HPA (Horizontal Pod Autoscaler)
데모 애플리케이션 배포 - https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/#run-and-expose-php-apache-server
cat <<EOF | kubectl apply -f - apiVersion: apps/v1 kind: Deployment metadata: name: php-apache spec: selector: matchLabels: app: php-apache replicas: 1 template: metadata: labels: app: php-apache spec: containers: - name: php-apache image: k8s.gcr.io/hpa-example ports: - containerPort: 80 resources: limits: cpu: 500m requests: cpu: 200m --- apiVersion: v1 kind: Service metadata: name: php-apache labels: app: php-apache spec: ports: - port: 80 selector: app: php-apache EOFPod의 리소스 사용량 확인
kubectl top pod -l app=php-apacheMetrics Server 설치 - https://github.com/kubernetes-sigs/metrics-server#kubernetes-metrics-server
{ export CLUSTER_NAME=$(kubectl get node \ -o=jsonpath='{.items[0].metadata.labels.alpha\.eksctl\.io\/cluster-name}') eksctl create addon --name metrics-server --cluster $CLUSTER_NAME }Metrics Server 설치 확인
kubectl get pod -n kube-system -l app.kubernetes.io/name=metrics-serverAPI 서버에 등록된 API 목록 확인
kubectl get apiservices.apiregistration.k8s.iov1beta1.metrics.k8s.io API의 상세 내용 확인
kubectl describe apiservices.apiregistration.k8s.io v1beta1.metrics.k8s.io모든 Pod의 리소스 사용량 확인
kubectl top pod -A모든 Node의 리소스 사용량 확인
kubectl top nodeMetrics Server 로그 확인
kubectl -n kube-system logs deploy/metrics-serverMetrics Server 로그 레벨 변경
kubectl -n kube-system patch deployment metrics-server --type=json \ -p='[{"op": "add", "path": "/spec/template/spec/containers/0/args/-", "value": "--v=6"}]'Metrics Server 로그 확인 - 새로운 Pod가 뜬 다음에 확인
kubectl -n kube-system logs deploy/metrics-serverkubelet에서 제공하는 지표에 대한 접근 권한을 가진 Pod 생성
cat <<EOF | kubectl apply -f - kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: kubelet-access rules: - apiGroups: [""] resources: - nodes/stats - nodes/metrics verbs: ["get"] --- apiVersion: v1 kind: ServiceAccount metadata: name: kubelet-access --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: kubelet-access namespace: default subjects: - kind: ServiceAccount name: kubelet-access namespace: default roleRef: kind: ClusterRole name: kubelet-access apiGroup: rbac.authorization.k8s.io --- apiVersion: v1 kind: Pod metadata: name: curl spec: serviceAccountName: kubelet-access containers: - image: curlimages/curl name: curl command: ["sleep", "3600"] env: - name: HOST_IP valueFrom: fieldRef: fieldPath: status.hostIP EOF위에서 생성한 Pod에서 Metrics Server가 지표를 수집할때 호출하는 Endpoint 호출 - https://github.com/kubernetes-sigs/metrics-server/blob/4436807eec6b07ea649444529eb3b46ddbbd8914/pkg/scraper/client/resource/client.go#L77
kubectl exec curl -- \ sh -c 'curl -s -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" https://$HOST_IP:10250/metrics/resource -k'kubelet에서 제공하는 모든 지표 확인
kubectl exec curl -- \ sh -c 'curl -s -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" https://$HOST_IP:10250/stats/summary -k'kubelet에서 제공하는 지표중에서 CPU 및 Memory에 대한 지표만 확인
kubectl exec curl -- \ sh -c 'curl -s -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" https://$HOST_IP:10250/stats/summary?only_cpu_and_memory=true -k'API 서버를 통해서 Metrics Server가 지표를 수집할때 호출하는 Endpoint 호출
kubectl get --raw /api/v1/nodes/$(kubectl get node -o=jsonpath='{.items[0].metadata.name}')/proxy/metrics/resourceAutoscaling (HPA)설정
kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=5위에서 생성한 HPA 상태 확인
kubectl get hpa php-apache데모 애플리케이션에 부하를 발생시키는 Pod 생성
kubectl run load-generator --image=busybox:1.28 -- /bin/sh -c "while sleep 0.01; do wget -q -O- http://php-apache; done"HPA 상태 모니터링
kubectl get hpa php-apache -wCtrl+C를 입력해서 HPA 모니터링을 중지하고 실제로 Pod가 생겼는지 확인
kubectl get pod -l app=php-apachePod의 리소스 사용량 확인
kubectl top pod -l app=php-apache데모 애플리케이션에 부하를 발생시키는 Pod 삭제
kubectl delete pod load-generator --nowHPA 상태 모니터링
kubectl get hpa php-apache -wCtrl+C를 입력해서 HPA 모니터링을 중지하고 HPA 상세 내용 확인
kubectl describe hpa php-apachePod의 리소스 사용량 확인
kubectl top pod -l app=php-apachestabilizationWindowSeconds의 기본값 확인
kubectl explain hpa.spec.behavior.scaleDown.stabilizationWindowSecondsstabilizationWindowSeconds의 값을 60으로 조정
kubectl patch hpa php-apache -p '{"spec": {"behavior": {"scaleDown": {"stabilizationWindowSeconds": 60}}}}'HPA 상태 확인
kubectl describe hpa php-apachePod 갯수 확인
kubectl get pod -l app=php-apache데모 애플리케이션 및 리소스 삭제
{ kubectl delete hpa php-apache kubectl delete deployment php-apache kubectl delete svc php-apache kubectl delete pod curl --now kubectl delete clusterrole kubelet-access kubectl delete clusterrolebinding kubelet-access kubectl delete sa kubelet-access }
Cluster Autoscaler
Deployment 생성
cat <<EOF | kubectl apply -f - apiVersion: apps/v1 kind: Deployment metadata: name: nginx labels: app: nginx spec: replicas: 5 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx ports: - containerPort: 80 resources: requests: cpu: 1 memory: 1Gi limits: cpu: 2 memory: 2Gi EOF생성된 Deployment 및 Pod 확인
kubectl get deploy,pod -l app=nginxPending 상태의 Pod가 있다면 아래의 명령어를 통해서 그 이유를 확인
kubectl describe pod \ $(kubectl get pod -o=jsonpath='{.items[?(@.status.phase=="Pending")].metadata.name}')Cluster Autoscaler에게 부여할 IAM 정책 생성
cat <<EOF > cluster-autoscaler-policy.json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "autoscaling:DescribeAutoScalingGroups", "autoscaling:DescribeAutoScalingInstances", "autoscaling:DescribeLaunchConfigurations", "autoscaling:DescribeScalingActivities", "ec2:DescribeImages", "ec2:DescribeInstanceTypes", "ec2:DescribeLaunchTemplateVersions", "ec2:GetInstanceTypesFromInstanceRequirements", "eks:DescribeNodegroup" ], "Resource": [ "*" ] }, { "Effect": "Allow", "Action": [ "autoscaling:SetDesiredCapacity", "autoscaling:TerminateInstanceInAutoScalingGroup" ], "Resource": [ "*" ] } ] } EOF aws iam create-policy \ --policy-name AmazonEKSClusterAutoscalerPolicy \ --policy-document file://cluster-autoscaler-policy.jsonIAM OIDC 제공자 활성화
{ export CLUSTER_NAME=$(kubectl get node \ -o=jsonpath='{.items[0].metadata.labels.alpha\.eksctl\.io\/cluster-name}') export ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) eksctl utils associate-iam-oidc-provider --region=$AWS_REGION \ --cluster=$CLUSTER_NAME --approve }ServiceAccount 생성
eksctl create iamserviceaccount \ --cluster=$CLUSTER_NAME \ --namespace=kube-system \ --name=cluster-autoscaler \ --attach-policy-arn=arn:aws:iam::${ACCOUNT_ID}:policy/AmazonEKSClusterAutoscalerPolicy \ --override-existing-serviceaccounts \ --approve \ --region $AWS_REGIONServiceAccount가 생성되었는지 확인 - Annotations 확인
kubectl -n kube-system describe sa cluster-autoscalerServiceAccount와 연동된 IAM 역할에 부여된 IAM 정책 확인
{ IAM_ROLE_NAME=$(kubectl -n kube-system get sa cluster-autoscaler \ -o=jsonpath='{.metadata.annotations.eks\.amazonaws\.com\/role-arn}' \ | grep -oP '(?<=role.).*') aws iam list-attached-role-policies --role-name $IAM_ROLE_NAME }ServiceAccount와 연동된 IAM 역할에 부여된 신뢰관계 정책 확인
aws iam get-role --role-name $IAM_ROLE_NAMECluster Autoscaler 설치
kubectl apply -f https://raw.githubusercontent.com/kubernetes/autoscaler/master/cluster-autoscaler/cloudprovider/aws/examples/cluster-autoscaler-autodiscover.yamlCluster Autoscaler 로그 확인 - ASG map 확인
kubectl -n kube-system logs deploy/cluster-autoscalerCluster Autoscaler 설정값 확인
kubectl -n kube-system get deploy cluster-autoscaler \ -o=jsonpath='{.spec.template.spec.containers[*].command}' | jqEKS 노드그룹와 연동된 오토스케일링 그룹의 인스턴스 현황 확인
{ export ASG_NAME=$(aws autoscaling describe-auto-scaling-groups --query \ "AutoScalingGroups[? Tags[? (Key=='eks:cluster-name') && Value=='$CLUSTER_NAME']].AutoScalingGroupName" --output text) aws autoscaling describe-auto-scaling-groups --auto-scaling-group-names $ASG_NAME \ --query "AutoScalingGroups[0].{MinSize: MinSize, MaxSize: MaxSize, DesiredCapacity: DesiredCapacity}" }오토스케일링 그룹에 부여된 태그 확인
aws autoscaling describe-auto-scaling-groups \ --auto-scaling-group-names $ASG_NAME --query "AutoScalingGroups[0].Tags"Node 갯수 확인
kubectl get nodeCluster Autoscaler 설정값 수정
kubectl -n kube-system patch deployment cluster-autoscaler --type=json \ -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/command", "value": [ "./cluster-autoscaler", "--v=4", "--stderrthreshold=info", "--cloud-provider=aws", "--skip-nodes-with-local-storage=false", "--expander=least-waste", "--node-group-auto-discovery=asg:tag=k8s.io/cluster-autoscaler/enabled,k8s.io/cluster-autoscaler/'${CLUSTER_NAME}'", "--balance-similar-node-groups", "--skip-nodes-with-system-pods=false" ]}]'Cluster Autoscaler 로그 확인 - 오토스케일링그룹이 정상 등록되었는지 확인
kubectl -n kube-system logs deploy/cluster-autoscalerPending 상태였던 Pod가 생성 되었는지 확인
kubectl get pod -l app=nginxNode 갯수 확인
kubectl get node오토스케일링 그룹의 인스턴스 현황 확인
aws autoscaling describe-auto-scaling-groups --auto-scaling-group-names $ASG_NAME \ --query "AutoScalingGroups[0].{MinSize: MinSize, MaxSize: MaxSize, DesiredCapacity: DesiredCapacity}"오토스케일링 그룹의 활동 로그 확인
aws autoscaling describe-scaling-activities --auto-scaling-group-name $ASG_NAMEDeployment 삭제
kubectl delete deployment nginxPod 목록 확인
kubectl get pod -l app=nginxNode가 삭제 되는지 확인
kubectl get nodeCluster Autoscaler 로그 확인
kubectl -n kube-system logs deploy/cluster-autoscalerCluster Autoscaler 스케일 다운 동작방식 리뷰 - https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md#how-does-scale-down-work
Cluster Autoscaler에 의해서 삭제 되지 않는 Node 확인 - https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md#what-types-of-pods-can-prevent-ca-from-removing-a-node
Exposing
Service
Deployment 생성
cat <<'EOF' | kubectl apply -f - apiVersion: apps/v1 kind: Deployment metadata: name: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx ports: - containerPort: 80 volumeMounts: - name: html mountPath: /usr/share/nginx/html initContainers: - name: index image: curlimages/curl command: - "sh" - "-c" - "echo 'hello from $(POD_NAME), my ip is $(POD_IP)' > /data/index.html" volumeMounts: - name: html mountPath: /data env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_IP valueFrom: fieldRef: fieldPath: status.podIP volumes: - name: html emptyDir: {} EOFService 생성
kubectl expose deployment nginx --port 80생성된 Service 확인
kubectl get svc nginx -o wide생성된 Endpoint 확인
kubectl get ep nginx생성된 Pod의 IP주소 확인
kubectl get pod -l app=nginx -o wideEndpoint에 타겟으로 등록되어 있는 Pod 목록 확인
kubectl get ep nginx \ -o jsonpath='{range .subsets[*].addresses[*]}{.targetRef.name}{"\t"}{.ip}{"\n"}{end}'생성된 Deployment의 Replica 갯수를 6개로 조정
kubectl scale deployment nginx --replicas=6생성된 Pod의 IP주소 확인
kubectl get pod -l app=nginx -o wideEndpoint에 타겟으로 등록되어 있는 Pod 목록 확인
kubectl get ep nginx \ -o jsonpath='{range .subsets[*].addresses[*]}{.targetRef.name}{"\t"}{.ip}{"\n"}{end}'Pod를 생성하고 Pod에서 위에서 생성한 Service 호출
kubectl run curl --image=nginx -it --rm --restart=Never -- \ bash -c "for i in {1..20};do curl -s $(kubectl get svc nginx -o=jsonpath='{.spec.clusterIP}');done"새로운 터미널을 열고 kube-proxy 로그 확인 - 아래의 명령어를 입력하고 엔터키를 몇번 입력해서 간격을 만들어두면 새로운 로그를 좀 더 쉽게 알아볼수 있음
kubectl -n kube-system logs ds/kube-proxy -f기존 터미널로 돌아와서 생성된 Deployment의 Replica 갯수를 3개로 조정
kubectl scale deployment nginx --replicas=3다른 터미널로 이동해서 kube-proxy 로그를 확인하고 Ctrl+C를 입력해서 프로세스 종료
한개의 Node로 Session Manager 연결
aws ssm start-session --target \ $(kubectl get node -o jsonpath='{.items[0].spec.providerID}{"\n"}' | grep -oE "i-[a-z0-9]+")Iptable의 모든 규칙 확인
sudo iptables-saveIptable의 NAT 규칙 확인
sudo iptables -L -t natKUBE-SERVICES 규칙 확인
sudo iptables -t nat -L KUBE-SERVICES -n | column -t위에서 생성한 Service의 Cluster IP로 연결된 규칙의 상세내용 확인
{ export SERVICE_CHAIN=$(sudo iptables -t nat -L KUBE-SERVICES -n | column -t | grep "default/nginx" | grep -oE "^KUBE-SVC-[A-Z0-9]+") sudo iptables -t nat -L $SERVICE_CHAIN -n | column -t }위의 명령어로 나온 결과중의 한개의 Chain 규칙 확인
sudo iptables -t nat -L $(sudo iptables -t nat -L $SERVICE_CHAIN -n | column -t | grep -oE "^KUBE-SEP-[A-Z0-9]+" | head -1) \ -n | column -t첫번째 터미널로 이동해서 생성된 Pod의 IP주소 확인
kubectl get pod -o wide -l app=nginxDeployment의 Replica 갯수를 6개로 조정
kubectl scale deployment nginx --replicas=6두번째 터미널로 이동해서 18번 명령어 재실행
첫번째 터미널로 이동해서 Service를 ClusterIP에서 LoadBalancer로 변경
kubectl patch svc nginx -p '{"spec": {"type": "LoadBalancer"}}'Service가 변경되었는지 확인
kubectl get svc nginx -o wideService 객체에 발생한 Event 확인
kubectl describe svc nginx웹 브라우저를 열고 Service의 External IP 주소로 접속 - 아래의 명령어로 주소 확인 가능
kubectl get svc nginx -o jsonpath='{.status.loadBalancer.ingress[0].hostname}{"\n"}'Service 상세 내용 확인 - 포트 정보 확인
kubectl get svc nginx -o=jsonpath='{.spec}' | jqService를 통해서 생성된 ELB 상세 내용 확인
aws elb describe-load-balancers --load-balancer-names \ $(kubectl get svc nginx -o jsonpath='{.status.loadBalancer.ingress[0].hostname}' | grep -o -E '^[a-z0-9]+' )ELB의 Listener 설정 확인
aws elb describe-load-balancers --load-balancer-names \ $(kubectl get svc nginx -o jsonpath='{.status.loadBalancer.ingress[0].hostname}' | grep -o -E '^[a-z0-9]+' ) \ --query 'LoadBalancerDescriptions[*].ListenerDescriptions'ELB의 보안그룹 확인
aws elb describe-load-balancers --load-balancer-names \ $(kubectl get svc nginx -o jsonpath='{.status.loadBalancer.ingress[0].hostname}' | grep -o -E '^[a-z0-9]+' ) \ --query 'LoadBalancerDescriptions[*].SecurityGroups'노드에 부여된 보안그룹에 ELB 보안그룹에 대한 새로운 인바운드 규칙이 추가 됐는지 확인
aws ec2 describe-security-groups --group-ids \ $(aws ec2 describe-instances --instance-ids \ $(kubectl get node -o jsonpath='{.items[0].spec.providerID}{"\n"}' | grep -oE "i-[a-z0-9]+") \ --query 'Reservations[0].Instances[0].SecurityGroups[*].GroupId' --output text) \ --query "SecurityGroups[*].IpPermissions"두번째 터미널로 이동해서 Iptable 규칙 확인
sudo iptables-save | grep nginxKUBE-SERVICES 규칙 확인
sudo iptables -t nat -L KUBE-SERVICES -n | column -tKUBE-NODEPORTS 규칙 확인
sudo iptables -t nat -L KUBE-NODEPORTS -n | column -tNodePort 호출
curl localhost:NODEPORT첫번째 터미널로 이동해서 Service를 LoadBalancer에서 ClusterIP로 변경
kubectl patch svc nginx -p '{"spec": {"type": "ClusterIP"}}'ELB가 삭제되었는지 확인
aws elb describe-load-balancers데모 애플리케이션 삭제
{ kubectl delete deploy nginx kubectl delete svc nginx }
Ingress
AWS Load Balancer Controller에 부여할 IAM 정책 생성
{ export ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) export CLUSTER_NAME=$(kubectl get node \ -o=jsonpath='{.items[0].metadata.labels.alpha\.eksctl\.io\/cluster-name}') eksctl utils associate-iam-oidc-provider \ --region $AWS_REGION \ --cluster $CLUSTER_NAME \ --approve curl -o aws-loadbalancer-controller-policy.json \ https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.13.2/docs/install/iam_policy.json aws iam create-policy \ --policy-name AWSLoadBalancerControllerIAMPolicy \ --policy-document file://aws-loadbalancer-controller-policy.json }ServiceAccount 생성
eksctl create iamserviceaccount \ --cluster $CLUSTER_NAME \ --namespace=kube-system \ --name=aws-load-balancer-controller \ --attach-policy-arn=arn:aws:iam::${ACCOUNT_ID}:policy/AWSLoadBalancerControllerIAMPolicy \ --override-existing-serviceaccounts \ --approve \ --region $AWS_REGIONEKS 리포지토리 추가
helm repo add eks https://aws.github.io/eks-charts && helm repo update위에서 추가한 리포지토리가 추가되었는지 확인
helm repo list위에서 추가한 리포지토리에 있는 Helm 차트 목록 확인
helm search repo eksAWS Load Balancer Controller 설치
helm install aws-load-balancer-controller eks/aws-load-balancer-controller \ --version 1.13.2 \ --namespace kube-system \ --set clusterName=$CLUSTER_NAME \ --set replicaCount=1 \ --set serviceAccount.create=false \ --set serviceAccount.name=aws-load-balancer-controllerAWS Load Balancer Controller 로그 확인
kubectl -n kube-system logs deploy/aws-load-balancer-controller데모 웹사이트 배포
{ kubectl create deployment nginx --image=nginx --port=80 kubectl expose deploy nginx }생성된 리소스 확인
kubectl get all -l app=nginxIngress 생성
cat <<EOF | kubectl apply -f - apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: nginx spec: ingressClassName: alb rules: - http: paths: - path: / pathType: Prefix backend: service: name: nginx port: number: 80 EOF생성된 Ingress 확인
kubectl get ing nginx위에서 생성한 Ingress에 발생한 Event 확인
kubectl describe ingress nginxAWS Load Balancer Controller 로그 확인
kubectl -n kube-system logs deploy/aws-load-balancer-controllerIngress 수정
cat <<EOF | kubectl apply -f - apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: nginx annotations: alb.ingress.kubernetes.io/target-type: ip spec: ingressClassName: alb rules: - http: paths: - path: / pathType: Prefix backend: service: name: nginx port: number: 80 EOFIngress 상태 확인
kubectl get ing nginxIngress에 발생한 Event 확인
kubectl describe ingress nginxAWS Load Balancer Controller 로그 확인
kubectl -n kube-system logs deploy/aws-load-balancer-controller아래의 명령어를 실행해서 생성된 ALB 엔드포인트를 확인하고 웹브라우저를 통해서 접근이 되는지 확인
echo $(kubectl get ing nginx -o=jsonpath='{.status.loadBalancer.ingress[0].hostname}')생성된 ALB의 상세 내용 확인 - Scheme 확인
{ export LoadBalancerName=$(aws elbv2 describe-load-balancers | \ jq -r '.LoadBalancers[] | select(.DNSName == "'"$(kubectl get ing nginx -o=jsonpath='{.status.loadBalancer.ingress[0].hostname}')"'") | .LoadBalancerName') aws elbv2 describe-load-balancers --names $LoadBalancerName }ALB가 생성된 서브넷 확인
aws elbv2 describe-load-balancers --names $LoadBalancerName \ --query 'LoadBalancers[0].AvailabilityZones[*]'ALB가 생성된 서브넷에 부여된 태그 확인
aws ec2 describe-subnets --subnet-ids --query 'Subnets[*].Tags' \ $(aws elbv2 describe-load-balancers --names $LoadBalancerName \ --query 'LoadBalancers[0].AvailabilityZones[*].SubnetId' --output text)AWS Load Balancer Controller가 ALB를 생성한 서브넷을 선택하는 방법 확인 - https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.13/deploy/subnet_discovery/
AWS Load Balancer Controller로 Ingress 생성할때 요구되는 파라미터 및 기본값 확인 - https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.13/guide/ingress/annotations/
Ingress 수정
cat <<EOF | kubectl apply -f - apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: nginx annotations: alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/target-type: ip spec: ingressClassName: alb rules: - http: paths: - path: / pathType: Prefix backend: service: name: nginx port: number: 80 EOFIngress에 발생한 Event 확인
kubectl describe ingress nginxAWS Load Balancer Controller 로그 확인
kubectl -n kube-system logs deploy/aws-load-balancer-controller아래의 명령어를 실행해서 생성된 ALB 엔드포인트를 확인하고 웹브라우저를 통해서 접근이 되는지 확인
echo $(kubectl get ing nginx -o=jsonpath='{.status.loadBalancer.ingress[0].hostname}')기존에 생성된 ALB가 존재하는지 확인
aws elbv2 describe-load-balancers --names $LoadBalancerName새롭게 생성된 ALB의 ARN를 확인하고 환경변수로 저장
{ export LoadBalancerArn=$(aws elbv2 describe-load-balancers | \ jq -r '.LoadBalancers[] | select(.DNSName == "'"$(kubectl get ing nginx -o=jsonpath='{.status.loadBalancer.ingress[0].hostname}')"'") | .LoadBalancerArn') echo $LoadBalancerArn }아파치 웹서버 배포
{ kubectl create deployment httpd --image=httpd kubectl expose deployment httpd --port=80 }Ingress 수정
cat <<EOF | kubectl apply -f - apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: nginx annotations: alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/target-type: ip spec: ingressClassName: alb rules: - host: nginx.example.com http: paths: - path: / pathType: Prefix backend: service: name: nginx port: number: 80 - host: httpd.example.com http: paths: - path: / pathType: Prefix backend: service: name: httpd port: number: 80 EOF아래의 명령어를 실행해서 생성된 ALB 엔드포인트를 확인하고 웹브라우저를 통해서 접근이 되는지 확인
echo $(kubectl get ing nginx -o=jsonpath='{.status.loadBalancer.ingress[0].hostname}')cURL 명령어로 Host 값을 nginx.example.com으로 명시하고 ALB 엔드포인트 호출
curl -H "Host: nginx.example.com" \ $(kubectl get ing nginx -o=jsonpath='{.status.loadBalancer.ingress[0].hostname}')cURL 명령어로 Host 값을 httpd.example.com으로 명시하고 ALB 엔드포인트 호출
curl -H "Host: httpd.example.com" $(kubectl get ing nginx -o=jsonpath='{.status.loadBalancer.ingress[0].hostname}')ALB 리스너 확인
{ export ListnerArn=$(aws elbv2 describe-listeners \ --load-balancer-arn $LoadBalancerArn \ --query "Listeners[0].ListenerArn" --output text) aws elbv2 describe-listeners --listener-arns $ListnerArn }ALB 리스너 규칙 확인
aws elbv2 describe-rules --listener-arn $ListnerArnALB에 연동된 대상그룹 확인
{ export TG=$(aws elbv2 describe-target-groups \ --load-balancer-arn $LoadBalancerArn \ --query "TargetGroups[*].TargetGroupArn" \ --output text) aws elbv2 describe-target-groups --target-group-arns $TG }대상그룹에 포함된 대상 목록 확인
for target in $TG do aws elbv2 describe-target-health --target-group-arn $target --no-cli-pager donePod 목록 확인
kubectl get pod -o wide -l 'app in (nginx,httpd)'아파치 Pod 갯수를 3개로 조정
kubectl scale deployment httpd --replicas=3Pod 목록 확인
kubectl get pod -o wide -l 'app in (nginx,httpd)'대상그룹에 포함된 대상 목록 확인
for target in $TG do aws elbv2 describe-target-health --target-group-arn $target --no-cli-pager doneIngress 삭제
kubectl delete ing nginxAWS Load Balancer Controller 로그 확인
kubectl -n kube-system logs deploy/aws-load-balancer-controllerALB가 삭제되었는지 확인
aws elbv2 describe-load-balancers --load-balancer-arns $LoadBalancerArn리소스 삭제
{ kubectl delete svc httpd nginx kubectl delete deploy httpd nginx }
Last updated
Was this helpful?