https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/creating-a-vpc.html
---
AWSTemplateFormatVersion: '2010-09-09'
Description: 'Amazon VPC - Private and Public subnets'
Parameters:
VpcBlock:
Type: String
Default: 10.24.0.0/16
Description: The CIDR range for the VPC. This should be a valid private (RFC 1918) CIDR range.
PublicSubnet01Block:
Type: String
Default: 10.24.1.0/24
Description: CidrBlock for public subnet 01 within the VPC
PublicSubnet02Block:
Type: String
Default: 10.24.2.0/24
Description: CidrBlock for public subnet 02 within the VPC
PrivateSubnet01Block:
Type: String
Default: 10.24.11.0/24
Description: CidrBlock for private subnet 01 within the VPC
PrivateSubnet02Block:
Type: String
Default: 10.24.12.0/24
Description: CidrBlock for private subnet 02 within the VPC
Subnet01AZ:
Type: String
Default: "ap-northeast-2a"
Subnet02AZ:
Type: String
Default: "ap-northeast-2c"
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
-
Label:
default: "Worker Network Configuration"
Parameters:
- VpcBlock
- PublicSubnet01Block
- PublicSubnet02Block
- PrivateSubnet01Block
- PrivateSubnet02Block
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VpcBlock
EnableDnsSupport: true
EnableDnsHostnames: true
Tags:
- Key: Name
Value: !Sub '${AWS::StackName}-vpc'
InternetGateway:
Type: "AWS::EC2::InternetGateway"
VPCGatewayAttachment:
Type: "AWS::EC2::VPCGatewayAttachment"
Properties:
InternetGatewayId: !Ref InternetGateway
VpcId: !Ref VPC
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: Public Subnets
- Key: Network
Value: Public
PrivateRouteTable01:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: Private Subnet AZ1
- Key: Network
Value: Private01
PrivateRouteTable02:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: Private Subnet AZ2
- Key: Network
Value: Private02
PublicRoute:
DependsOn: VPCGatewayAttachment
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
PrivateRoute01:
DependsOn:
- VPCGatewayAttachment
- NatGateway01
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PrivateRouteTable01
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId: !Ref NatGateway01
PrivateRoute02:
DependsOn:
- VPCGatewayAttachment
- NatGateway02
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PrivateRouteTable02
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId: !Ref NatGateway02
NatGateway01:
DependsOn:
- NatGatewayEIP1
- PublicSubnet01
- VPCGatewayAttachment
Type: AWS::EC2::NatGateway
Properties:
AllocationId: !GetAtt 'NatGatewayEIP1.AllocationId'
SubnetId: !Ref PublicSubnet01
Tags:
- Key: Name
Value: !Sub '${AWS::StackName}-NatGatewayAZ1'
NatGateway02:
DependsOn:
- NatGatewayEIP2
- PublicSubnet02
- VPCGatewayAttachment
Type: AWS::EC2::NatGateway
Properties:
AllocationId: !GetAtt 'NatGatewayEIP2.AllocationId'
SubnetId: !Ref PublicSubnet02
Tags:
- Key: Name
Value: !Sub '${AWS::StackName}-NatGatewayAZ2'
NatGatewayEIP1:
DependsOn:
- VPCGatewayAttachment
Type: 'AWS::EC2::EIP'
Properties:
Domain: vpc
NatGatewayEIP2:
DependsOn:
- VPCGatewayAttachment
Type: 'AWS::EC2::EIP'
Properties:
Domain: vpc
PublicSubnet01:
Type: AWS::EC2::Subnet
Metadata:
Comment: Subnet 01
Properties:
MapPublicIpOnLaunch: true
AvailabilityZone: !Ref Subnet01AZ
CidrBlock:
Ref: PublicSubnet01Block
VpcId:
Ref: VPC
Tags:
- Key: Name
Value: !Sub "${AWS::StackName}-pub-sn-a"
- Key: kubernetes.io/role/elb
Value: 1
- Key: kubernetes.io/cluster/worldskills-cloud-cluster
Value: shared
PublicSubnet02:
Type: AWS::EC2::Subnet
Metadata:
Comment: Subnet 02
Properties:
MapPublicIpOnLaunch: true
AvailabilityZone: !Ref Subnet02AZ
CidrBlock:
Ref: PublicSubnet02Block
VpcId:
Ref: VPC
Tags:
- Key: Name
Value: !Sub "${AWS::StackName}-pub-sn-c"
- Key: kubernetes.io/role/elb
Value: 1
- Key: kubernetes.io/cluster/worldskills-cloud-cluster
Value: shared
PrivateSubnet01:
Type: AWS::EC2::Subnet
Metadata:
Comment: Subnet 03
Properties:
AvailabilityZone: !Ref Subnet01AZ
CidrBlock:
Ref: PrivateSubnet01Block
VpcId:
Ref: VPC
Tags:
- Key: Name
Value: !Sub "${AWS::StackName}-priv-sn-a"
- Key: kubernetes.io/role/internal-elb
Value: 1
- Key: kubernetes.io/cluster/worldskills-cloud-cluster
Value: shared
PrivateSubnet02:
Type: AWS::EC2::Subnet
Metadata:
Comment: Private Subnet 02
Properties:
AvailabilityZone: !Ref Subnet02AZ
CidrBlock:
Ref: PrivateSubnet02Block
VpcId:
Ref: VPC
Tags:
- Key: Name
Value: !Sub "${AWS::StackName}-priv-sn-c"
- Key: kubernetes.io/role/internal-elb
Value: 1
- Key: kubernetes.io/cluster/worldskills-cloud-cluster
Value: shared
PublicSubnet01RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet01
RouteTableId: !Ref PublicRouteTable
PublicSubnet02RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet02
RouteTableId: !Ref PublicRouteTable
PrivateSubnet01RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet01
RouteTableId: !Ref PrivateRouteTable01
PrivateSubnet02RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet02
RouteTableId: !Ref PrivateRouteTable02
ControlPlaneSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Cluster communication with worker nodes
VpcId: !Ref VPC
Outputs:
SubnetIds:
Description: Subnets IDs in the VPC
Value: !Join [ ",", [ !Ref PublicSubnet01, !Ref PublicSubnet02, !Ref PrivateSubnet01, !Ref PrivateSubnet02 ] ]
SecurityGroups:
Description: Security group for the cluster control plane communication with worker nodes
Value: !Join [ ",", [ !Ref ControlPlaneSecurityGroup ] ]
VpcId:
Description: The VPC Id
Value: !Ref VPC
CloudFormation으로 생성
eksctl, kubectl 등 cli tool을 사용하기 위해 기본적인 host를 생성합니다
worldskills-cloud-keypair 이름으로 keypair 생성
IAM 2개 생성
curl -o kubectl https://s3.us-west-2.amazonaws.com/amazon-eks/1.22.6/2022-03-09/bin/linux/amd64/kubectl
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
sudo apt update -y; sudo apt install -y jq gettext bash-completion moreutils
echo 'yq() {
docker run --rm -i -v "${PWD}":/workdir mikefarah/yq "$@"
}' | tee -a ~/.bashrc && source ~/.bashrc
sudo apt-get update -y
sudo apt-get remove docker docker-engine docker.io -y
sudo apt-get install docker.io -y
sudo service docker start
sudo chmod 666 /var/run/docker.sock
sudo usermod -a -G docker ubuntu
for command in kubectl jq envsubst aws
do
which $command &>/dev/null && echo "$command in path" || echo "$command NOT FOUND"
done
kubectl completion bash >> ~/.bash_completion
. /etc/profile.d/bash_completion.sh
. ~/.bash_completion
echo 'export LBC_VERSION="v2.4.3"' >> ~/.bash_profile
echo 'export LBC_CHART_VERSION="1.4.4"' >> ~/.bash_profile
. ~/.bash_profile
curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp
sudo mv -v /tmp/eksctl /usr/local/bin
eksctl completion bash >> ~/.bash_completion
. /etc/profile.d/bash_completion.sh
. ~/.bash_completion
eks cluster secret의 KMS 암호화를 위해 kms secret key, alias 를 만들고 저장해 놓습니다
aws kms create-alias --alias-name alias/worldskills-cloud-cluster-sec --target-key-id $(aws kms create-key --query KeyMetadata.Arn --output text)
CMK의 ARN을 검색하여 create cluster 명령에 입력하겠습니다.
export MASTER_ARN=$(aws kms describe-key --key-id alias/worldskills-cloud-cluster-sec --query KeyMetadata.Arn --output text)
나중에 KMS 키를 쉽게 참조할 수 있도록 MASTER_ARN 환경 변수를 설정했습니다.
이제 MASTER_ARN 환경 변수를 bash_profile에 저장해 보겠습니다.
echo "export MASTER_ARN=${MASTER_ARN}" | tee -a ~/.bash_profile
아래 파일로 cluster config을 설정합니다. (cat 활용 안하고 vi, nano 등 에디터에서 작업시 MASTER ARN을 직접 입력하세요)
# worldskills-cloud-cluster.yaml
---
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: worldskills-cloud-cluster
region: ap-northeast-2
version: "1.22"
# Override your vpc & network setup setting here
vpc:
id: "vpc-08d68fcabb001d14d"
subnets:
public:
ap-northeast-2a:
id: "subnet-0c0d9af436e4d5903"
ap-northeast-2c:
id: "subnet-05f4ab817d0bc5050"
private:
ap-northeast-2a:
id: "subnet-0ad72deba691923d3"
ap-northeast-2c:
id: "subnet-0129657f028a9cc1f"
sharedNodeSecurityGroup: sg-0343f6faaa06865e5
fargateProfiles:
- name: worldskills-cloud-ws-profile
selectors:
- namespace: worldskills-ns
managedNodeGroups:
- name: worldskills-cloud-node
instanceType: t3.medium
cloudWatch:
clusterLogging:
enableTypes: ["*"]
secretsEncryption:
keyARN: ${MASTER_ARN}
eksctl 명령어를 통해 cluster를 생성!
생성 시간은 평균 10분입니다.
vpc endpoint 생성시 이거 참고
https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/cluster-endpoint.html
https://eksctl.io/usage/vpc-cluster-access/
kubectl create namespace worldskills-ns
위 명령어를 통해 worldskills-ns 네임스페이스를 만들어줍니다
콘솔에서 eks 리소스를 보려면 인증이 필요한데 eksctl 이용 시 생성이 IAM mapping이 안되어 있습니다.
원래 IAM User를 생성해서 사용시 rolearn에 user name을 넣으면 되나, eksctl의 --arn parameter는 user, role arn만 지원하기 때문에 두번째 명령어에서 직접 편집해주어야 한다.
eksctl create iamidentitymapping --cluster eksworkshop-eksctl --arn ${rolearn} --group system:masters --username admin
kubectl edit configmap aws-auth -n kube-system
위 명령어 실행 시 aws-auth의 yaml 설정 파일 편집기로 넘어간다.
편집기에서 아래의 내용으로 편집하면 콘솔에서도 볼 수 있다!
mapUsers: |
- groups:
- system:masters
userarn: arn:aws:iam:230564760920:root
이전에 로드 밸런서를 생성한 적이 없는 AWS 계정에서는 ELB에 대한 서비스 역할이 아직 존재하지 않을 수 있습니다.
아래 명령어를 통해 역할을 확인하고 누락된 경우 만들 수 있습니다.
aws iam get-role --role-name "AWSServiceRoleForElasticLoadBalancing" || aws iam create-service-linked-role --aws-service-name "elasticloadbalancing.amazonaws.com"
https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/aws-load-balancer-controller.html
https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/alb-ingress.html
https://zigispace.net/1160
eksworkshop
https://www.eksworkshop.com/beginner/130_exposing-service/exposing/
https://www.eksworkshop.com/beginner/130_exposing-service/ingress_controller_alb/
aws elb ingress controller
https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.4/
S3 bucket을 생성합니다
Bucket Name: worldskills-cloud-s3-AWS Account ID
kubernetes deployment의 배포 파일입니다.
s3 권한을 위해 aws access_key를 secret으로 만들어 env로 넣었습니다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: worldskills-cloud-deployment
labels:
app: app-container
spec:
replicas: 1
selector:
matchLabels:
app: app-container
template:
metadata:
labels:
app: app-container
spec:
containers:
- image: pjm1024cl/ws-image:latest
imagePullPolicy: IfNotPresent
name: app-container
env:
- name: s3_bucket
value: "worldskills-cloud-s3-230564760920" # bucket name
- name: AWS_ACCESS_KEY_ID
valueFrom:
secretKeyRef:
name: worldskills-cloud-app-secret-s3
key: aws-access-key-id
- name: AWS_SECRET_ACCESS_KEY
valueFrom:
secretKeyRef:
name: worldskills-cloud-app-secret-s3
key: aws-secret-access-key
ports:
- containerPort: 3000
protocol: TCP
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
readinessProbe:
httpGet:
path: /health
port: 3000
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 10
periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
name: app-service
spec:
selector:
app: app-container
type: LoadBalancer
ports:
- protocol: TCP
port: 80
targetPort: 3000
secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: worldskills-cloud-app-secret-s3
type: Opaque
data:
aws-access-key-id: <key-id>
aws-secret-access-key: <access-key>
파일 생성 후
kubectl apply -f <file.yaml> -n
명령오로 생성해줍니다
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.5.0/components.yaml
위 명령어로 hpa를 위한 metrics server를 생성해줍니다
kubectl get apiservice v1beta1.metrics.k8s.io -o json | jq '.status'
위 명령어로 잘 설치되었는지 확인합니다.
kubectl autoscale deployment worldskills-cloud-deployment `#The target average CPU utilization` \
--cpu-percent=20 \
--min=1 `#The lower limit for the number of pods that can be set by the autoscaler` \
--max=20 `#The upper limit for the number of pods that can be set by the autoscaler`
위 명령어로 hpa를 등록합니다
aws autoscaling \ describe-auto-scaling-groups \ --query "AutoScalingGroups[? Tags[? (Key=='eks:cluster-name') && Value=='worldskills-cloud-cluster']].[AutoScalingGroupName, MinSize, MaxSize,DesiredCapacity]" \ --output table
위 명령어로 node group auto scailing 현재 상황을 확인합니다.
# we need the ASG name
export ASG_NAME=$(aws autoscaling describe-auto-scaling-groups --query "AutoScalingGroups[? Tags[? (Key=='eks:cluster-name') && Value=='worldskills-cloud-cluster']].AutoScalingGroupName" --output text)
# increase max capacity up to 4
aws autoscaling \
update-auto-scaling-group \
--auto-scaling-group-name ${ASG_NAME} \
--min-size 3 \
--desired-capacity 3 \
--max-size 4
# Check new values
aws autoscaling \
describe-auto-scaling-groups \
--query "AutoScalingGroups[? Tags[? (Key=='eks:cluster-name') && Value=='worldskills-cloud-cluster']].[AutoScalingGroupName, MinSize, MaxSize,DesiredCapacity]" \
--output table
위 명령어로 auto scaling min, max, desire capacity를 설정합니다
Amazon EKS 클러스터의 서비스 계정에 대한 IAM 역할을 사용하여 IAM 역할을 다음과 연결할 수 있습니다.Kubernetes 서비스 계정. 그런 다음 이 서비스 계정은 해당 서비스 계정을 사용하는 모든 포드의 컨테이너에 AWS 권한을 제공할 수 있습니다. 이 기능을 사용하면 해당 노드의 포드가 AWS API를 호출할 수 있도록 더 이상 노드 IAM 역할에 확장된 권한을 제공할 필요가 없습니다.
클러스터의 서비스 계정에 대한 IAM 역할 활성화
eksctl utils associate-iam-oidc-provider \
--cluster worldskills-cloud-cluster \
--region ap-northeast-2 \
--approve
CA 포드가 자동 크기 조정 그룹과 상호 작용하도록 허용하는 서비스 계정에 대한 IAM 정책 생성.
cat <<EoF > ~/k8s-asg-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"autoscaling:DescribeAutoScalingGroups",
"autoscaling:DescribeAutoScalingInstances",
"autoscaling:DescribeLaunchConfigurations",
"autoscaling:DescribeTags",
"autoscaling:SetDesiredCapacity",
"autoscaling:TerminateInstanceInAutoScalingGroup",
"ec2:DescribeLaunchTemplateVersions"
],
"Resource": "*",
"Effect": "Allow"
}
]
}
EoF
aws iam create-policy \
--policy-name k8s-asg-policy \
--policy-document file://~/k8s-asg-policy.json
마지막으로 kube-system 네임스페이스에서 cluster-autoscaler 서비스 계정에 대한 IAM 역할을 생성합니다.
eksctl create iamserviceaccount \
--name cluster-autoscaler \
--namespace kube-system \
--cluster eksworkshop-eksctl \
--attach-policy-arn "arn:aws:iam::${ACCOUNT_ID}:policy/k8s-asg-policy" \
--approve \
--override-existing-serviceaccounts
IAM 역할의 ARN이 있는 서비스 계정에 주석이 추가되었는지 확인합니다.
kubectl -n kube-system describe sa cluster-autoscaler
curl -o cluster-autoscaler-autodiscover.yaml https://raw.githubusercontent.com/kubernetes/autoscaler/master/cluster-autoscaler/cloudprovider/aws/examples/cluster-autoscaler-autodiscover.yaml
<YOUR CLUSTER NAME>
을 클러스터 이름으로 바꿉니다. 또한 사용자 환경에 따라 결정되는 대로 cpu
및 memory
값을 바꾸는 것이 좋습니다.kubectl apply -f cluster-autoscaler-autodiscover.yaml
CA가 자체 포드가 실행 중인 노드를 제거하는 것을 방지하기 위해 cluster-autoscaler.kubernetes.io/safe-to-evict
다음 명령을 사용하여 배포에 주석을 추가합니다.
kubectl -n kube-system \
annotate deployment.apps/cluster-autoscaler \
cluster-autoscaler.kubernetes.io/safe-to-evict="false"
마지막으로 자동 크기 조정 이미지를 업데이트하겠습니다.
# we need to retrieve the latest docker image available for our EKS version
export K8S_VERSION=$(kubectl version --short | grep 'Server Version:' | sed 's/[^0-9.]*\([0-9.]*\).*/\1/' | cut -d. -f1,2)
export AUTOSCALER_VERSION=$(curl -s "https://api.github.com/repos/kubernetes/autoscaler/releases" | grep '"tag_name":' | sed -s 's/.*-\([0-9][0-9\.]*\).*/\1/' | grep -m1 ${K8S_VERSION})
kubectl -n kube-system \
set image deployment.apps/cluster-autoscaler \
cluster-autoscaler=us.gcr.io/k8s-artifacts-prod/autoscaling/cluster-autoscaler:v${AUTOSCALER_VERSION}
ClusterName='worldskills-cloud-cluster'
LogRegion='ap-northeast-2'
FluentBitHttpPort='2020'
FluentBitReadFromHead='Off'
[[ ${FluentBitReadFromHead} = 'On' ]] && FluentBitReadFromTail='Off'|| FluentBitReadFromTail='On'
[[ -z ${FluentBitHttpPort} ]] && FluentBitHttpServer='Off' || FluentBitHttpServer='On'
curl https://raw.githubusercontent.com/aws-samples/amazon-cloudwatch-container-insights/latest/k8s-deployment-manifest-templates/deployment-mode/daemonset/container-insights-monitoring/quickstart/cwagent-fluent-bit-quickstart.yaml | sed 's/{{cluster_name}}/'${ClusterName}'/;s/{{region_name}}/'${LogRegion}'/;s/{{http_server_toggle}}/"'${FluentBitHttpServer}'"/;s/{{http_server_port}}/"'${FluentBitHttpPort}'"/;s/{{read_from_head}}/"'${FluentBitReadFromHead}'"/;s/{{read_from_tail}}/"'${FluentBitReadFromTail}'"/' | kubectl apply -f -
https://www.eksworkshop.com/beginner/091_iam-groups/intro/
IAM OIDC 연결하고,
IAM Role 생성 후
kubernetes Role, Group 생성
eksctl로 iamidentitymapping, => 결국은 aws-auth configmap 수정임 직접도 가능
https://aws.amazon.com/ko/premiumsupport/knowledge-center/eks-iam-permissions-namespaces/
https://aws.amazon.com/ko/premiumsupport/knowledge-center/amazon-eks-cluster-access/