레이블이 eks인 게시물을 표시합니다. 모든 게시물 표시
레이블이 eks인 게시물을 표시합니다. 모든 게시물 표시

aws cli command

# AWS CLI 설치
https://docs.aws.amazon.com/ko_kr/cli/latest/userguide/install-cliv2-mac.html
# mac
curl "https://awscli.amazonaws.com/AWSCLIV2.pkg" -o "AWSCLIV2.pkg"
sudo installer -pkg AWSCLIV2.pkg -target /

# linux
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install

# AWS > IAM > 사용자 > 보안자격증명 > 액세스 키 만들기
# 액세스 키ID: xxxxx
# 비밀 액세스 키ID: xxxxx (액세스 키는 만들기 팝업에서만 보이기 때문에 이때 적어둬야함, 이때 못 보면 새로 만들어야함)
# AWS CLI 명령
# aws 접속 설정
aws configure
AWS Access Key ID [None]: xxxxx
AWS Secret Access Key [None]: xxxxx
Default region name [None]: ap-northeast-2
Default output format [None]: json

# aws 접속 설정 수정
vi ~/.aws/credentials
vi ~/.aws/config

# eks 연결 설정
aws eks update-kubeconfig --region ap-northeast-2 --name ysoftman-dev

# ecr 클라언트 인증
aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin xxxxx.dkr.ecr.ap-northeast-2.amazonaws.com

# elb(classic) 리스트 파악
aws elb describe-load-balancers

# elb tag key 중 "ysoftman" 가 포함된 설정 보기
aws elb describe-load-balancers | rg -i loadbalancername | awk '{print $2}' | sed -e "s/\"//g" -e "s/,//g" | xargs aws elb describe-tags --load-balancer-names | jq '.TagDescriptions[] | select (.Tags[].Key | contains("ysoftman"))'

# elbv2(nlb, alb) 리스트 파악
aws elbv2 describe-load-balancers

# elbv2 LoadBalancerName 중 "ysoftman" 가 포함된 설정 보기 (arn 기준으로 찾는다.)
aws elbv2 describe-load-balancers | rg -i arn | awk '{print $2}' | sed -e "s/\"//g" -e "s/,//g" | xargs aws elbv2 describe-load-balancers --load-balancer-arns | jq '.LoadBalancers[] | select (.LoadBalancerName | contains("ysoftman"))'

# ec2 network acls 설정 보기
aws ec2 describe-network-acls


#####

# AWS > IAM > 사용자 > 권한 > 기존 정책 직접 연결 > AmazonS3FullAccess 선택 후 다음(권한추가)

# AWS > S3 > 버킷(bill-xxxxx) 생성 또는 
aws s3 mb s3://bill-xxxx

# s3 버킷 리스트(접속 확인)
aws s3 ls | grep bill-xxxxx

# billtest.txt 업로드
aws s3 cp billtest.txt s3://bill-xxxxx

# abc 디렉토리 업로드
aws s3 cp ./abc s3://bill-xxxxx/abc --recursive
# 또는 
aws s3 sync ./abc s3://bill-xxxxx/abc

# abc 디렉토리 삭제
aws s3 rm s3://bill-xxxxx/abc --recursive

AWS ingress-nginx controller https 사용하기

# 참고로 로드 밸런서 타입에 따라 각각 가능한 프로토콜이 정해져 있다.
# Application Load Balancer(ALB) - HTTP, HTTPS
# CLASSIC(Elastic) LOAD BALANCER (CLB/ELB) - HTTP, HTTPS
# Network Load Balancer(NLB) - TCP, TLS, UDP

# ALB + ALB ingress controller 를 사용한 경우
# ingress annotation 으로 인증서 AWS Certificate Manager(ACM)에 등록된
# 인증서를 arn 으로 사용할 수 있다.
kubectl edit ingress my-test-ingress -n my-test
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]'
    alb.ingress.kubernetes.io/actions.ssl-redirect: '{"Type": "redirect", "RedirectConfig": { "Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_301"}}'
    alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:ap-northeast-2:11111:certificate/11111

# NLB + ingress-nginx controller 를 사용하는 경우
# ingress tls -> secretName 때문에 인증서를 k8s secret 리소스로 등록해야 된다.
# 발급된 인증서를 사용하는 경우
# aws private CA(인증서) 를 사용하는 경우 ACM 콘솔이나 다음 명령으로 내보낼 수 있다.
# 참고로 public CA 는 내보내기가 안된다.
aws acm export-certificate \
--certificate-arn arn:aws:acm:ap-northeast-2:11111:certificate/11111 \
--passphrase fileb://path-to-passphrase-file  \
| jq -r '"\(.Certificate)\(.CertificateChain)\(.PrivateKey)"'

# 테스트로 사용하는 경우
# self-signed certificate 인증서 생성해 사용
# cert 파일 생성
rm -rf tls.crt tls.key
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=*.dev.ysoftman-aws.io/O=*.dev.ysoftman-aws.io"

# 이제 secret 리소스 생성하자
kubectl create secret tls dev-ysoftman-aws --key tls.key --cert tls.crt -n my-test

# ingress -> tls -> secretName 명시
kubectl edit ingress my-test-ingress -n my-test
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
... 생략 ...
spec:
  tls:
  - hosts:
    - my-test-api.dev.ysoftman-aws.io
    secretName: dev-ysoftman-aws
... 생략 ...

# ELB + ingress-nginx controller 를 설치하면 alb 처럼 annotation 으로 public CA 를 사용할 수 있다.
# 참고 https://kubernetes.github.io/ingress-nginx/deploy/#aws -> deploy-tls-termination.yaml
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.46.0/deploy/static/provider/aws/deploy-tls-termination.yaml

# 다운로드된 파일에서 XXX 부분을 변경 한다.
proxy-real-ip-cidr: XXX.XXX.XXX/XX  -> VPC CIDR 명시

# ingress-nginx-controller service 에서 public CA arn 을 사용할 수 있다.
arn:aws:acm:us-west-2:XXXXXXXX:certificate/XXXXXX-XXXXXXX-XXXXXXX-XXXXXXXX -> 발급받은 인증서 명시
# 적용
kubectl apply -f deploy-tls-termination.yaml

# external-ip 가 새로 만들어지기 때문에 route53 에서 기존 레코드 바인딩을 수정하자.
kubectl get svc --namespace ingress-nginx

# 이제 NLB 처럼 ingress tls,secret 설정 없이, https 를 사용할 수 있다.

k8s dashboard 사용하기

# k8s dashboard 사용하기
# 참고로 oauth proxy + github 인증으로 로컬 proxy 서버없이 접근하는 방법도 있다.

# k8s dashboard 설치
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.5/aio/deploy/recommended.yaml

# 로컬에서 k8s api 연결 할 수 있는 프록시 서버 띄우기
kubectl proxy

# 로컬 URL 로 dashboard 접근
http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/

#####

# 위의 로컬 프록시는 매번 로컬에 프록시 서버를 띄워 접속해야 돼서 불편하다.
# 고정 도메인으로 접속 하기

# 방법1 - ingress -> service 80 -> pod 9090 으로 연결하는 방식
# kubernetes-dashboard deployment 설정 변경
# 모든 8443 -> 9090 으로 변경
# scheme HTTPS -> HTTP 로 변경
# container arg 기존 설정은 다 삭제하고 다음으로 변경
- --namespace=kubernetes-dashboard
- --insecure-bind-address=0.0.0.0
- --insecure-port=9090
- --enable-insecure-login

# kubernetes-dashboard service 설정 변경
# 80 -> pod 9090 으로 연결되도록 변경
ports:
- port: 80
  protocol: TCP
  targetPort: 9090

# kubernetes-dashboard ingress 추가
# host 는 ingress-nginx controller 설치시 생성되는 aws loadbalaner 사용
cat << EOF | kubectl apply -f -
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  namespace: kubernetes-dashboard
  name: kubernetes-dashboard-ingress
  annotations:
    kubernetes.io/ingress.class: nginx
    ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/backend-protocol: HTTP
    nginx.ingress.kubernetes.io/cors-allow-origin: '*'
    nginx.ingress.kubernetes.io/enable-cors: "false"
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
    nginx.ingress.kubernetes.io/rewrite-target: /$1
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
  rules:
    - host: aaa111.elb.ap-northeast-2.amazonaws.com
      http:
        paths:
          - path: /dashboard/(.*)
            backend:
              serviceName: kubernetes-dashboard
              servicePort: 80
EOF

# 접속 확인
https://aaa111.elb.ap-northeast-2.amazonaws.com/dashboard/#/login

# 구입한 도메인이 있다면 호스트명 변경해서 사용하자
kubectl edit ingress kubernetes-dashboard-ingress -n kubernetes-dashboard
    # 구입한 도메인을 사용
    - host: lemon-apple.ysoftman.com

# 접속 확인
https://lemon-apple.ysoftman.com/dashboard/#/login

# 참고로 위 설정에서 http 를 사용했으니
# 로컬 kubectl proxy 사용시 다음과 같이 http 를 사용해야 한다.
http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/#/login

# 방법2
# 별도 서버가 있다면 aws 클러스터 접속 설정하고 kubectl proxy 실행한다
nohup kubectl proxy

#####

# dashboard service(admin) account 토큰을 파악해 대시보드 로그인에 사용
kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | rg admin | awk '{print $1}') | rg -i token: | awk '{print $2}' | pbcopy

aws 커스텀 vpc + eks 구성

아래 커스텀 VPC 생성하려면 az 마다 subnet private/public 을 생성하고 각각 설정을 해줘야돼서 힘들다.
eks 기본 설정으로 클러스터를 생성하면 VPC 가 자동생성되니 vpc management console 에서 필요한 부분만 수정하는것이 편하다.

#####

VPC 는 다음과 같은 흐름으로 구성된다.
internetgateway <--> nacl <--> public routing table <--> public subnet
(internetgateway <--> nacl 위줄과 같은 것) <--> private routing table <--> private subnet

[vpc 생성�]
참고로 리전당 VPC 생성은 5개로, VPC 당 서브넷은 200등 각종 개수가 제한되어 있고, 필요시 증가 요청을 해야 한다.
private ip 로 사용할 수 있는 범위는 다음과 같고, 가장 많이 사용할 수 있는 10.0.0.0 대역을 사용�
RFC1918 nameIP address rangeClassful description
24-bit block10.0.0.0 – 10.255.255.255single class A network
20-bit block172.16.0.0 – 172.31.255.25516 contiguous class B networks
16-bit block192.168.0.0 – 192.168.255.255256 contiguous class C networks

생성한 VPC 에서 10.0.0.0/16 으로 65,536 개의 사설 IP 를 사용할 수 있도록 한다.
(cider ip 파악 할때 참고 https://cidr.xyz/)

VPC 생성


[vpc subnet 생성]
하나의 subnet 은 하나의 가용영역(az)에서만 종속된다.
public subnet 생성
a az 에 설정
10.0.0.0/24 로 10.0.0 는 고정 나머지 8bit (256개) IP 구분 가능하도록 한다.

public subnet 은 인터넷과 연결되어야 하기 때문에 '자동 할당 ip' 를 설정해야 한다.

private subnet 생성
b az 에 설정
10.0.1.0/24 로 10.0.1 는 고정 나머지 8bit (256개) IP 구분 가능하도록 한다.



[vpc internet-gateway (igw) 생성]
igw 를 통해서만 인터넷 연결이 가능한다.
igw 생성

igw 생성 후 bill-test vpc 와 연결(igw 는 하나의 VPC 에만 연결할 수 있다.)


[vpc routing table (rt) 생성]
bill-test-public-rt 생성


bill-test-private-rt 생성

bill-test-private-rt -> 서브넷 연결 -> bill-private-subnet1 연결
bill-test-public-rt -> 서브넷 연결 -> bill-public-subnet1 연결(스샷참고)

bill-test-public-rt -> 라우팅 편집 -> bill-test-igw 과 연결 후 라우팅 편집
10.0.0.0/16 은 local 보내고 그외 0.0.0.0/0 (모든) 트랙픽은 인터넷 연결 가능하도록 한다.




[vpc network access control list (nacl) 생성]
인터넷 연결은 위한 bill-test-public-subnet1 만 nacl에 연결한다.

nacl 은 stateless 로 상태를 알 수 없기 때문에 inbound(내부로 들어오는)/outbound(외부로 나가는) 트랙픽에 대해서 모두 설정해줘야 한다.
룰 규칙 번호는 낮은 -> 큰 숫자(최대 32766) 우선순위으로 적용된다.(같은 내용의 규칙이라면 낮은 규칙번호가 적용)
inbound http(80), https(443) 허용하는 새규칙 추가

outbound 는 모든 포트를 허용하는 새규칙 추가


[ekctl 클러스터 생성]
# eksctl 을 사용하면 az3개에 각각 public, private subnet 및 VPC 관련 자동 설정된다.
# fargate(aws 에서 자동 관리해주는 node, daemonset 과 같은 리소스는 지원되지 않는다.) 생성해 사용
eksctl create cluster --name "bill-test" --fargate

# fargate 는fp-default 프로파일로 기본 생성되며
# 포드 선택기 -> 네임스페이스로 설정된 곳에선 fargate 가 사용된다.

# 참고로 nodegroup 도 추가한 경우, fargate 프로파일 네임스페이스에 없는 경우
# ng 로 배포된다. 

# kubectl 연결 설정 추가
aws eks update-kubeconfig --region ap-northeast-2 --name bill-test

# 위에 설정한 VPC bill-test pivate, public 서브넷 ID으로 설정
# cluster.yaml 작성
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
  name: bill-test
  region: ap-northeast-2
vpc:
  id: "vpc-111111" # bill-test vpc id
  subnets:
    public:
      ap-northeast-2a:
          id: "subnet-public11111"
      ap-northeast-2b:
          id: "subnet-public22222"

eksctl create cluster -f cluster.yaml


# 참고로 테스트를 위해 클러스터를 삭제해도 VPC 살아 있다.
eksctl delete cluster --name "bill-test" 

# 리전당 VPC 5개라 다음에 사용하지 않는다면 VPC 도 삭제해준다.
# VPC 는 management console 에석 삭제하면 되는데, 사용중인 곳이 있다면 삭제가 안된다.
# ec2 인스턴스가 autoscaling 그룹으로 지정되어 있어 이것을 먼저 삭제해야 한다.

aws eks 접속 토큰

# aws eks 에 생성한 클러스터 접근시
# 다음과 같이 접속 정보를 설정할 수 있다.
# --kubeconfig 가 없으면 ~/.kube/config 에 추가된다.
aws eks update-kubeconfig --region ap-northeast-2 --name ysoftman-cluster --kubeconfig ~/.kube/aws-ysoftman.yaml

# KUBECONFIG 환경변수 설정
export KUBECONFIG=~/.kube/config:~/.kube/aws-ysoftman.yaml 

# 그런데 실제 접속 정보를 보면 사용자 token: 값 대신
# 다음과 같이 aws eks get-token 으로 새 토큰을 얻는 명령 수행 방식으로 설정된다.
vi ~/.kube/kubeconfig-aws-ysoftman.yaml
... 생략 ...
users:
- name: arn:aws:eks:ap-northeast-2:1111111111:cluster/ysoftman-cluster
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1alpha1
      args:
      - --region
      - ap-northeast-2
      - eks
      - get-token
      - --cluster-name
      - ysoftman-cluster
      command: aws

# 에 보면 get-token 으로 얻은 토큰은 TTL(time to live)이 15분이라
# 15분마다 새 토큰으로 갱신이 필요한데,
# 클라이언트가 kubectl 인 경우 위 설정으로 자동 갱신을 해준다.

# 그런데 서버의 설정에는 고정 토큰 값으로 k8s api 을 사용하고 있다.
# 위의 명령을 다음과 같이 실행해 토큰 값을 파악할 수 있지만,
# 서버 설정 파일에 토큰을 설정하면 15분뒤에는 연결이 끊어진다.
aws --region ap-northeast-2 eks get-token --cluster-name ysoftman-cluster | jq .status.token

# 아래 사이트에서 k8s dashboard 설치시 service-account 를 추가하거나
# 다음과 같이 admin(service-account) 토큰 값을 파악해 
kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin | awk '{print $1}')

# ~/.kube/kubeconfig-aws-ysoftman.yaml 를 다음과 같이 고정하면 만료 없이 사용할 수 있긴 하다.
users:
- name: arn:aws:eks:ap-northeast-2:1111111111:cluster/ysoftman-cluster
  user:
    token: "위에서 파악한 토큰값"


aws eks(k8s) ingress path regex 동작 문제

# aws eks(elastic kubernetes service) 에 ingress controller 를 설치했다.
# nginx-ingress controller 는 아래 설명처럼 nginxinc 를 설치했다. 

# 참고로 nginx controller 는 크게 2종류가 있다.
# kubernetes 에서 개발한 kubernetes/ingress-nginx
# nginx 에서 개발한 nginxinc/kubernetes-ingress with NGINX
# 모두 nginx 기반으로 하고 약간의 차이가 있다.

# ingress 설정은 다음과 같이 (.*) regexp(정규식) 매칭을 사용했다.
# 정규식의 capture group-> 보통 () 로 구분되는 그룹,
# (.*) 하나만 있어 $1 (첫번째 캡쳐 그룹)을 rewrite 대상으로
# 백엔드 서비스에 넘겨주는 의도다. 
# 만약 ysoftman/(/|$)(.*) 라면
# (/|$) -> $1
# (.*) -> $2 
# 가 placeholder 가 된다.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: path-ingress
annotations:
  nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  rules:
  - host: "*.amazonaws.com"
      paths:
      - path: /ysoftman/(.*)
        backend:
          serviceName: ysoftman-service
          servicePort: 8080

# 그런데 다음과 같이 요청하면 nginx 404 응답을 준다.
# 참고로 path를 / 나 /ysoftman 처럼 고정된 경로를 주면 동작한다.
curl "https://aaa-bbb-ccc.amazonaws.com/ysoftman/abc"
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>

# nginx controller pod 의 로그를 보면 다음과 같은 에러 후 404로 응답한다.
/etc/nginx/html/ysoftman/abc" failed (2: No such file or directory)

# nginxinc 문서를 보니 ingress path 에 정규식이 사용되지 않고 있고,
# path 에 정규식을 지원한다고 명시도 되어 있지 않다.
# 대신 nginxinc ingress controller는 virtualServer 라는 새로운 loadbalancer 리소스도 제공하고 여기서 정규식을 사용할 수 있다.

# 그래서 nginxinc nginx-ingress controller 은 모두 삭제
kubectl delete namespace nginx-ingress
kubectl delete clusterrole nginx-ingress
kubectl delete clusterrolebinding nginx-ingress


# kubernetes nginx-ingress controller for AWS 를 설치
# NETWORK LOAD BALANCER (NLB) 설치
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.46.0/deploy/static/provider/aws/deploy.yaml

# 참고로 nginx controller pod 에러가 다음과 같이 발생하면 ingressclass 리소스를 삭제해야 한다.
Invalid IngressClass (Spec.Controller) value "quivr.be/ingress-nginx-controller". Should be "k8s.io/ingress-nginx"
IngressClass with name nginx is not valid for ingress-nginx (invalid Spec.Controller)

# external-ip 확인
# xxxxx-xxxxx.elb.ap-northeast-2.amazonaws.com
kubectl get svc --namespace ingress-nginx

# kubernetes ingress-nginx 는 path 에서 (.*)등의 정규식은 지원하지만
# host 명은 지원하지 않는다.
# 다음과 같이 호스명은 full hostname 으로 명시해야 하고
# path 에는 정규식을 사용할 수 있다.
  rules:
  - host: "xxxxx-xxxxx.elb.ap-northeast-2.amazonaws.com"
      paths:
      - path: /ysoftman/(.*)
        backend:
          serviceName: ysoftman-service
          servicePort: 8080

# 이제 ingress path 정규식에 맞다면 200 OK 응답을 받는다.
curl "https://xxxxx-xxxxx.elb.ap-northeast-2.amazonaws.com/ysoftman/abc"