클라우드 엔지니어 꿈나무
Load Balancer를 사용하여 도메인 연결 본문
awscli 설치
apt update -y
apt install -y awscli
인스턴스 이미지 : ami-0454bb2fefc7de534
aws configure 로 aws와 연결
aws configure
kubernetes 설치
* bastion cli 및 aws console 쿠버네티스 1.27로 버전 맞추었으나 오류 발생
* aws console 1.27으로 유지, bastion 은 1.23.6 으로 설치 후, 정상 가동
aws 측에서는 버전은 위 아래 1까지 적용 가능하다고 했으나 1.27에서 1.27 가동 불가, 1.26 가동 불가
1.23.6으로 설치 후, 가동
쿠버네티스 다운로드
curl -LO "https://storage.googleapis.com/kubernetes-release/release/v1.23.6/bin/linux/amd64/kubectl"
kubectl 권한 부여 및 실행 경로 이동
chmod +x ./kubectl && mv ./kubectl /usr/local/bin # ( = install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl)
eks 생성 tf
locals {
cluster_name = var.cluster_name
cluster_version = var.cluster_version
region = "ap-northeast-2"
vpc_id = var.vpc_id
public_subnets = var.public_subnets
private_subnets = var.private_subnets
tag = {
Environment = "test"
Terraform = "true"
}
}
module "eks" {
# https://registry.terraform.io/modules/terraform-aws-modules/eks/aws/latest
source = "terraform-aws-modules/eks/aws"
version = "18.31.0"
# Cluster Name Setting
cluster_name = local.cluster_name
cluster_version = local.cluster_version
# Cluster Endpoint Setting
cluster_endpoint_private_access = true
cluster_endpoint_public_access = true
# Network Setting
vpc_id = local.vpc_id
subnet_ids = local.private_subnets
# IRSA Enable / OIDC 구성
enable_irsa = true
node_security_group_additional_rules = {
ingress_nodes_karpenter_port = {
description = "Cluster API to Node group for Karpenter webhook"
protocol = "tcp"
from_port = 8443
to_port = 8443
type = "ingress"
source_cluster_security_group = true
}
}
# Tag Node Security Group
node_security_group_tags = {
"karpenter.sh/discovery" = local.cluster_name
}
eks_managed_node_groups = {
initial = {
instance_types = ["t3a.medium"]
create_security_group = false
create_launch_template = false # do not remove
launch_template_name = "" # do not remove
min_size = 2
max_size = 3
desired_size = 2
iam_role_additional_policies = [
# Required by Karpenter
"arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
]
tags = {
Name = "example-node-group"
}
}
}
# console identity mapping (AWS user)
# eks configmap aws-auth에 콘솔 사용자 혹은 역할을 등록
manage_aws_auth_configmap = true
aws_auth_users = [
{
userarn = "arn:aws:iam::<계정번호>:user/ <user ID> "
username = "<user ID>"
groups = ["system:masters"]
},
]
aws_auth_accounts = [
"<계정 번호>"
]
}
// 프라이빗 서브넷 태그
resource "aws_ec2_tag" "private_subnet_tag" {
for_each = toset(local.private_subnets)
resource_id = each.value
key = "kubernetes.io/role/internal-elb"
value = "1"
}
resource "aws_ec2_tag" "private_subnet_cluster_tag" {
for_each = toset(local.private_subnets)
resource_id = each.value
key = "kubernetes.io/cluster/${local.cluster_name}"
value = "owned"
}
resource "aws_ec2_tag" "private_subnet_karpenter_tag" {
for_each = toset(local.private_subnets)
resource_id = each.value
key = "karpenter.sh/discovery/${local.cluster_name}"
value = local.cluster_name
}
// 퍼블릭 서브넷 태그
resource "aws_ec2_tag" "public_subnet_tag" {
for_each = toset(local.public_subnets)
resource_id = each.value
key = "kubernetes.io/role/elb"
value = "1"
}
*나의 경우 bastion 인스턴스 생성 후, xshell 에서 작업을 했기 때문에 eks 보안 그룹에 443 bastion을 인바운드 규칙으로 추가했다.
aws eks 와 연결
aws eks update-kubeconfig --region <Region명> --name<EKS Cluster명>
연결 확인
eksctl 설치하여 진행할 경우, 하기 접은 글 참고
eksctl 설치
<<참고>>
https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/aws-load-balancer-controller.html
curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp
mv /tmp/eksctl /usr/local/bin
eksctl version
tf 파일로 역할 생성하였으니 정책 부분 생략
IAM 정책 생성
aws iam create-policy --policy-name AWSLoadBalancerControllerIAMPolicy --policy-document file://iam_policy.json
클러스터에서 IAM OIDC(OpenID Connect) 공급자 연결
eksctl utils associate-iam-oidc-provider --region=ap-northeast-2 --cluster=test-eks-cluster --approve => Amazon EKS (Elastic Kubernetes Service)
IAM 역할 생성
eksctl create iamserviceaccount \
--cluster=my-cluster \
--namespace=kube-system \
--name=aws-load-balancer-controller \
--role-name AmazonEKSLoadBalancerControllerRole \
--attach-policy-arn=arn:aws:iam::111122223333:policy/AWSLoadBalancerControllerIAMPolicy \
--approve
오토스케일용 karpenter.tf
module "karpenter" {
source = "terraform-aws-modules/eks/aws//modules/karpenter"
version = "18.31.0"
cluster_name = module.eks.cluster_name
irsa_oidc_provider_arn = module.eks.oidc_provider_arn
irsa_namespace_service_accounts = ["karpenter:karpenter"]
create_iam_role = false
iam_role_arn = module.eks.eks_managed_node_groups["initial"].iam_role_arn
}
resource "helm_release" "karpenter" {
namespace = "karpenter"
create_namespace = true
name = "karpenter"
repository = "oci://public.ecr.aws/karpenter"
repository_username = data.aws_ecrpublic_authorization_token.token.user_name
repository_password = data.aws_ecrpublic_authorization_token.token.password
chart = "karpenter"
version = "v0.20.0"
set {
name = "settings.aws.clusterName"
value = module.eks.cluster_name
}
set {
name = "settings.aws.clusterEndpoint"
value = module.eks.cluster_endpoint
}
set {
name = "serviceAccount.annotations.eks\\.amazonaws\\.com/role-arn"
value = module.karpenter.irsa_arn
}
set {
name = "settings.aws.defaultInstanceProfile"
value = module.karpenter.instance_profile_name
}
set {
name = "settings.aws.interruptionQueueName"
value = module.karpenter.queue_name
}
}
alb 역할 생성 (접은 글)
module "iam_assumable_role_alb_controller" {
source = "terraform-aws-modules/iam/aws//modules/iam-assumable-role-with-oidc"
version = "5.0.0"
create_role = true
role_name = "${local.cluster_name}-alb-controller"
role_description = "Used by AWS Load Balancer Controller for EKS"
provider_url = module.eks.cluster_oidc_issuer_url
oidc_fully_qualified_subjects = ["system:serviceaccount:kube-system:aws-load-balancer-controller"]
}
data "http" "iam_policy" {
url = "https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.4.1/docs/install/iam_policy.json"
}
resource "aws_iam_role_policy" "controller" {
name_prefix = "AWSLoadBalancerControllerIAMPolicy"
policy = data.http.iam_policy.response_body
role = module.iam_assumable_role_alb_controller.iam_role_name
}
data "aws_iam_policy_document" "additional_permissions" {
statement {
effect = "Allow"
actions = [
"elasticloadbalancing:AddTags",
]
resources = ["*"]
}
}
resource "aws_iam_policy" "additional_permissions" {
name = "AdditionalPermissions"
description = "Additional permissions for AWS Load Balancer Controller"
policy = data.aws_iam_policy_document.additional_permissions.json
}
resource "aws_iam_role_policy_attachment" "additional_permissions" {
role = module.iam_assumable_role_alb_controller.iam_role_name
policy_arn = aws_iam_policy.additional_permissions.arn
}
Cert manager 구성
Cert manager 가 없다면 AWS Load Balancer Controller에서 Certificate를 배포하지 못함
curl -Lo cert-manager.yaml https://github.com/jetstack/cert-manager/releases/download/v1.12.3/cert-manager.yaml
# cert-manager를 설치한 다음 인증서 구성을 Webhook
#선택 사항
sed -i.bak -e 's|quay.io|<계정 번호>.dkr.ecr.region-code.amazonaws.com|' ./cert-manager.yaml
#자체 레지스트리 이름으로 세 개의 이미지에 대한 매니페스트 quay.io 로 변경 (개인 리포지토리의 이름이 원본 리포지토리와 동일할 떄
kubectl apply -f cert-manager.yaml
ALB Controller 설치
해당 부분에 ServiceAccount 까지 표시되어 있음
curl -Lo v2_5_4_full.yaml https://github.com/kubernetes-sigs/aws-load-balancer-controller/releases/download/v2.5.4/v2_5_4_full.yaml
#선택 사항 이 부분을 제거하지 않으면 이전 단계에서 서비스 계정에 작성한 필수 주석이 덮어씌어지고, 제거하면 컨트롤러를 삭제할 경우 이전 단계에서 생성한 서비스 계정 유지
sed -i.bak -e 's|your-cluster-name|<클러스터명>|' ./v2_5_4_full.yaml
해당 yaml 파일에 클러스터 명 수정
(서비스 어카운트까지 생성되는 yaml 코드)
만약 service account 를 먼저 생성해준 상태라면 ServiceAccount 부분 삭제
kubectl apply -f v2_5_4_full.yaml
provisioner.yaml
vi provisioner.yaml
apiVersion: karpenter.sh/v1alpha5
kind: Provisioner
metadata:
name: service
spec:
taints:
- key: service
value: "true"
effect: NoSchedule
labels:
nodeType: service-2023
requirements:
- key: "node.kubernetes.io/instance-type"
operator: In
values: ["t3.medium","t3a.medium"]
- key: "topology.kubernetes.io/zone"
operator: In
values: [ "ap-northeast-2a", "ap-northeast-2c" ]
- key: "karpenter.sh/capacity-type"
operator: In
values: ["on-demand"]
providerRef:
name: service-lt
ttlSecondsAfterEmpty: 30
ttlSecondsUntilExpired: 1209600
---
apiVersion: karpenter.k8s.aws/v1alpha1
kind: AWSNodeTemplate
metadata:
name: service-lt
spec:
subnetSelector:
karpenter.sh/discovery/kang-cluster: '*'
securityGroupSelector:
aws:eks:cluster-name: kang-cluster # do not change
tags:
karpenter.sh/discovery: kang-cluster
kubectl apply -f provisioner.tf
namespace.yaml 생성 (=kubectl create ns test-ingress-alb)
vi namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: flask
kubectl apply -f namespace.yaml
deployment.yaml 생성
vi deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: flask
name: flask
spec:
revisionHistoryLimit: 5
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25%
maxUnavailable: 0%
selector:
matchLabels:
app.kubernetes.io/name: flask
template:
metadata:
labels:
app.kubernetes.io/name: flask
spec:
containers:
- name: flask
image: "끌고 올 이미지 주소"
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 8080
protocol: TCP
nodeSelector:
nodeType: service-2023
tolerations:
- key: service
operator: "Equal"
value: "true"
effect: "NoSchedule"
kubectl apply -f deployment.yaml
service.yaml
vi service.yaml
apiVersion: v1
kind: Service
metadata:
namespace: flask
name: flask
spec:
type: ClusterIP
ports:
- port: 8080
targetPort: 8080
protocol: TCP
name: http
selector:
app.kubernetes.io/name: flask
kubectl apply -f service.yaml
test-ingress-alb.yaml 생성
vi test-ingress-alb.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
namespace: flask
name: flask
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/load-balancer-name: kang-alb
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]'
alb.ingress.kubernetes.io/healthcheck-path: /
alb.ingress.kubernetes.io/subnets: subnet-####,subnet-#### #퍼블릭 서브넷
alb.ingress.kubernetes.io/certificate-arn: <acm 주소>
spec:
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: flask
port:
number: 8080
tls:
- hosts:
- # 실제 도메인으로 교체
secretName: # 임의의 시크릿 이름으로 지정
로드밸런서 생성 확인
호스팅 영역 생성
Route53 연결
레코드 이름 앞에 www 입력 필수
도메인 이름 입력
연결 확인
트러블 슈팅
alb-controller 생성 후, pod 조회하면 하기와 같이 CrashLoopBackOff 에러 출력
최신 버전인 v2_5_4_full.yaml 다운받아 실행하니 정상 작동
'AWS' 카테고리의 다른 글
AWS Cloudfront 사용하여 route53과 연결하기 (0) | 2024.01.03 |
---|---|
EKS autoscaling 생성 w/helm (0) | 2024.01.03 |
AWS OPENVPN 설치 (0) | 2023.12.25 |
AWS ECR 생성 및 레포지토리에 이미지 업로드 (0) | 2023.12.10 |
AWS OpenVPN 으로 로그인 (0) | 2023.12.10 |