AWS EKS(Elastic Kubernetes Service) 삽질기
AWS EKS에서 kubectl 접속부터 Pod, Service, Deployment, Ingress 등 쿠버네티스 오브젝트와 helm을 사용하며 발생한 문제를 해결한 내용을 정리했습니다.
(계속 업데이트할 예정입니다.)
로컬 PC는 macOS Catalina를 사용중이며 AWS EKS는 1.14버전입니다.
$ k version
Client Version: version.Info{Major:"1", Minor:"14", GitVersion:"v1.14.8", GitCommit:"211047e9a1922595eaa3a1127ed365e9299a6c23", GitTreeState:"clean", BuildDate:"2019-10-15T12:11:03Z", GoVersion:"go1.12.10", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"14+", GitVersion:"v1.14.9-eks-c0eccc", GitCommit:"c0eccca51d7500bb03b2f163dd8d534ffeb2f7a2", GitTreeState:"clean", BuildDate:"2019-12-22T23:14:11Z", GoVersion:"go1.12.12", Compiler:"gc", Platform:"linux/amd64"}
쿠버네티스 개념에 대한 설명은 없습니다.
kubectl↔EKS cluster 연결
aws-iam-authenticator 설치
(가이드에서는 설치하라고 하는데 필요한지 모르겠습니다. 이후 과정에서 관련 문제가 발생하면 설치해주세요.)brew install aws-iam-authenticator
- awscli 설치
pip3 install awscli
aws configure
- IAM 사용자/역할 확인
aws sts get-caller-identity
- eks kubeconfig 추가
aws eks update-kubeconfig --name <cluster-name>
클러스터를 생성하고 다른 사용자에게 권한 주기
클러스터를 만든 사용자 계정이 아닌 다른 계정으로 kubectl
을 이용해 접근하니 권한 에러가 발생했습니다.
다른 사용자에게 권한 주기를 참고해 권한을 지급하는 등의 설정을 할 수 있습니다.
# aws-auth.yaml 예
apiVersion: v1
kind: ConfigMap
metadata:
name: aws-auth
namespace: kube-system
data:
mapRoles: |
- rolearn: arn:aws:iam::832626921517:role/AWSEC2AmazonEKSGroup # 노드 IAM 역할
username: system:node:
groups:
- system:bootstrappers
- system:nodes
mapUsers: |
- userarn: arn:aws:iam::832626921517:user/Kubernetes # 사용자
username: Kubernetes # 사용자 이름
groups: # 그룹 (https://kubernetes.io/docs/reference/access-authn-authz/rbac/#default-roles-and-role-bindings 참고)
- system:masters
- aws-auth 확인:
kubectl describe configmap -n kube-system aws-auth
- EKS 반영:
kubectl apply -f aws-auth.yaml
Dashboard
쿠버네티스를 관리할 수 있는 대시보드를 띄울 수 있습니다.
참고자료
Ingress
인그레스는 클라이언트의 요청을 서비스로 전달합니다.
아래의 helm을 참고하면 간편하게 구성할 수 있습니다.
Ingress만 생성하면 사용할 수 없고, Ingress Controller를 생성해줘야 합니다.
https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml 설정을 이용해서 인그레스 컨트롤러를 생성했는데, 추가적인 설정이 필요했습니다.
kind: ConfigMap
apiVersion: v1
metadata:
name: nginx-configuration
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
data:
# 옵션에 대한 설명은
# [https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap](https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#use-forwarded-headers)
# 에서 확인할 수 있습니다.
use-forwarded-headers: "true"
compute-full-forwarded-for: "true"
use-proxy-protocol: "true"
# TCP4 프록시하는 로그
172.31.40.219 - - [23/Dec/2019:03:19:26 +0000] "PROXY TCP4 27.115.124.6 172.31.40.219 64396 443" 400 163 "-" "-" 0 0.091 [] [] - - - - 936532129462698291cc150891df4eb9
172.31.40.219 - - [23/Dec/2019:03:19:27 +0000] "PROXY TCP4 27.115.124.70 172.31.40.219 49929 443" 400 163 "-" "-" 0 0.098 [] [] - - - - 3a28d01a364cd0d78eaeeaad879f26fb
# 설정 적용 후 정상 동작하는 로그
106.240.29.163 - - [23/Dec/2019:03:24:15 +0000] "GET / HTTP/2.0" 200 27 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36" 13 0.003 [default-sample-service-18080] [] 172.31.13.213:8080 27 0.004 200 9bef6f2255aa43db65e1204cb4321e41
106.240.29.163 - - [23/Dec/2019:03:24:15 +0000] "GET / HTTP/2.0" 200 27 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36" 13 0.004 [default-sample-service-18080] [] 172.31.10.7:8080 27 0.004 200 6f811489dd313133b69f6cede18bb6a5
external-dns를 이용해 route 53의 레코드를 자동으로 설정 할 수 있습니다.
이때, EKS 역할이 사용할 route 53의 권한 정책이 필요합니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"route53:ChangeResourceRecordSets",
"route53:ListResourceRecordSets"
],
"Resource": "arn:aws:route53:::hostedzone/*"
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": "route53:ListHostedZones",
"Resource": "*"
}
]
}
ingress 메니페스트 파일입니다.
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: sample-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: "sample.jubeom.dev"
http:
paths:
- path: /
backend:
serviceName: sample-service
servicePort: 18080
인그레스를 적용하면 rules
의 host
를 이용해 레코드를 자동으로 생성합니다.
참고자료
HPA (Horizontal Pod Autoscaler)
파드의 수를 수평적으로 확장할 수 있는 기능입니다.
문제 1. no matches for kind "HorizontalPodAutoScaler" in version "autoscaling/v2beta1"
error: unable to recognize "?.yml": no matches for kind "HorizontalPodAutoScaler" in version "autoscaling/v2beta1"
버전에 맞지 않은 yml 세팅을 사용해 발생한 문제입니다.
AWS EKS 클러스터는 1.14 버전을 사용 중입니다.
공식 문서의 룰에 따라 HPA를 설정해서 해결할 수 있었습니다.
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: sample-hpa
spec: # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.14/#horizontalpodautoscalerspec-v2beta2-autoscaling
scaleTargetRef:
apiVersion: extensions/v1beta1
kind: Deployment
name: sample-app
minReplicas: 1
maxReplicas: 5
metrics: # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.14/#metricspec-v2beta2-autoscaling
- type: Resource
resource: # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.14/#resourcemetricsource-v2beta2-autoscaling
name: cpu
target: # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.14/#metrictarget-v2beta2-autoscaling
type: Utilization
averageUtilization: 80
# type: AverageValue
# averageValue: 80
참고자료
- https://github.com/kubernetes/kubernetes/issues/73738
- https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.14/
문제 2. target pod cpu unknown
$ kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
sample-hpa Deployment/sample-app <unknown>/80 1 5 1 18m
$ kubectl describe hpa
Name: sample-hpa
Namespace: default
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"autoscaling/v2beta2","kind":"HorizontalPodAutoscaler","metadata":{"annotations":{},"name":"sample-hpa","namespace":"default...
CreationTimestamp: Tue, 24 Dec 2019 10:07:08 +0900
Reference: Deployment/sample-app
Metrics: ( current / target )
resource cpu on pods: <unknown> / 80
Min replicas: 1
Max replicas: 5
Deployment pods: 1 current / 0 desired
Conditions:
Type Status Reason Message
---- ------ ------ -------
AbleToScale True SucceededGetScale the HPA controller was able to get the target's current scale
ScalingActive False FailedGetResourceMetric the HPA was unable to compute the replica count: unable to get metrics for resource cpu: unable to fetch metrics from resource metrics API: the server could not find the requested resource (get pods.metrics.k8s.io)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedComputeMetricsReplicas 19m (x12 over 22m) horizontal-pod-autoscaler failed to get cpu utilization: unable to get metrics for resource cpu: unable to fetch metrics from resource metrics API: the server could not find the requested resource (get pods.metrics.k8s.io)
Warning FailedGetScale 17m (x5 over 18m) horizontal-pod-autoscaler deployments/scale.apps "sample-service" not found
Warning FailedGetResourceMetric 2m16s (x68 over 22m) horizontal-pod-autoscaler unable to get metrics for resource cpu: unable to fetch metrics from resource metrics API: the server could not find the requested resource (get pods.metrics.k8s.io)
아래 참고 자료를 이용해 메트릭 서버를 실행시켜 CPU 정보를 얻어올 수 있습니다.
$ k get hpa -w
sample-hpa Deployment/sample-app 4%/80% 1 5 1 68m
sample-hpa Deployment/sample-app 4%/80% 1 5 1 69m
sample-hpa Deployment/sample-app 0%/80% 1 5 1 70m
부하를 줘서 실제로 파드의 수가 늘어나는지 확인하기 위해 스케일링 기준 CPU를 낮추고 loader.io를 이용해 테스트한 결과입니다.
참고자료
Helm
helm은 쿠버네티스 패키지 관리자입니다.
helm v3.x을 사용했습니다.
(version.BuildInfo{Version:”v3.0.2”, GitCommit:”19e47ee3283ae98139d98460de796c1be1e3975f”, GitTreeState:”clean”, GoVersion:”go1.13.5”})
helm 설치
$ brew install helm
레포지토리 추가
$ helm repo add stable https://kubernetes-charts.storage.googleapis.com/
헬름 차트 만들 때
- helm 템플릿 파일은 templates 디렉토리 하위에 있어야 합니다. (vscode에서 문법 오류)
- 확장자를
.yml
을 사용하면 인식이 안됩니다..yaml
을 사용해야 합니다.
헬름 차트 릴리즈
$ helm install <name> <dir>
헬름 차트 업그레이드
helm upgrade <name> <dir>
다른 배포 환경을 사용할 경우 helm install sample-staging . --values ./values-staging.yml
와 같이 --values
옵션을 이용해 지정할 수 있습니다.
위(ingress)에서 설치한 nginx-ingress, external-dns는 helm을 이용해 손쉽게 구성할 수 있습니다.
# nginx-ingress
$ helm install nginx-ingress stable/nginx-ingress \
--set controller.publishService.enabled=true
# external-dns
$ helm install external-dns stable/external-dns \
--set aws.region=ap-northeast-2 \
--set aws.zoneType=public
참고자료
- https://github.com/helm/charts/tree/master/stable/nginx-ingress
- https://github.com/helm/charts/tree/master/stable/external-dns
무중단 배포
참고자료
모니터링
prometheus
$ helm install prometheus-operator stable/prometheus-operator # prometheus 설치
grafana
$ helm install grafana stable/grafana # grafana 설치
$ kubectl get secret grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo # grafana 비밀번호 확인
grafana의 유저네임은 admin
입니다.
Import → 1860
(dashboard id) → Import
- Node Exporter Full - https://grafana.com/grafana/dashboards/1860
- Analysis by Cluster - https://grafana.com/grafana/dashboards/6873
(cost는 GCP 기준으로 되어있고 값 수정이 가능) - Analysis by Pod - https://grafana.com/grafana/dashboards/6876
- Analysis by Namespace - https://grafana.com/grafana/dashboards/6879
참고자료
댓글남기기