<1> EKS 생성 1 비용 많이 나올수 있으니 노드 1개만 설치하자. 수정하자. 2 # YAML 파일 다운로드 curl -O https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/K8S/eks-oneclick6.yaml # CloudFormation 스택 배포 예시) aws cloudformation deploy --template-file eks-oneclick6.yaml --stack-name myeks --parameter-overrides KeyName=kp-gasida SgIngressSshCidr=$(curl -s ipinfo.io/ip)/32 MyIamUserAccessKeyID=AKIA5... MyIamUserSecretAccessKey='CVNa2...' ClusterBaseName=myeks --region ap-northeast-2 # CloudFormation 스택 배포 완료 후 작업용 EC2 IP 출력 aws cloudformation describe-stacks --stack-name myeks --query 'Stacks[*].Outputs[0].OutputValue' --output text # 작업용 EC2 SSH 접속 ssh -i ~/.ssh/kp-gasida.pem ec2-user@$(aws cloudformation describe-stacks --stack-name myeks --query 'Stacks[*].Outputs[0].OutputValue' --output text) 3 # default 네임스페이스 적용 kubectl ns default # (옵션) context 이름 변경 NICK=<각자 자신의 닉네임> NICK= kubectl ctx kubectl config rename-context admin@myeks.ap-northeast-2.eksctl.io $NICK # ExternalDNS MyDomain=<자신의 도메인> echo "export MyDomain=<자신의 도메인>" >> /etc/profile MyDomain= echo "export MyDomain=gasida.link" >> /etc/profile MyDnzHostedZoneId=$(aws route53 list-hosted-zones-by-name --dns-name "${MyDomain}." --query "HostedZones[0].Id" --output text) echo $MyDomain, $MyDnzHostedZoneId curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/aews/externaldns.yaml MyDomain=$MyDomain MyDnzHostedZoneId=$MyDnzHostedZoneId envsubst < externaldns.yaml | kubectl apply -f - # AWS LB Controller helm repo add eks https://aws.github.io/eks-charts helm repo update helm install aws-load-balancer-controller eks/aws-load-balancer-controller -n kube-system --set clusterName=$CLUSTER_NAME \ --set serviceAccount.create=false --set serviceAccount.name=aws-load-balancer-controller # 노드 IP 확인 및 PrivateIP 변수 지정 N1=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2a -o jsonpath={.items[0].status.addresses[0].address}) N2=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2b -o jsonpath={.items[0].status.addresses[0].address}) N3=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2c -o jsonpath={.items[0].status.addresses[0].address}) echo "export N1=$N1" >> /etc/profile echo "export N2=$N2" >> /etc/profile echo "export N3=$N3" >> /etc/profile echo $N1, $N2, $N3 # 노드 보안그룹 ID 확인 NGSGID=$(aws ec2 describe-security-groups --filters Name=group-name,Values='*ng1*' --query "SecurityGroups[*].[GroupId]" --output text) aws ec2 authorize-security-group-ingress --group-id $NGSGID --protocol '-1' --cidr 192.168.1.0/24 # 워커 노드 SSH 접속 for node in $N1 $N2 $N3; do ssh ec2-user@$node hostname; done <2> ACK 개요 1 aws 서비스 리소스를 k8s 에서 직접 정의하고 사용 할 수 있음 쿠버네티스에는 익숙한데 AWS에 익숙한 엔지니어가 있는경우. 사용자는 kubectl (쿠버네티스 api) 를 사용하여 AWS S3 버킷을 생성 할 수 있다. 쿠버네티스 api 는 ack-s3-controller 에 요청을 전달하고, ack-s3-controller(IRSA)이 AWS S3 API 를 통해 버킷을 생성하게 됩니다 아직은 상용으로 사용하기에는 20% 부족하다. 참고로 테스트해보자. 2 동작 https://aws-controllers-k8s.github.io/community/docs/community/how-it-works/ 각 서비스별 컨트롤러가 필요하다. ack-s3-controller , ack-rds-controller 등이 설정을 반영하여 AWS에 배포한다. 권한 IRSA는 필요하다. 3 지원되는 AWS 서비스들 GA된 서비스들만 이용하세요. 17개. 프리뷰(평가판)은 조금 있다가. 10개. https://aws-controllers-k8s.github.io/community/docs/community/services/ 4 순서? 컨트롤러 생성 - AWS 현재 상태가 원하는 상태와 같은지 확인하는 컨트롤러. IRSA 권한 생성 S3 리소스 생성 <3> ACK S3 Controller 설치 with Helm 1 자료 https://aws-controllers-k8s.github.io/community/docs/user-docs/install/ 최근 버전으로 저장소에서 다운 받아서 진행하는 것이다. https://gallery.ecr.aws/aws-controllers-k8s https://github.com/aws-controllers-k8s/s3-controller 2 # 서비스명 변수 지정 export SERVICE=s3 # helm 차트 다운로드 기본 버지니아라 다운받아 수정함. #aws ecr-public get-login-password --region us-east-1 | helm registry login --username AWS --password-stdin public.ecr.aws export RELEASE_VERSION=$(curl -sL https://api.github.com/repos/aws-controllers-k8s/$SERVICE-controller/releases/latest | grep '"tag_name":' | cut -d'"' -f4 | cut -c 2-) helm pull oci://public.ecr.aws/aws-controllers-k8s/$SERVICE-chart --version=$RELEASE_VERSION tar xzvf $SERVICE-chart-$RELEASE_VERSION.tgz # helm chart 확인 tree ~/$SERVICE-chart # ACK S3 Controller 설치 네임스페이스를 ack-sysetm에 설치한다. export ACK_SYSTEM_NAMESPACE=ack-system export AWS_REGION=ap-northeast-2 helm install --create-namespace -n $ACK_SYSTEM_NAMESPACE ack-$SERVICE-controller --set aws.region="$AWS_REGION" ~/$SERVICE-chart 3 # 설치 확인 helm list --namespace $ACK_SYSTEM_NAMESPACE kubectl -n ack-system get pods crd도 설치된다. kubectl get crd | grep $SERVICE buckets.s3.services.k8s.aws 2022-04-24T13:24:00Z kubectl get all -n ack-system kubectl get-all -n ack-system kubectl describe sa -n ack-system ack-s3-controller 권한이 없다. IRSA권한 추가 하자. <4> IRSA 생성 - 권장 정책 AmazonS3FullAccess 1 서비스 별로 필요한 권장 정책이 있다. https://aws-controllers-k8s.github.io/community/docs/user-docs/irsa/ 2 # Create an iamserviceaccount - AWS IAM role bound to a Kubernetes service account eksctl create iamserviceaccount \ --name ack-$SERVICE-controller \ --namespace ack-system \ --cluster $CLUSTER_NAME \ --attach-policy-arn $(aws iam list-policies --query 'Policies[?PolicyName==`AmazonS3FullAccess`].Arn' --output text) \ --override-existing-serviceaccounts --approve // --override-existing-serviceaccounts 기존에 서비스 어카운트가 있더라도 겹쳐쓴다. 3 # 확인 >> 웹 관리 콘솔에서 CloudFormation Stack >> IAM Role 확인 eksctl get iamserviceaccount --cluster $CLUSTER_NAME # Inspecting the newly created Kubernetes Service Account, we can see the role we want it to assume in our pod. kubectl get sa -n ack-system kubectl describe sa ack-$SERVICE-controller -n ack-system 4 # Restart ACK service controller deployment using the following commands. kubectl -n ack-system rollout restart deploy ack-$SERVICE-controller-$SERVICE-chart # IRSA 적용으로 Env, Volume 추가 확인 kubectl describe pod -n ack-system -l k8s-app=$SERVICE-chart <5> S3 버킷 생성, 업데이트, 삭제 1 # [터미널1] 모니터링 watch -d aws s3 ls 2 # S3 버킷 생성을 위한 설정 파일 생성 // 어카운트 id 를 가지고 작업 한다. export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text) export BUCKET_NAME=my-ack-s3-bucket-$AWS_ACCOUNT_ID 3 read -r -d '' BUCKET_MANIFEST < bucket.yaml cat bucket.yaml | yh 4 # S3 버킷 생성 aws s3 ls kubectl create -f bucket.yaml bucket.s3.services.k8s.aws/my-ack-s3-bucket- created 5 // 콘솔에서 확인하자. 6 # S3 버킷 확인 aws s3 ls kubectl get buckets kubectl describe bucket/$BUCKET_NAME | head -6 Name: my-ack-s3-bucket- Namespace: default Labels: Annotations: API Version: s3.services.k8s.aws/v1alpha1 Kind: Bucket aws s3 ls | grep $BUCKET_NAME 2022-04-24 18:02:07 my-ack-s3-bucket- 7 # S3 버킷 업데이트 : 태그 정보 입력 read -r -d '' BUCKET_MANIFEST < bucket.yaml 8 // 콘솔에서 태그 확인 // CLI로 태그 확인 # S3 버킷 설정 업데이트 실행 : kubectl apply -f bucket.yaml # S3 버킷 업데이트 확인 tag를 추가한다. 오류 나오는건 무시해도 된다. 콘솔에서 태그 추가 확인하자. kubectl describe bucket/$BUCKET_NAME | grep Spec: -A5 Spec: Name: my-ack-s3-bucket- Tagging: Tag Set: Key: myTagKey Value: myTagValue 9 kubectl로 삭제 ~~ # S3 버킷 삭제 kubectl delete -f bucket.yaml # verify the bucket no longer exists kubectl get bucket/$BUCKET_NAME aws s3 ls | grep $BUCKET_NAME 10 삭제 https://aws-controllers-k8s.github.io/community/docs/user-docs/cleanup/ # helm uninstall export SERVICE=s3 helm uninstall -n $ACK_SYSTEM_NAMESPACE ack-$SERVICE-controller # ACK S3 Controller 관련 crd 삭제 kubectl delete -f ~/$SERVICE-chart/crds # IRSA 삭제 eksctl delete iamserviceaccount --cluster myeks --name ack-$SERVICE-controller --namespace ack-system # namespace 삭제 >> ACK 모든 실습 후 삭제 kubectl delete namespace $ACK_K8S_NAMESPACE <6> ACK EC2-Controller 설치 컨트롤러 생성 IRSA 권한 생성 VPC, Subnet 생성 1 ACK EC2-Controller 설치 with Helm https://aws-controllers-k8s.github.io/community/docs/tutorials/ec2-example/ https://gallery.ecr.aws/aws-controllers-k8s/ec2-chart https://github.com/aws-controllers-k8s/ec2-controller 2 # 서비스명 변수 지정 및 helm 차트 다운로드 export SERVICE=ec2 export RELEASE_VERSION=$(curl -sL https://api.github.com/repos/aws-controllers-k8s/$SERVICE-controller/releases/latest | grep '"tag_name":' | cut -d'"' -f4 | cut -c 2-) helm pull oci://public.ecr.aws/aws-controllers-k8s/$SERVICE-chart --version=$RELEASE_VERSION tar xzvf $SERVICE-chart-$RELEASE_VERSION.tgz # helm chart 확인 tree ~/$SERVICE-chart # ACK EC2-Controller 설치 export ACK_SYSTEM_NAMESPACE=ack-system export AWS_REGION=ap-northeast-2 helm install -n $ACK_SYSTEM_NAMESPACE ack-$SERVICE-controller --set aws.region="$AWS_REGION" ~/$SERVICE-chart # 설치 확인 helm list --namespace $ACK_SYSTEM_NAMESPACE kubectl -n $ACK_SYSTEM_NAMESPACE get pods -l "app.kubernetes.io/instance=ack-$SERVICE-controller" kubectl get crd | grep $SERVICE dhcpoptions.ec2.services.k8s.aws 2023-05-30T12:45:13Z elasticipaddresses.ec2.services.k8s.aws 2023-05-30T12:45:13Z instances.ec2.services.k8s.aws 2023-05-30T12:45:13Z internetgateways.ec2.services.k8s.aws 2023-05-30T12:45:13Z natgateways.ec2.services.k8s.aws 2023-05-30T12:45:13Z routetables.ec2.services.k8s.aws 2023-05-30T12:45:13Z securitygroups.ec2.services.k8s.aws 2023-05-30T12:45:13Z subnets.ec2.services.k8s.aws 2023-05-30T12:45:13Z transitgateways.ec2.services.k8s.aws 2023-05-30T12:45:13Z vpcendpoints.ec2.services.k8s.aws 2023-05-30T12:45:13Z vpcs.ec2.services.k8s.aws 2023-05-30T12:45:13Z 3 IRSA 설정 : 권장 정책 AmazonEC2FullAccess https://github.com/aws-controllers-k8s/ec2-controller/blob/main/config/iam/recommended-policy-arn 4 # Create an iamserviceaccount - AWS IAM role bound to a Kubernetes service account eksctl create iamserviceaccount \ --name ack-$SERVICE-controller \ --namespace $ACK_SYSTEM_NAMESPACE \ --cluster $CLUSTER_NAME \ --attach-policy-arn $(aws iam list-policies --query 'Policies[?PolicyName==`AmazonEC2FullAccess`].Arn' --output text) \ --override-existing-serviceaccounts --approve # 확인 >> 웹 관리 콘솔에서 CloudFormation Stack >> IAM Role 확인 eksctl get iamserviceaccount --cluster $CLUSTER_NAME # Inspecting the newly created Kubernetes Service Account, we can see the role we want it to assume in our pod. kubectl get sa -n $ACK_SYSTEM_NAMESPACE kubectl describe sa ack-$SERVICE-controller -n $ACK_SYSTEM_NAMESPACE # Restart ACK service controller deployment using the following commands. kubectl -n $ACK_SYSTEM_NAMESPACE rollout restart deploy ack-$SERVICE-controller-$SERVICE-chart # IRSA 적용으로 Env, Volume 추가 확인 kubectl describe pod -n $ACK_SYSTEM_NAMESPACE -l k8s-app=$SERVICE-chart ... <7> VPC, Subnet 생성 및 삭제 1 https://aws-controllers-k8s.github.io/community/docs/tutorials/ec2-example/#optional-create-a-vpc-and-subnet 2 # [터미널1] 모니터링 while true; do aws ec2 describe-vpcs --query 'Vpcs[*].{VPCId:VpcId, CidrBlock:CidrBlock}' --output text; echo "-----"; sleep 1; done 3 # VPC 생성 cat < vpc.yaml apiVersion: ec2.services.k8s.aws/v1alpha1 kind: VPC metadata: name: vpc-tutorial-test spec: cidrBlocks: - 10.0.0.0/16 enableDNSSupport: true enableDNSHostnames: true EOF kubectl apply -f vpc.yaml vpc.ec2.services.k8s.aws/vpc-tutorial-test created 4 # VPC 생성 확인 kubectl get vpcs kubectl describe vpcs aws ec2 describe-vpcs --query 'Vpcs[*].{VPCId:VpcId, CidrBlock:CidrBlock}' --output text 5 # [터미널1] 모니터링 VPCID=$(kubectl get vpcs vpc-tutorial-test -o jsonpath={.status.vpcID}) while true; do aws ec2 describe-subnets --filters "Name=vpc-id,Values=$VPCID" --query 'Subnets[*].{SubnetId:SubnetId, CidrBlock:CidrBlock}' --output text; echo "-----"; sleep 1 ; done 6 # 서브넷 생성 VPCID=$(kubectl get vpcs vpc-tutorial-test -o jsonpath={.status.vpcID}) cat < subnet.yaml apiVersion: ec2.services.k8s.aws/v1alpha1 kind: Subnet metadata: name: subnet-tutorial-test spec: cidrBlock: 10.0.0.0/20 vpcID: $VPCID EOF kubectl apply -f subnet.yaml 7 # 서브넷 생성 확인 kubectl get subnets kubectl describe subnets aws ec2 describe-subnets --filters "Name=vpc-id,Values=$VPCID" --query 'Subnets[*].{SubnetId:SubnetId, CidrBlock:CidrBlock}' --output text 8 # 리소스 삭제 kubectl delete -f subnet.yaml && kubectl delete -f vpc.yaml <8> Create a VPC Workflow 1 Create a VPC Workflow : VPC, Subnet, SG, RT, EIP, IGW, NATGW, Instance 생성 https://aws-controllers-k8s.github.io/community/docs/tutorials/ec2-example/#create-a-vpc-workflow - 1 VPC - 1 Instance - 1 Internet Gateway - 1 NAT Gateways - 1 Elastic IPs - 2 Route Tables - 2 Subnets (1 Public; 1 Private) - 1 Security Group 2 # VPC 환경 생성 kubectl apply -f vpc-workflow.yaml # [터미널1] NATGW 생성 완료 후 tutorial-private-route-table-az1 라우팅 테이블 ID가 확인되고 그후 tutorial-private-subnet1 서브넷ID가 확인됨 > 5분 정도 시간 소요 watch -d kubectl get routetables,subnet # VPC 환경 생성 확인 kubectl describe vpcs kubectl describe internetgateways kubectl describe routetables kubectl describe natgateways kubectl describe elasticipaddresses kubectl describe securitygroups # 배포 도중 2개의 서브넷 상태 정보 비교 해보자 kubectl describe subnets ... Status: Conditions: Last Transition Time: 2023-06-04T02:15:25Z Message: Reference resolution failed Reason: the referenced resource is not synced yet. resource:RouteTable, namespace:default, name:tutorial-private-route-table-az1 Status: Unknown Type: ACK.ReferencesResolved ... Status: Ack Resource Metadata: Arn: arn:aws:ec2:ap-northeast-2:911283464785:subnet/subnet-0f5ae09e5d680030a Owner Account ID: 911283464785 Region: ap-northeast-2 Available IP Address Count: 4091 Conditions: Last Transition Time: 2023-06-04T02:14:45Z Status: True Type: ACK.ReferencesResolved Last Transition Time: 2023-06-04T02:14:45Z Message: Resource synced successfully Reason: Status: True Type: ACK.ResourceSynced ... https://www.eksworkshop.com/docs/automation/controlplanes/ack/provision-resources/ <9>퍼블릭 서브넷에 인스턴스 생성 1 # public 서브넷 ID 확인 PUBSUB1=$(kubectl get subnets tutorial-public-subnet1 -o jsonpath={.status.subnetID}) echo $PUBSUB1 # 보안그룹 ID 확인 TSG=$(kubectl get securitygroups tutorial-security-group -o jsonpath={.status.id}) echo $TSG 2 # Amazon Linux 2 최신 AMI ID 확인 AL2AMI=$(aws ec2 describe-images --owners amazon --filters "Name=name,Values=amzn2-ami-hvm-2.0.*-x86_64-gp2" --query 'Images[0].ImageId' --output text) echo $AL2AMI # 각자 자신의 SSH 키페어 이름 변수 지정 MYKEYPAIR=<각자 자신의 SSH 키페어 이름> MYKEYPAIR=kp-gasida # 변수 확인 > 특히 서브넷 ID가 확인되었는지 꼭 확인하자! echo $PUBSUB1 , $TSG , $AL2AMI , $MYKEYPAIR 3 # [터미널1] 모니터링 while true; do aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,PrivateIPAdd:PrivateIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output table; date ; sleep 1 ; done 4 # public 서브넷에 인스턴스 생성 cat < tutorial-bastion-host.yaml apiVersion: ec2.services.k8s.aws/v1alpha1 kind: Instance metadata: name: tutorial-bastion-host spec: imageID: $AL2AMI # AL2 AMI ID - ap-northeast-2 instanceType: t3.medium subnetID: $PUBSUB1 securityGroupIDs: - $TSG keyName: $MYKEYPAIR tags: - key: producer value: ack EOF kubectl apply -f tutorial-bastion-host.yaml # 인스턴스 생성 확인 kubectl get instance kubectl describe instance aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,PrivateIPAdd:PrivateIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output table 5 public 서브넷에 인스턴스 접속 ssh -i <자신의 키페어파일> ec2-user@ ------ # public 서브넷에 인스턴스 접속 후 외부 인터넷 통신 여부 확인 ping -c 2 8.8.8.8 exit --- 6 // egress 룰이 없어서 만든다. 보안 그룹 정책 수정 : egress 규칙 추가 cat < modify-sg.yaml apiVersion: ec2.services.k8s.aws/v1alpha1 kind: SecurityGroup metadata: name: tutorial-security-group spec: description: "ack security group" name: tutorial-sg vpcRef: from: name: tutorial-vpc ingressRules: - ipProtocol: tcp fromPort: 22 toPort: 22 ipRanges: - cidrIP: "0.0.0.0/0" description: "ingress" egressRules: - ipProtocol: '-1' ipRanges: - cidrIP: "0.0.0.0/0" description: "egress" EOF kubectl apply -f modify-sg.yaml # 변경 확인 >> 보안그룹에 아웃바운드 규칙 확인 kubectl logs -n $ACK_SYSTEM_NAMESPACE -l k8s-app=ec2-chart -f 7 public 서브넷에 인스턴스 접속 후 외부 인터넷 통신 확인 ssh -i <자신의 키페어파일> ec2-user@ ------ # public 서브넷에 인스턴스 접속 후 외부 인터넷 통신 여부 확인 ping -c 10 8.8.8.8 curl ipinfo.io/ip ; echo # 출력되는 공인IP는 무엇인가? exit --- <10> 프라이빗 서브넷에 인스턴스 생성 1 # private 서브넷 ID 확인 >> NATGW 생성 완료 후 RT/SubnetID가 확인되어 다소 시간 필요함 PRISUB1=$(kubectl get subnets tutorial-private-subnet1 -o jsonpath={.status.subnetID}) echo $PRISUB1 # 변수 확인 > 특히 private 서브넷 ID가 확인되었는지 꼭 확인하자! echo $PRISUB1 , $TSG , $AL2AMI , $MYKEYPAIR 2 # private 서브넷에 인스턴스 생성 cat < tutorial-instance-private.yaml apiVersion: ec2.services.k8s.aws/v1alpha1 kind: Instance metadata: name: tutorial-instance-private spec: imageID: $AL2AMI # AL2 AMI ID - ap-northeast-2 instanceType: t3.medium subnetID: $PRISUB1 securityGroupIDs: - $TSG keyName: $MYKEYPAIR tags: - key: producer value: ack EOF kubectl apply -f tutorial-instance-private.yaml 3 # 인스턴스 생성 확인 kubectl get instance kubectl describe instance aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,PrivateIPAdd:PrivateIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output table 4 public 서브넷에 인스턴스에 SSH 터널링 설정 ssh -i <자신의 키페어파일> -L <자신의 임의 로컬 포트>::22 ec2-user@ -v ssh -i ~/.ssh/kp-gasida.pem -L 9999:10.0.129.196:22 ec2-user@3.34.96.12 -v --- 접속 후 그냥 두기 -L은 로컬이다. --- 5 자신의 임의 로컬 포트로 SSH 접속 시, private 서브넷에 인스턴스 접속됨 ssh -i <자신의 키페어파일> -p <자신의 임의 로컬 포트> ec2-user@localhost ssh -i ~/.ssh/kp-gasida.pem -p 9999 ec2-user@localhost --- # IP 및 네트워크 정보 확인 ip -c addr sudo ss -tnp ping -c 2 8.8.8.8 curl ipinfo.io/ip ; echo # 출력되는 공인IP는 무엇인가? exit NAT IP --- 6 실습 후 리소스 삭제 kubectl delete -f tutorial-bastion-host.yaml && kubectl delete -f tutorial-instance-private.yaml kubectl delete -f vpc-workflow.yaml # vpc 관련 모든 리소스들 삭제에는 다소 시간이 소요됨 <11> RDS 1 지원 엔진 - Aurora(MySQL & PostgreSQL), RDS for PostgreSQL, RDS for MySQL, RDS for MariaDB, RDS for Oracle, RDS for SQL Server 2 ACK RDS Controller 설치 with Helm https://aws-controllers-k8s.github.io/community/docs/tutorials/rds-example/ https://gallery.ecr.aws/aws-controllers-k8s https://github.com/aws-controllers-k8s/rds-controller 3 # 서비스명 변수 지정 및 helm 차트 다운로드 export SERVICE=rds export RELEASE_VERSION=$(curl -sL https://api.github.com/repos/aws-controllers-k8s/$SERVICE-controller/releases/latest | grep '"tag_name":' | cut -d'"' -f4 | cut -c 2-) helm pull oci://public.ecr.aws/aws-controllers-k8s/$SERVICE-chart --version=$RELEASE_VERSION tar xzvf $SERVICE-chart-$RELEASE_VERSION.tgz # helm chart 확인 tree ~/$SERVICE-chart # ACK EC2-Controller 설치 export ACK_SYSTEM_NAMESPACE=ack-system export AWS_REGION=ap-northeast-2 helm install -n $ACK_SYSTEM_NAMESPACE ack-$SERVICE-controller --set aws.region="$AWS_REGION" ~/$SERVICE-chart # 설치 확인 helm list --namespace $ACK_SYSTEM_NAMESPACE kubectl -n $ACK_SYSTEM_NAMESPACE get pods -l "app.kubernetes.io/instance=ack-$SERVICE-controller" kubectl get crd | grep $SERVICE 4 IRSA 설정 : 권장 정책 AmazonRDSFullAccess https://github.com/aws-controllers-k8s/rds-controller/blob/main/config/iam/recommended-policy-arn # Create an iamserviceaccount - AWS IAM role bound to a Kubernetes service account eksctl create iamserviceaccount \ --name ack-$SERVICE-controller \ --namespace $ACK_SYSTEM_NAMESPACE \ --cluster $CLUSTER_NAME \ --attach-policy-arn $(aws iam list-policies --query 'Policies[?PolicyName==`AmazonRDSFullAccess`].Arn' --output text) \ --override-existing-serviceaccounts --approve # 확인 >> 웹 관리 콘솔에서 CloudFormation Stack >> IAM Role 확인 eksctl get iamserviceaccount --cluster $CLUSTER_NAME # Inspecting the newly created Kubernetes Service Account, we can see the role we want it to assume in our pod. kubectl get sa -n $ACK_SYSTEM_NAMESPACE kubectl describe sa ack-$SERVICE-controller -n $ACK_SYSTEM_NAMESPACE # Restart ACK service controller deployment using the following commands. kubectl -n $ACK_SYSTEM_NAMESPACE rollout restart deploy ack-$SERVICE-controller-$SERVICE-chart # IRSA 적용으로 Env, Volume 추가 확인 kubectl describe pod -n $ACK_SYSTEM_NAMESPACE -l k8s-app=$SERVICE-chart ... <12> AWS RDS for MariaDB 생성 및 삭제 1 https://aws-controllers-k8s.github.io/community/docs/tutorials/rds-example/ 2 # DB 암호를 위한 secret 생성 RDS_INSTANCE_NAME="" RDS_INSTANCE_PASSWORD="" RDS_INSTANCE_NAME=myrds RDS_INSTANCE_PASSWORD=qwe12345 kubectl create secret generic "${RDS_INSTANCE_NAME}-password" --from-literal=password="${RDS_INSTANCE_PASSWORD}" # 확인 kubectl get secret $RDS_INSTANCE_NAME-password 3 # [터미널1] 모니터링 RDS_INSTANCE_NAME=myrds watch -d "kubectl describe dbinstance "${RDS_INSTANCE_NAME}" | grep 'Db Instance Status'" 4 # RDS 배포 생성 : 15분 이내 시간 소요 >> 보안그룹, 서브넷 등 필요한 옵션들은 추가해서 설정해보자! cat < rds-mariadb.yaml apiVersion: rds.services.k8s.aws/v1alpha1 kind: DBInstance metadata: name: "${RDS_INSTANCE_NAME}" spec: allocatedStorage: 20 dbInstanceClass: db.t4g.micro dbInstanceIdentifier: "${RDS_INSTANCE_NAME}" engine: mariadb engineVersion: "10.6" masterUsername: "admin" masterUserPassword: namespace: default name: "${RDS_INSTANCE_NAME}-password" key: password EOF kubectl apply -f rds-mariadb.yaml 5 # 생성 확인 kubectl get dbinstances ${RDS_INSTANCE_NAME} kubectl describe dbinstance "${RDS_INSTANCE_NAME}" aws rds describe-db-instances --db-instance-identifier $RDS_INSTANCE_NAME | jq kubectl describe dbinstance "${RDS_INSTANCE_NAME}" | grep 'Db Instance Status' Db Instance Status: creating kubectl describe dbinstance "${RDS_INSTANCE_NAME}" | grep 'Db Instance Status' Db Instance Status: backing-up kubectl describe dbinstance "${RDS_INSTANCE_NAME}" | grep 'Db Instance Status' Db Instance Status: available # 생성 완료 대기 : for 지정 상태가 완료되면 정상 종료됨 kubectl wait dbinstances ${RDS_INSTANCE_NAME} --for=condition=ACK.ResourceSynced --timeout=15m dbinstance.rds.services.k8s.aws/myrds condition met console에 접속해 확인. 디폴트는 퍼블릭에서 허용하도록 되어 있다. 6 MariaDB 접속 https://aws-controllers-k8s.github.io/community/docs/tutorials/rds-example/#connect-to-database-instances https://www.eksworkshop.com/docs/automation/controlplanes/ack/configure-application/ 7 앤드포인트를 알아야 한다. 파드가 접속해야 한다. fieldexport 로 앤드포인트를 확인한다~~ fieldexport 생성 : # 상태 정보 확인 : address 와 port 정보 kubectl get dbinstances myrds -o jsonpath={.status.endpoint} | jq { "address": "myrds.cb79jlim4dyq.ap-northeast-2.rds.amazonaws.com", "hostedZoneID": "ZLA2NUCOLGUUR", "port": 3306 } # 상태 정보 확인 : masterUsername 확인 kubectl get dbinstances myrds -o jsonpath={.spec.masterUsername} ; echo # 컨피그맵 확인 kubectl get cm myrds-conn-cm -o yaml | kubectl neat | yh apiVersion: v1 data: default.myrds-host: myrds.cb79jlim4dyq.ap-northeast-2.rds.amazonaws.com default.myrds-port: "3306" default.myrds-user: admin kind: ConfigMap metadata: name: myrds-conn-cm namespace: default # fieldexport 정보 확인 kubectl get crd | grep fieldexport kubectl get fieldexport kubectl get fieldexport myrds-host -o yaml | k neat | yh 8 RDS 사용하는 파드를 생성 환경변수를 알수 있다. APP_NAMESPACE=default cat < rds-pods.yaml apiVersion: v1 kind: Pod metadata: name: app namespace: ${APP_NAMESPACE} spec: containers: - image: busybox name: myapp command: - sleep - "3600" imagePullPolicy: IfNotPresent env: - name: DBHOST valueFrom: configMapKeyRef: name: ${RDS_INSTANCE_CONN_CM} key: "${APP_NAMESPACE}.${RDS_INSTANCE_NAME}-host" - name: DBPORT valueFrom: configMapKeyRef: name: ${RDS_INSTANCE_CONN_CM} key: "${APP_NAMESPACE}.${RDS_INSTANCE_NAME}-port" - name: DBUSER valueFrom: configMapKeyRef: name: ${RDS_INSTANCE_CONN_CM} key: "${APP_NAMESPACE}.${RDS_INSTANCE_NAME}-user" - name: DBPASSWORD valueFrom: secretKeyRef: name: "${RDS_INSTANCE_NAME}-password" key: password EOF kubectl apply -f rds-pods.yaml 9 # 생성 확인 kubectl get pod app # 파드의 환경 변수 확인 kubectl exec -it app -- env | grep DB DBHOST=myrds.cb79jlim4dyq.ap-northeast-2.rds.amazonaws.com DBPORT=3306 DBUSER=admin DBPASSWORD=qwe12345 프로그램짤때 엔드포인트를 확인할수 있다. 10 RDS 의 master 암호를 변경해보고 확인! 11 # [터미널] watch -d "kubectl get dbinstance; echo; kubectl get cm myrds-conn-cm -o yaml | kubectl neat" # DB 식별자를 업데이트 >> 어떤 현상이 발생하는가? kubectl patch dbinstance myrds --type=merge -p '{"spec":{"dbInstanceIdentifier":"studyend"}}' // 콘솔에서 변경해도 상태 정보가 깨진다. 관리가 안된다. # 확인 kubectl get dbinstance myrds kubectl describe dbinstance myrds 12 최종적으로 변경된 status 정보가 반영되었는지 확인해보자 # 상태 정보 확인 : address 변경 확인! kubectl get dbinstances myrds -o jsonpath={.status.endpoint} | jq { "address": "studyend.cb79jlim4dyq.ap-northeast-2.rds.amazonaws.com", "hostedZoneID": "ZLA2NUCOLGUUR", "port": 3306 } # 파드의 환경 변수 확인 >> 파드의 경우 환경 변수 env로 정보를 주입했기 때문에 변경된 정보를 확인 할 수 없다 kubectl exec -it app -- env | grep DB DBHOST=myrds.cb79jlim4dyq.ap-northeast-2.rds.amazonaws.com DBPORT=3306 DBUSER=admin DBPASSWORD=qwe12345 13 # 파드 삭제 후 재생성 후 확인 kubectl delete pod app && kubectl apply -f rds-pods.yaml # 파드의 환경 변수 확인 >> 변경 정보 확인! # 즉 deployments, daemonsets, statefulsets 의 경우 rollout 으로 env 변경 적용을 할 수 는 있겠다! kubectl exec -it app -- env | grep DB DBHOST=studyend.cb79jlim4dyq.ap-northeast-2.rds.amazonaws.com DBPORT=3306 DBUSER=admin DBPASSWORD=qwe12345 14 RDS 삭제 > AWS 웹 관리콘솔에서 myrds 는 직접 삭제 할 것 # 파드 삭제 kubectl delete pod app # RDS 삭제 kubectl delete -f rds-mariadb.yaml2