[AWS] Load Balance Conller + k8s services

hugingstar·7일 전

AWS

목록 보기
18/18
post-thumbnail
  • 서비스가 배포된 것을 보면 EXTERNAL IP가 여러개인 것을 볼 수 있다.
  • 접속할 때 원활한 IP가 뭔지 어떻게 알 수 있을까? 불가능하다.

  • AWS 로드 밸런서와 k8s service를 합쳐서 만들어본다.

Subnet(PUB) Tag 설정

awscli 사용

  • 각 subnet의 id를 사용해서 aws 명령어로 tag를 설정한다.
# 각 subnet의 id가 필요하다.
# role/elb = 1 : Public subnet
# role/internal-elb =1 : Private subnet
# role/yslee-cluster = shared :public, private 모두
aws ec2 create-tags \
-- resources <<subnet-id-0>>, <<subnet-id-0>>, .. \
-- tags Key=kubernetes.io/role/elb,Value=1 \
		Key=kubernetes.io/role/internal-elb,Value=1 \
        Key=kubernetes.io/cluster/yslee-cluster,Value=shared 
  • 쉼표, 띄어쓰기 잘 신경써서 작업한다.
aws ec2 create-tags \
-- resources subnet-0d8f8b992c8739fde subnet-03ca1d569fe5571ba \
-- tags Key=kubernetes.io/role/elb,Value=1 \
Key=kubernetes.io/role/internal-elb,Value=1 \
Key=kubernetes.io/cluster/yslee-cluster,Value=shared 

  • VPC>서브넷> PUB-2A, PUB-2C의 태크 확인

Cluster의 IAM OIDC 자격 증명 공급자 생성

eksctl utils associate-iam-oidc-provider --cluster yslee-cluster --region ap-southeast-2 --approve

IAM 정책 생성

  • IAM > ID 제공업체가 있다.

  • IAM 정책 부분 들어가서 loadbalancer 치면 하나 나온다.

  • 실제로 해야 하는 것은
# IAM 정책 다운로드 - AWS Load Balancer Controller가 AWS API 호출을 허용하는 정책
curl -o iam_policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.3.1/docs/install/iam_policy.json

# 부하분산 관련 정책 생성
aws iam create-policy \
    --policy-name AWSLoadBalancerControllerIAMPolicy \
    --policy-document file://iam_policy.json

  • 정책 부분에 Loadbalancer 쳐보니까 위에서 policy 생성한 것이 들어가 있다. 유형이 고객 관리함이라고 써져 있다.

aws-load-balancer-controller 라는 k8s service 계정에 대한 IAM 역할 생성

  • 생성한 정책의 ARN 주소를 사용해야하기 때문에 복사해둔다. 정책 안에 들어가면 복사할 수 있다.
eksctl create iamserviceaccount \
  --region=ap-northeast-2 \
  --cluster=xxx-cluster \
  --namespace=kube-system \
  --name=aws-load-balancer-controller \
  --attach-policy-arn=arn:aws:iam::xxxxxxxx:policy/AWSLoadBalancerControllerIAMPolicy \
  --override-existing-serviceaccounts \
  --approve

  • IAM>역할로 가서 serviceaccount를 검색해보면 하나 등록된 것이 있을 것이다.

  • serviceaccount를 kubectl로도 확인해본다.
# 간략한 정보
kubectl get serviceaccount -n kube-system aws-load-balancer-controller

# 더욱 상세한 정보 - Annotation 부분을 봐야한다.
kubectl describe serviceaccount -n kube-system aws-load-balancer-controller

역할에 권한 추가

  • 만들어진 것 들어가보면, 권한 정책에 Policy 추가되어 있는 것을 볼 수 있다.

  • 여기서 "정책 연결"을 눌러서 정책을 추가해줄 것이다.
  • ElasticLoadBalancingFullAccess를 권한 추가한다.

AWS load balancer controller 설치

  • Helm과 저장소를 추가한다.
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod +x get_helm.sh
./get_helm

helm repo add eks https://aws.github.io/eks-charts
helm repo update

  • helm을 사용하여 AWS Load Balancer Controller를 설치한다.
helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
   -n kube-system \
   --set clusterName=xxx-cluster \
   --set serviceAccount.create=false \
   --set serviceAccount.name=aws-load-balancer-controller \
   --set image.repository=602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/amazon/aws-load-balancer-controller \
   --set region=ap-northeast-2 \
   --set vpcId=vpc-xxxxxxxxxxxxxxxx

  • 잘못쓰면 삭제하고 다시하기
# 삭제 방법
helm uninstall aws-load-balancer-contoller -n kube-system
release "aws-load-balancer-contoller" uninstalled
  • 오타로 잘못썼을 때,

  • deploy를 조회해본다.
kubectl get deploy -n kube-system aws-load-balancer-controller

kubectl get pod -n kube-system

  • aws-load-balancer-controller라고 만들어진 것이 2개 생성되어 있다.

  • Pod describe
# 첫번째
kubectl describe pod -n kube-system aws-load-balancer-controller-6d969cf4-kclbz

# 두번째
kubectl describe pod -n kube-system aws-load-balancer-controller-6d969cf4-wcwwd

Service에 AWS load Balancer 적용

  • 띄워져있는 서비스 있는데 잠시 내린다.
  • nginx-01.yaml을 복사해서 변경해서 새로운 것을 적용한다.
# nginx-00.yaml delete
kubectl delete -f nginx-00.yaml
 
# nginx-01.yaml
cp nginx-00.yaml nginx-01.yaml

  • 아래쪽 Service 부분을 일부 수정해야한다.
  • internet-facing 줄을 추가한다. 그리고 type:을 LoadBalancer로 변경한다.
  • LoadBalancer를 사용하니까 nodePort 지워줘야한다.
vi nginx-01.yaml

# 작성한 내용
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: docker.io/yslee4050/yslee-nginx:v1.0
          ports:
          - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
spec:
  type: LoadBalancer
  selector:
    app: nginx
  ports:
  - port: 80
    targetPort: 80

  • nginx-01.yaml을 실행한다. 특이한 점은 EXTERNAL-IP 부분을 보면 특이한 형태의 주소가 떠 있는 것을 볼 수 있다.
  • nodePort할 때는 30080으로 고정되어 있지만, 이번에는 LoadBalancer를 사용하니까 IP가 다른걸로 변경되어 있는 것을 볼 수 있다.

  • 그리고 AWS에도 잘 반영되어 있는지 확인할려면, EC2 인스턴스로 가본다.
  • Loadbalancer 2개가 적용되어서 인스턴스 2개가 생성되어 있다.

  • Pod1 안으로 들어가본다.
  • bash가 없어서 sh로 해야한다.
# 파드 안으로 접속
kubectl exec -it nginx-deploy-7cb4cc88f8-brv68 -- /bin/sh

# 현재 index.html 확인
cat /usr/share/nginx/html/index.html

# pod1이라는 문자로 대체
echo "pod1" > /usr/share/nginx/html/index.html

# 확인
curl localhost
  • Pod2 안으로 들어가본다.
kubectl exec -it nginx-deploy-7cb4cc88f8-n4q49 -- /bin/sh

cat /usr/share/nginx/html/index.html

echo "pod2" > /usr/share/nginx/html/index.html

curl localhost

  • kubectl 부분 svc를 조회한다.

  • 로드밸런서로 가본다. 로드밸런서를 한번 새로고침해본다.

  • 가용영역 southeast-2a,southeast-2c로 설정되어 있다. DNS 복사해서 접속해본다.

  • DNS를 웹에 써서 들어가서 한번 연결되면, 다른 곳으로 자동으로 넘어가지 않는다.

마지막 단계

  • 최종 작업을 위해서 nginx-01.yaml을 nginx-02.yaml로 파일을 복사한다.

  • Ingress를 적용해서 만들어본다. 이전에 썼던 LoadBalancer는 지운다.
  • Ingress는 nginx-svc를 받아서 작동한다.
  • path에 역슬래쉬 넣으면 안된다.
vi nginx-02.yaml

# 작성한 내용
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: docker.io/yslee4050/yslee-nginx:v1.0
          ports:
          - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  type: ClusterIP
  selector:
    app: nginx
  ports:
  - port: 80
    targetPort: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-alb
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
spec:
  ingressClassName: alb
  defaultBackend:
    service:
      name: nginx-svc
      port:
        number: 80
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-svc
            port:
              number: 80

  • 실행한다.
kubectl apply -f nginx-02.yaml
  • Ingress가 잘 떠있는지를 확인해본다.
kubectl get ingress

  • 로드밸런서도 프로비저닝 하고있다.

  • 활성 상태 되었다.

  • DNS로 접속을 실행해본다.

  • 어디 파드로 접속했는지를 모르니까 exec로 파드 들어가서 글자 바꿔서 해본다.
  • 나올 때는 ctrl+D로 나오면 된다.

  • 자동으로 잘 바뀐다.

원상복구 방법

  • 빌드하는 것 만큼이나 중요한 것은 원상복구다.

(1) deploy,svc 삭제

kubectl delete -f nginx-02.yaml

(2) helm 제거

helm uninstall aws-load-balancer-controller -n kube-system

(3) iamserviceaccount 삭제

eksctl delete iamserviceaccount \
  --cluster yslee-cluster \
  --namespace kube-system \
  --region ap-southeast-2 \
  --name aws-load-balancer-controller

(4) role & policy 삭제

# 정책 관련 arn 확인
aws iam list-policies --scope Local | grep AWSLoadBalancerControllerIAMPolicy

# 연결된 entity 확인
aws iam list-entities-for-policy \
  --policy-arn arn:aws:iam::xxxxxxxxxxxx:policy/AWSLoadBalancerControllerIAMPolicy

# policy 삭제
aws iam delete-policy \
  --policy-arn arn:aws:iam::xxxxxxxxxxxx:policy/AWSLoadBalancerControllerIAMPolicy

(참고)
# Role detach
aws iam detach-role-policy \
  --role-name eksctl-xxx-cluster-addon-iamserviceaccount-kube-system-aws-load-balancer-controller-Role1-XXXXXX \
  --policy-arn arn:aws:iam::xxxxxxxxxxxxx:policy/AWSLoadBalancerControllerIAMPolicy

# 연결된 entity 확인
aws iam list-entities-for-policy \
  --policy-arn arn:aws:iam::xxxxxxxxxxxx:policy/AWSLoadBalancerControllerIAMPolicy
  • AWS 창에서도 잘 지워졌는지 확인해본다.

0개의 댓글