diff --git a/SUMMARY.md b/SUMMARY.md index fe1ff84..0c1cbff 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -2,6 +2,9 @@ * [Introduction](README.md) * Chapters - * [VM과 컨테이너](posts/week1/container.md) - * [Kubernetes란](posts/week2/About_Kubernetes.md) + * [VM과 컨테이너](posts/chapter1/container.md) + * [Kubernetes란](posts/chapter2/About_Kubernetes.md) + * [Terrform으로 EKS 생성하기](posts/chapter3/EKS_Terraform.md) + * [Kuberentes 기본 리소스](posts/chapter4/Kuberentes_Resources.md) + diff --git a/posts/week1/container.md b/posts/chapter1/container.md similarity index 100% rename from posts/week1/container.md rename to posts/chapter1/container.md diff --git a/posts/week1/images/image.png b/posts/chapter1/images/image.png similarity index 100% rename from posts/week1/images/image.png rename to posts/chapter1/images/image.png diff --git a/posts/week1/images/image1.png b/posts/chapter1/images/image1.png similarity index 100% rename from posts/week1/images/image1.png rename to posts/chapter1/images/image1.png diff --git a/posts/week1/images/image2.png b/posts/chapter1/images/image2.png similarity index 100% rename from posts/week1/images/image2.png rename to posts/chapter1/images/image2.png diff --git a/posts/week1/images/image3.png b/posts/chapter1/images/image3.png similarity index 100% rename from posts/week1/images/image3.png rename to posts/chapter1/images/image3.png diff --git a/posts/week1/images/image4.png b/posts/chapter1/images/image4.png similarity index 100% rename from posts/week1/images/image4.png rename to posts/chapter1/images/image4.png diff --git a/posts/week1/images/image5.png b/posts/chapter1/images/image5.png similarity index 100% rename from posts/week1/images/image5.png rename to posts/chapter1/images/image5.png diff --git a/posts/week2/About_Kubernetes.md b/posts/chapter2/About_Kubernetes.md similarity index 100% rename from posts/week2/About_Kubernetes.md rename to posts/chapter2/About_Kubernetes.md diff --git a/posts/week2/images/cni.png b/posts/chapter2/images/cni.png similarity index 100% rename from posts/week2/images/cni.png rename to posts/chapter2/images/cni.png diff --git a/posts/week2/images/crio.png b/posts/chapter2/images/crio.png similarity index 100% rename from posts/week2/images/crio.png rename to posts/chapter2/images/crio.png diff --git a/posts/week2/images/csi.png b/posts/chapter2/images/csi.png similarity index 100% rename from posts/week2/images/csi.png rename to posts/chapter2/images/csi.png diff --git a/posts/week2/images/image.png b/posts/chapter2/images/image.png similarity index 100% rename from posts/week2/images/image.png rename to posts/chapter2/images/image.png diff --git a/posts/week2/images/image1.png b/posts/chapter2/images/image1.png similarity index 100% rename from posts/week2/images/image1.png rename to posts/chapter2/images/image1.png diff --git a/posts/week2/images/image2.png b/posts/chapter2/images/image2.png similarity index 100% rename from posts/week2/images/image2.png rename to posts/chapter2/images/image2.png diff --git a/posts/chapter3/EKS_Terraform.md b/posts/chapter3/EKS_Terraform.md new file mode 100644 index 0000000..fd81703 --- /dev/null +++ b/posts/chapter3/EKS_Terraform.md @@ -0,0 +1,216 @@ +# EKS with Terraform + +EKS IAC + +스터디에서 사용할 EKS 코드를 IaC 인 Terraform으로 생성하는 과정입니다. + +## EKS + +![[https://awskoreamarketingasset.s3.amazonaws.com/2022 Summit/pdf/T14S4_Amazon EKS 마이그레이션 요점 정리.pdf](https://awskoreamarketingasset.s3.amazonaws.com/2022%20Summit/pdf/T14S4_Amazon%20EKS%20%EB%A7%88%EC%9D%B4%EA%B7%B8%EB%A0%88%EC%9D%B4%EC%85%98%20%EC%9A%94%EC%A0%90%20%EC%A0%95%EB%A6%AC.pdf)](images/image.png) + +[https://awskoreamarketingasset.s3.amazonaws.com/2022 Summit/pdf/T14S4_Amazon EKS 마이그레이션 요점 정리.pdf](https://awskoreamarketingasset.s3.amazonaws.com/2022%20Summit/pdf/T14S4_Amazon%20EKS%20%EB%A7%88%EC%9D%B4%EA%B7%B8%EB%A0%88%EC%9D%B4%EC%85%98%20%EC%9A%94%EC%A0%90%20%EC%A0%95%EB%A6%AC.pdf) + +![image.png](images/image1.png) + +**Amazon EKS(Amazon Elastic Kubernetes Service)** 는 완전관리형 Kubernetes 서비스입니다. + +- **AWS 관리형 컨트롤 플레인**: + - EKS는 Kubernetes의 핵심 구성요소(ETCD, API 서버 등)를 AWS가 완전 관리 + - 장애 발생 시 자동 복구 & 가용성 + - AWS 서비스(ALB, IAM, CloudWatch 등)와의 통합으로 AWS 생태계 활용 +- **통합 AWS 생태계**: + - AWS IAM과 연동하여 권한 제어 + - 자동 확장(Auto Scaling)이나 로드밸런서(ALB/NLB) 등 연계 + - AWS의 스토리지와 네트워크 통합 +- **IRSA(IAM Roles for Service Accounts)** 등 컨테이너 워크로드에 대한 세분화된 권한 설정 + - 클라우드 리소스별 세부 권한 분리 + +## Terraform + +**Terraform** 은 IaC(Infrastructure as Code)의 표준 도구 + +- **상태 관리(State Management)** + - Terraform은 state 파일을 통해 인프라 상태를 저장, 필요한 변경만 수행 + - 상태 파일은 협업 시에도 유용하며, 인프라의 최신 상태를 추적 가능 +- **복원력** + - Terraform은 선언적 구성을 사용하여 원하는 최종 상태를 정의 + - 상태를 달성하기 위해 필요한 조치를 자동으로 계산 + - 배포 실패 시 롤백을 용이 +- **자동화된 인프라 생성** + - 선언형 코드로 원하는 인프라 상태를 정의해 리소스를 생성/연결/삭제 + - 모든 변경 사항은 명확하게 정의되어 반복 가능한 환경을 제공 + +## Terraform Provisioning & Deletion + +### Terraform Code + +```jsx +# 코드 가져오기 +git clone https://github.com/idoyo7/DKS.git +cd terraform + +# terraform 환경 변수 저장 +export TF_VAR_KeyName=[각자 ssh keypair] +echo $TF_VAR_KeyName + +# 배포 정보 확인하기 +terraform init +terraform plan + +# 10분 후 배포 완료 +terraform apply -auto-approve +``` + +### 배포된 테라폼 정보 확인 + +```jsx +# State 파일 확인 +**terraform state list +~~~** +# 배포된 정보 확인 +**terraform console** +----------------- +data.aws_caller_identity.current +**data.aws_caller_identity.current.arn** +data.aws_eks_cluster.cluster +**data.aws_eks_cluster.cluster.name** +**data.aws_eks_cluster.cluster.version +data.aws_eks_cluster.cluster.access_config** +data.aws_eks_cluster_auth.cluster +kubernetes_service_account.aws_lb_controller +----------------- +terraform state show ... + +# 자세한 정보들 +cat terraform.tfstate | jq +**more terraform.tfstate** +``` + +### Verify + +```jsx +kubectl get node -v=6 + +# EKS 클러스터 인증 정보 업데이트 +CLUSTER_NAME=myeks +aws eks update-kubeconfig --region ap-northeast-2 --name $CLUSTER_NAME +kubectl config rename-context "arn:aws:eks:ap-northeast-2:$(aws sts get-caller-identity --query 'Account' --output text):cluster/$CLUSTER_NAME" "DKS-Labs" + +# config 내용 확인 +kubectl cluster-info +kubectl get node --label-columns=node.kubernetes.io/instance-type,eks.amazonaws.com/capacityType,topology.kubernetes.io/zone +kubectl get pod -A +``` + +### AWS LB Controller + +EKS의 AWS Elastic Load Balancer를 관리 + +컨트롤러는 클러스터 Service 또는 Ingress 정보의 AWS 로드 밸런서를 프로비저닝 + +컨트롤러는 클러스터의 여러 포드를 가리키는 단일 IP 주소 또는 DNS 이름을 생성합니다. + +![[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/aws-load-balancer-controller.html)](images/image2.png) + +[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/aws-load-balancer-controller.html) + +2.5 버전 이상에서는 AWS Load Balancer Controller이(가) **`type: LoadBalancer`**와(과) 함께 Kubernetes 서비스 리소스의 기본 컨트롤러가 되며 각 서비스에 대한 AWS Network Load Balancer(NLB)를 만듭니다. + +Kubernetes **`Ingress`** + +Kubernetes **`Ingress`**을(를) 생성할 때 AWS Load Balancer Controller은(는) AWS Application Load Balancer(ALB)를 생성합니다. + +**AWS LoadBalancer의 동작방식** + +![https://montkim.com/images/AEWS/week2/EKS_Networking/Untitled21.png](https://montkim.com/images/AEWS/week2/EKS_Networking/Untitled21.png) + +[https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.6/how-it-works/](https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.6/how-it-works/) + +- AWS LB는 인스턴스 모드와 IP모드를 지원합니다. +- K8s의 경우 한 인스턴스(노드)에 여러 POD가 있을수 있겠죠. +- 인티스턴스모드의 경우 해당 노드로 트래픽이 도달 후 다시 POD를 찾아서 전달하는 방식으로 이를 위해서는 NodePort를 활용하며, LB에는 노드의 대표 IP가 등록됩니다. +- IP모드의 경우 노드의 대표 IP를 거치지 않고, 바로 Pod의 IP로 트래픽을 전달하며, 따라서 Pod IP가 직접 LB에 등록됩니다. + +```bash +ACCOUNT_ID=$(aws sts get-caller-identity --query 'Account' --output text) +CLUSTER_NAME=myeks + +eksctl create iamserviceaccount --cluster=$CLUSTER_NAME --namespace=kube-system --name=aws-load-balancer-controller --role-name AmazonEKSLoadBalancerControllerRole \ +--attach-policy-arn=arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy --override-existing-serviceaccounts --approve + +helm upgrade --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 + +``` + +### External DNS + +ExternalDNS는 Kubernetes 의 서비스와 도메인(DNS) 이름을 자동으로 연결해주는 도구 + +- Kubernetes 리소스(예: Ingress, Service)를 기반으로 DNS 레코드를 생성, 업데이트, 삭제하는 작업을 자동화합니다. +- Route53, Cloudflare, Azure DNS 등 여러 클라우드 DNS 제공자와 통합됩니다. + +**ExternalDNS의 주요 동작 원리** + +1. Kubernetes 리소스(예: Ingress, Service)를 감시하여 DNS 이름 및 대상 IP를 확인합니다. +2. Kubernetes 리소스와 연결된 DNS 제공자(Route53 등)에 DNS 레코드를 생성하거나 업데이트합니다. +3. DNS 레코드가 Kubernetes 리소스의 상태에 맞춰 자동으로 관리됩니다. +4. 삭제된 리소스는 관련된 DNS 레코드도 제거하여 불필요한 리소스를 최소화합니다. +5. + +**ExternalDNS 설치** + +```bash +# EKS 배포 시 Node IAM Role 설정되어 있음 +# eksctl create cluster ... --external-dns-access ... + +# +MyDomain=montkim.org +# 자신의 Route 53 도메인 ID 조회 및 변수 지정 +MyDnzHostedZoneId=$(aws route53 list-hosted-zones-by-name --dns-name "${MyDomain}." --query "HostedZones[0].Id" --output text) + +# 변수 확인 +echo $MyDomain, $MyDnzHostedZoneId + +# ExternalDNS 배포 +curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/aews/externaldns.yaml +sed -i '' "s/0.13.4/0.14.0/g" externaldns.yaml + +cat externaldns.yaml | yh +MyDomain=$MyDomain MyDnzHostedZoneId=$MyDnzHostedZoneId envsubst < externaldns.yaml | kubectl apply -f - + +``` + +- external dns with helm + + ```bash + # EKS 배포 시 Node IAM Role 설정되어 있음 + # eksctl create cluster ... --external-dns-access ... + DOMAIN="montkim.org" + AWS_REGION="ap-northeast-2" + HOSTED_ZONE_ID=$(aws route53 list-hosted-zones-by-name \ + --dns-name "${DOMAIN}." \ + --query "HostedZones[0].Id" \ + --output text) + + helm upgrade --install external-dns bitnami/external-dns \ + --namespace kube-system \ + --create-namespace \ + --set "provider=aws" \ + --set "aws.zoneType=public" \ + --set "txtOwnerId=externaldns-${HOSTED_ZONE_ID}" \ + --set "domainFilters[0]=$DOMAIN" \ + --set "aws.region=$AWS_REGION" \ + --set "rbac.create=true" \ + --set "serviceAccount.create=true" \ + --set "serviceAccount.name=external-dns" + ``` + + +## 클러스터 삭제 + +생성의 역순인 삭제를 해주도록 하겠습니다 + +```jsx +terraform destroy -auto-approve +``` \ No newline at end of file diff --git a/posts/chapter3/images/image.png b/posts/chapter3/images/image.png new file mode 100644 index 0000000..e29ca6c Binary files /dev/null and b/posts/chapter3/images/image.png differ diff --git a/posts/chapter3/images/image1.png b/posts/chapter3/images/image1.png new file mode 100644 index 0000000..1f57e73 Binary files /dev/null and b/posts/chapter3/images/image1.png differ diff --git a/posts/chapter3/images/image2.png b/posts/chapter3/images/image2.png new file mode 100644 index 0000000..1ed0ad3 Binary files /dev/null and b/posts/chapter3/images/image2.png differ diff --git a/posts/chapter4/Kuberentes_Resources.md b/posts/chapter4/Kuberentes_Resources.md new file mode 100644 index 0000000..9d7e2ac --- /dev/null +++ b/posts/chapter4/Kuberentes_Resources.md @@ -0,0 +1,608 @@ +# 쿠버네티스 기본 리소스 + +기본 리소스를 체계적으로 이해하고 실습할 수 있도록 **컨테이너 -> 파드 -> 워크로드 -> 네트워킹**으로 이어지는 구조를 제안합니다. + +--- + +# **Kubernetes 기본 리소스 계층** + +### **Container** + +- 쿠버네티스에서 실행되는 애플리케이션의 가장 작은 단위. +- 컨테이너 이미지를 기반으로 실행되며, 쿠버네티스가 관리. + +```bash +# Dockerfile 예시 +FROM nginx:alpine +COPY index.html /usr/share/nginx/html +EXPOSE 80 +CMD ["nginx", "-g", "daemon off;"] + +``` + +- 주요 개념: + - **환경변수(Env Vars)**: + - 쿠버네티스 스펙 내 `env` 또는 `envFrom`(ConfigMap, Secret 사용). + - **Command & Args**: + - `spec.containers.command`와 `spec.containers.args`로 command/argument 오버라이드 가능. + - **Security Context**: + - 컨테이너, 파드 레벨에서의 보안 설정(읽기 전용 파일시스템, runAsUser 등). + +### **Pod (파드)** + +- 컨테이너를 묶는 기본 단위. +- 하나의 파드는 **여러 컨테이너**를 포함할 수 있으며, 주로 단일 컨테이너로 구성. +- 주요 개념: + - Multi-Container Pods: + - Init Container: 메인 컨테이너 실행 전 사전 작업(예: config 파일 생성, DB schema init). + - Sidecar Pattern: 로그 수집, 프록시, 모니터링 에이전트 등 보조 역할. + - Volume: + - EmptyDir, HostPath, ConfigMap, Secret, PVC 등 다양한 볼륨 타입. + - ConfigMap/Secret 통해 env 주입. + - Resource Requests & Limits 를 통한 자원 설정. + - Liveness/Readiness Probe 를 이용한 HealthCheck + +### **ReplicaSet** + +- 파드 복제를 통해 안정적인 애플리케이션 가용성을 보장. +- 일반적으로 Deployment, DaemonSet, StatefulSet과 같은 상위 워크로드 리소스가 관리. + +## **Workload 리소스** + +### **Deployment** + +- 무상태(stateless) 애플리케이션에 적합. +- **RollingUpdate** 전략: 무중단 배포 (배포 시점에 새로운 파드와 기존 파드를 동시에 운영). +- **Recreate** 전략: 기존 파드를 모두 중지 후 새 파드 배포. + +### **DaemonSet** + +- 모든 노드(또는 특정 레이블의 노드)마다 1개씩 파드 배포. +- 로그 수집, 모니터링, 네트워킹 에이전트 등 시스템 레벨 데몬에 적합. + +### **StatefulSet** + +- 상태가 필요한 애플리케이션(데이터베이스, Zookeeper 등) 관리. +- 각 파드에 고유한 ID(이름 및 순서)가 부여. +- **PersistentVolumeClaim**과 연동하여 스토리지 영속성 보장. + +주요 차이점: + +| **항목** | **Deployment** | **DaemonSet** | **StatefulSet** | +| --- | --- | --- | --- | +| **사용 사례** | 일반 애플리케이션 (무상태) | 노드별 에이전트 배포 | 상태 있는 데이터베이스 등 | +| **복제 방식** | 원하는 개수만큼 복제 | 모든 노드에 1개씩 배포 | 이름/순서를 가진 복제본 관리 | +| **스토리지** | Stateless | Stateless | 상태 저장 (PersistentVolume) | + +--- + +## **데이터 관리 리소스** + +### **ConfigMap** + +- 비민감한 설정 데이터를 저장. +- 환경 변수, 설정 파일, CLI 인자로 주입 가능. + +### **Secret** + +- 민감한 데이터를 저장. (예: 비밀번호, API 키) +- Base64로 인코딩되어 저장되며, 추가 암호화 가능. + +### **ConfigMap과 Secret의 차이점** + +| **항목** | **ConfigMap** | **Secret** | +| --- | --- | --- | +| **목적** | 비민감한 설정 데이터를 저장. | 민감한 데이터를 저장 (예: 비밀번호, 인증 토큰). | +| **보안** | 평문으로 저장. | Base64로 인코딩되어 저장.이외에도 Kubernetes는 Secret 데이터를 etcd에 **암호화**할 수 있는 옵션 제공. | +| **기본 용량 제한** | 약 1MB. | 약 1MB. (ConfigMap과 동일) | +| **데이터 접근** | 컨테이너 환경변수, 볼륨 마운트, Command-line 등. | ConfigMap과 동일하지만 **보안 고려** 필요. | +| **External Integration** | 보통 외부 시스템과의 연계가 필요하지 않음. | 외부 비밀 관리 시스템(예: AWS Secrets Manager, HashiCorp Vault)과 연계. | +| **주요 사용 사례** | - 환경 변수 +- 구성 파일 +- 스크립트 등. | - 비밀번호 +- API 키 +- 인증서 +- OAuth 토큰 등. | + +--- + +### **Secret의 주요 특징** + +1. **Base64 인코딩**: + - Kubernetes 내부에서 Secret은 Base64로 인코딩됩니다. 하지만 이는 단순히 데이터 전송의 편의를 위해 인코딩된 것이지, 암호화된 데이터는 아닙니다. + - 추가적인 보안이 필요한 경우 **etcd 암호화**를 활성화해야 합니다. +2. **etcd와 Secret 암호화**: + - 기본적으로 Secret은 etcd에 평문으로 저장되기 때문에, 데이터 유출 위험이 있습니다. + - Kubernetes에서는 `-encryption-provider-config`를 통해 etcd에 저장되는 Secret을 암호화할 수 있습니다. +3. **RBAC (Role-Based Access Control)**: + - Secret은 ConfigMap보다 민감한 데이터를 다루기 때문에 **RBAC**으로 접근 제어가 필수적입니다. + - 예를 들어, 특정 네임스페이스에만 접근을 허용하거나, 읽기/쓰기 권한을 제한할 수 있습니다. +4. **외부 Secret 관리**: + - Secret은 종종 외부 시스템과 연동하여 관리됩니다. Kubernetes에 저장된 Secret이 아닌, **외부 Secret Management 도구**와 통합하여 사용하는 경우가 많습니다. + - 예: AWS Secrets Manager, HashiCorp Vault, Azure Key Vault. +- **PersistentVolume (PV) / PersistentVolumeClaim (PVC)** + - 상태 저장 애플리케이션을 위한 외부 스토리지 연계. + - 동적/정적 프로비저닝 개념. + +--- + +## **네트워킹 리소스** + +### **Service (SVC)** + +- 파드 간의 통신을 위해 안정적인 IP와 DNS 이름 제공. +- **Service Discovery**: `svc-name.namespace.svc.cluster.local` 형태로 DNS가 자동 생성. +- 주요 Service 타입: + - **ClusterIP**: 클러스터 내부에서만 접근. + - **NodePort**: 외부에서 고정 포트를 통해 접근 가능. + - **LoadBalancer**: 클라우드에서 외부 로드밸런서를 생성. + +![image.png](images/image.png) + +- 예: + + ```yaml + apiVersion: v1 + kind: Service + metadata: + name: my-service + spec: + selector: + app: my-app + ports: + - protocol: TCP + port: 80 + targetPort: 8080 + type: ClusterIP + ``` + + +### **Ingress** + +- HTTP/HTTPS 요청을 특정 Service로 라우팅. +- 주요 기능: + - 경로 기반 라우팅 (Path-Based Routing). + - 도메인 기반 라우팅 (Host-Based Routing). + - TLS 인증서로 HTTPS 제공. + +![image.png](images/image1.png) + +- 예: + + ```yaml + apiVersion: networking.k8s.io/v1 + kind: Ingress + metadata: + name: example-ingress + spec: + rules: + - host: example.com + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: my-service + port: + number: 80 + ``` + + +--- + +### **YAML 문법과 kubectl 명령어** + +- YAML 문법: + - 기본 구조: `apiVersion`, `kind`, `metadata`, `spec` 필드. + - 들여쓰기, 리스트, 맵 형식. + - 자주 사용하는 필드와 키워드 설명. +- kubectl 명령어: + - 리소스 생성: + + ```bash + kubectl apply -f + ``` + + - 리소스 조회: + + ```bash + kubectl get + ``` + + - 리소스 세부 정보: + + ```bash + kubectl describe + ``` + + - 로그 확인: + + ```bash + kubectl logs + ``` + + - 파드 내부 접근: + + ```bash + kubectl exec -it -- /bin/bash + ``` + + +--- + +### **실습: 간단한 애플리케이션 배포** + +### **1) Deployment 생성** + +- 애플리케이션을 배포하고 ReplicaSet으로 관리. + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: mario + namespace: games + labels: + app: mario +spec: + replicas: 1 + selector: + matchLabels: + app: mario + template: + metadata: + labels: + app: mario + spec: + containers: + - name: mario + image: pengbai/docker-supermario + +``` + +### **2) Service로 노출** + +- ClusterIP로 파드에 접근. + +```yaml +apiVersion: v1 +kind: Service +metadata: + name: mario + namespace: games + annotations: + alb.ingress.kubernetes.io/healthcheck-path: /mario/index.html +spec: + selector: + app: mario + ports: + - port: 80 + protocol: TCP + targetPort: 8080 + type: NodePort + externalTrafficPolicy: Local + +``` + +### **3) Ingress를 통해 외부로 노출** + +- HTTP 경로를 통해 접근 설정. + +```yaml +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + namespace: games + name: games-ingress + annotations: + alb.ingress.kubernetes.io/scheme: internet-facing + alb.ingress.kubernetes.io/target-type: ip + alb.ingress.kubernetes.io/certificate-arn: ${CERT_ARN} + alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]' + alb.ingress.kubernetes.io/healthcheck-protocol: HTTP + alb.ingress.kubernetes.io/healthcheck-port: traffic-port + alb.ingress.kubernetes.io/healthcheck-interval-seconds: '15' + alb.ingress.kubernetes.io/healthcheck-timeout-seconds: '5' + alb.ingress.kubernetes.io/success-codes: '200' + alb.ingress.kubernetes.io/healthy-threshold-count: '2' + alb.ingress.kubernetes.io/unhealthy-threshold-count: '2' +spec: + ingressClassName: alb + rules: + - host: ${WEBDOMAIN} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: mario + port: + number: 80 + +``` + +배포하기 + +```bash + +kubectl create namespace games + +# 애플리케이션 배포 +kubectl apply -f mario.yaml + +``` + +ingress 설정 + +```bash +DOMAIN="montkim.org" +WILDCARD_DOMAIN="*.$DOMAIN" + +CERT_ARN=$(aws acm list-certificates --output json | jq -r --arg wildcard "$WILDCARD_DOMAIN" '.CertificateSummaryList[] | select(.DomainName==$wildcard) | .CertificateArn') + +WEBDOMAIN=mario.montkim.org +WEBDOMAIN=$WEBDOMAIN CERT_ARN=$CERT_ARN envsubst < ingress.yaml > rendered-ingress.yaml +kubectl apply -f rendered-ingress.yaml +``` + +- onpremise / ingress nginx controller 용 설정 + + ```bash + apiVersion: apps/v1 + kind: Deployment + metadata: + name: mario + namespace: games + labels: + app: mario + spec: + replicas: 1 + selector: + matchLabels: + app: mario + template: + metadata: + labels: + app: mario + spec: + containers: + - name: mario + image: pengbai/docker-supermario + --- + apiVersion: v1 + kind: Service + metadata: + name: mario + namespace: games + spec: + selector: + app: mario + ports: + - port: 80 + protocol: TCP + targetPort: 8080 + type: NodePort + --- + apiVersion: networking.k8s.io/v1 + kind: Ingress + metadata: + namespace: games + name: games-ingress + spec: + ingressClassName: nginx + rules: + - host: mario.montkim.com + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: mario + port: + number: 80 + ``` + + +--- + +## **Advanced** + +![image.png](images/image2.png) + +- **Probes**: Liveness, Readiness 설정. +- **Horizontal Pod Autoscaler (HPA)**: 부하에 따른 자동 확장. +- **Node Affinity/Taints & Tolerations**: 노드 스케줄링 제약. +- + +## **Probes** + +Probes는 Kubernetes에서 Pod 상태를 모니터링하는 메커니즘으로, 두 가지 주요 유형이 있습니다. + +### **Liveness Probe** + +- Pod이 **죽었는지**를 판단합니다. +- 실패 시 컨테이너를 재시작합니다. +- 예를 들어, 애플리케이션이 Deadlock 상태가 되면 이를 감지하고 복구합니다. + +### **Readiness Probe** + +- Pod이 **트래픽을 받을 준비가 되었는지**를 판단합니다. +- 실패 시 Pod을 Service의 엔드포인트에서 제거합니다. +- 애플리케이션이 초기화 중이거나 외부 종속성을 대기하는 경우 유용합니다. + +### **Startup Probe** + +- 애플리케이션이 시작되었는지 확인합니다. +- 실패 시 Pod을 재시작하며, 초기화가 느린 애플리케이션에 적합합니다. + +### **Probes 설정 예제** + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-probe-example +spec: + replicas: 1 + selector: + matchLabels: + app: nginx + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx:latest + ports: + - containerPort: 80 + livenessProbe: + httpGet: + path: / + port: 80 + initialDelaySeconds: 3 + periodSeconds: 5 + readinessProbe: + httpGet: + path: / + port: 80 + initialDelaySeconds: 3 + periodSeconds: 5 + startupProbe: + httpGet: + path: / + port: 80 + initialDelaySeconds: 5 + periodSeconds: 10 + +``` + +--- + +## **Horizontal Pod Autoscaler (HPA)** + +HPA는 애플리케이션 부하에 따라 Pod의 개수를 자동으로 조정합니다. CPU 사용량, 메모리 사용량, 또는 커스텀 메트릭을 기준으로 동작합니다. + +### **HPA의 주요 개념** + +- **기준 메트릭**: 기본적으로 CPU, 메모리 사용량을 기준으로 설정. +- **자동 확장**: 사용량이 높아지면 Pod 수를 늘리고, 낮아지면 줄임. +- **리소스 요청/제한 필요**: Pod의 CPU/메모리 요청 값(`resources.requests`)이 설정되어야 효과적으로 동작. + +### **HPA 설정 예제** + +```yaml +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: nginx-hpa +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: nginx-deployment + minReplicas: 1 + maxReplicas: 5 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 50 + +``` + +### **HPA 작동 원리** + +1. CPU 사용량이 50%를 초과하면 Pod 수를 늘립니다. +2. 사용량이 50% 이하로 감소하면 Pod 수를 줄입니다. +3. Kubernetes Metrics Server가 활성화되어 있어야 작동합니다. + +--- + +## **Node Affinity / Taints & Tolerations** + +Pod을 특정 노드에 배치하거나 특정 노드를 회피하도록 설정합니다. + +### **Node Affinity** + +- 특정 조건의 노드에만 Pod을 배치합니다. +- **Types**: + - `requiredDuringSchedulingIgnoredDuringExecution`: 강제 배치. + - `preferredDuringSchedulingIgnoredDuringExecution`: 선호 배치. + +### **Node Affinity 예제** + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-affinity +spec: + replicas: 1 + selector: + matchLabels: + app: nginx + template: + metadata: + labels: + app: nginx + spec: + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: disktype + operator: In + values: + - ssd + containers: + - name: nginx + image: nginx:latest + +``` + +### **Taints & Tolerations** + +- **Taints**: 노드에 태그를 추가하여 특정 Pod만 실행되도록 제한합니다. +- **Tolerations**: Pod이 Taints를 무시하고 해당 노드에 배치되도록 설정합니다. + +### **Taints 설정 예제** + +```bash +kubectl taint nodes disktype=ssd:NoSchedule +``` + +### **Tolerations 설정 예제** + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-toleration +spec: + replicas: 1 + selector: + matchLabels: + app: nginx + template: + metadata: + labels: + app: nginx + spec: + tolerations: + - key: "disktype" + operator: "Equal" + value: "ssd" + effect: "NoSchedule" + containers: + - name: nginx + image: nginx:latest + +``` \ No newline at end of file diff --git a/posts/chapter4/images/image.png b/posts/chapter4/images/image.png new file mode 100644 index 0000000..f2d8a58 Binary files /dev/null and b/posts/chapter4/images/image.png differ diff --git a/posts/chapter4/images/image1.png b/posts/chapter4/images/image1.png new file mode 100644 index 0000000..6732712 Binary files /dev/null and b/posts/chapter4/images/image1.png differ diff --git a/posts/chapter4/images/image2.png b/posts/chapter4/images/image2.png new file mode 100644 index 0000000..c0b3bc3 Binary files /dev/null and b/posts/chapter4/images/image2.png differ