Metrics Server
# Metrics Server 설치
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
# Metrics Server SSL 무시
kubectl patch deployment metrics-server -n kube-system --type=json \
-p='[{"op": "add", "path": "/spec/template/spec/containers/0/args/-", "value": "--kubelet-insecure-tls"}]'
# Metrics Server 배포 확인
kubectl get pods -n kube-system -l k8s-app=metrics-server
# 쿠버네티스 리소스 자원 사용량 확인
kubectl top node
kubectl top pods -A
# CPU, Memory 내림차순
kubectl top pods -A --sort-by=cpu
kubectl top pods -A --sort-by=memory
targetCPUUtilizationPercentage
등)을 넘으면 Pod 수를 늘리고, 밑돌면 줄임Deployment
(혹은 ReplicaSet
)의 replicas
필드를 조정apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: hpa-sample
spec:
scaleTargetRef: # Scale 타겟 지정
apiVersion: apps/v1
kind: Deployment
name: my-app # Deployment 이름
minReplicas: 2 # 최소 Pod
maxReplicas: 10 # 최대 Pod
metrics: # Scale 기준 지표 설정
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50 # CPU 사용률 50% 기준
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 70 # 메모리 사용률 70% 기준
cat << EOF >> hpa-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: hpa-nginx
spec:
replicas: 1
selector:
matchLabels:
app: hpa-nginx
template:
metadata:
labels:
app: hpa-nginx
spec:
containers:
- name: hpa-nginx
image: nginx
resources:
requests:
cpu: 50m
limits:
cpu: 100m
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: hpa-nginx
labels:
app: hpa-nginx
spec:
ports:
- port: 80
selector:
app: hpa-nginx
EOF
# hpa-nginx.yaml 파일 확인
cat hpa-nginx.yaml
# Deployment 배포
kubectl apply -f hpa-nginx.yaml
kubectl get deploy,pod
# HPA 생성
kubectl autoscale deployment hpa-nginx --cpu-percent=50 --min=1 --max=10
# HPA 확인
kubectl get hpa
# HPA 상세 정보 확인
kubectl describe hpa
HPA 생성
HPA 확인
HPA 상세 정보
UpdatePolicy
에 따라 Pod 재생성(RollingUpdate)apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: my-app-vpa
spec:
targetRef: # Scale 대상
apiVersion: apps/v1
kind: Deployment
name: my-app # Deployment 명칭
updatePolicy:
updateMode: "Auto" # VPA Recommender 에 의해 자동 조정 활성화
resourcePolicy:
containerPolicies:
- containerName: my-app-container # Container 명칭 "*" 사용 가능
minAllowed: # 컨테이너가 할당받을 수 있는 최소 리소스
cpu: "200m"
memory: "512Mi"
maxAllowed: # 컨테이너가 할당받을 수 있는 최대 리소스
cpu: "2"
memory: "2Gi"
# EKS Workshop 소스 사용
git clone https://github.com/kubernetes/autoscaler.git
# VPA 배포
cd autoscaler/vertical-pod-autoscaler/
./hack/vpa-up.sh
# VPA Controller 확인
kubectl get pods -n kube-system | grep vpa
# VPA 제거
./hack/vpa-down.sh
minSize
, maxSize
)-scale-down-delay-after-add
)목적
특징
주요 사용 용도
기본 구성
apiVersion: v1
kind: ConfigMap
metadata:
name: my-app-config
data:
LOG_LEVEL: "debug"
API_ENDPOINT: "https://api.example.com"
Pod에 주입 방법
apiVersion: v1
kind: ConfigMap
metadata:
name: mysql
data:
DBNAME: mydatabase
---
apiVersion: v1
kind: Pod
metadata:
name: nginx-configmap
spec:
containers:
- image: nginx
name: nginx-configmap # 컨테이너에서 사용할 변수 Key 값
env:
- name: DB
valueFrom:
configMapKeyRef:
name: mysql # 사용할 ConfigMap의 이름
key: DBNAME # ConfigMap 내의 키 -> 값: value1
위의 yaml 파일을 통해 배포하면 다음과 같이 DBNAME의 변수에 mydatabase가 적용되어 있음을 확인할 수 있습니다. # config-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-configmap-deploy # Deployment 리소스 이름
spec:
replicas: 2 # 생성할 Pod 개수
selector:
matchLabels:
app: nginx-configmap # Pod 선택용 레이블 셀렉터
template:
metadata:
labels:
app: nginx-configmap # Pod 템플릿에 붙일 레이블
spec:
containers:
- name: nginx # 컨테이너 이름
image: nginx # 사용할 컨테이너 이미지
ports:
- containerPort: 80 # 컨테이너 내 열어줄 포트
volumeMounts:
- name: config-volume # 아래 volumes.name 과 매칭
mountPath: /etc/nginx/nginx.conf # 컨테이너 내부에 마운트할 경로
subPath: nginx.conf # 볼륨 내 nginx.conf 파일만 마운트
volumes:
- name: config-volume # 컨테이너에 마운트할 볼륨 식별자
configMap:
name: nginx-config # 참조할 ConfigMap 이름
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service # Service 리소스 이름
spec:
type: NodePort # 외부 접근을 위한 NodePort 방식
selector:
app: nginx-configmap # 서비스가 트래픽을 전달할 Pod 레이블
ports:
- protocol: TCP
port: 80 # 서비스 포트
targetPort: 80 # Pod 컨테이너 포트
nodePort: 31001 # 클러스터 노드의 고정 노드포트
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config # ConfigMap 리소스 이름
data:
nginx.conf: | # 키가 곧 파일명이 되고, 아래 내용이 파일 내용으로 매핑
events {}
http {
server {
listen 80;
location / {
return 200 'Hello from nginx configmap!';
}
}
}
위 두 Yaml 파일을 배포한 후 확인해보면 다음과 같이 볼륨 마운트가 되어있음을 확인할 수 있습니다. apiVersion: v1
kind: Secret
metadata:
name: my-secret
type: Opaque
data:
username: bXl1c2Vy # base64로 인코딩된 값
password: bXlwYXNzd29yZA== # base64로 인코딩된 값
apiVersion: v1
kind: Pod
metadata:
name: my-app
spec:
containers:
- name: my-container
image: my-image
env:
- name: DB_USER # Container 에서 사용할 변수명
valueFrom:
secretKeyRef:
name: my-secret # 사용할 Secret의 이름
key: username # Secret 내의 키
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: my-secret # 사용할 Secret의 이름
key: password # Secret 내의 키
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: my-app-secret
key: DB_PASSWORD
volumes:
- name: secret-volume
secret:
secretName: my-app-secret
containers:
- name: app
image: my-app:latest
volumeMounts:
- name: secret-volume
mountPath: /etc/secret
readOnly: true
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: secret-test # Secret 이름
type: Opaque # 일반 문자열 타입
data:
# Base64 인코딩된 값
username: YWRtaW4=
password: cGFzc3dvcmQ=
# secretPod.yaml
apiVersion: v1
kind: Pod
metadata:
name: secret-pod # Pod 이름
spec:
containers:
- name: nginx # 컨테이너 이름
image: nginx # 사용할 이미지
env:
- name: DB_USER
valueFrom:
secretKeyRef:
name: secret-test # 참조할 Secret 이름
key: username # Secret 데이터 키
- name: DB_PASS
valueFrom:
secretKeyRef:
name: secret-test # 참조할 Secret 이름
key: password # Secret 데이터 키
위 yaml 파일을 배포하면 다음과 같이 secret이 적용된 것을 확인할 수 있습니다.
항목 | ConfigMap | Secret |
---|---|---|
저장 데이터 | 평문(plain text) | Base64 인코딩 (etcd 암호화 옵션 가능) |
용도 | 비민감 설정값 | 비밀번호, 토큰, 인증서 등 민감 정보 |
접근 제어 | 네임스페이스 단위 RBAC 가능 | 네임스페이스 단위 RBAC + 암호화 가능 |
생성 커맨드 | kubectl create configmap | kubectl create secret |
크기 제한 | 최대 1MiB | 최대 1MiB |
# cluster-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: cluster-pod-1
labels:
app: cluster-pod
spec:
containers:
- name: container
image: traefik/whoami
---
apiVersion: v1
kind: Pod
metadata:
name: cluster-pod-2
labels:
app: cluster-pod
spec:
containers:
- name: container
image: traefik/whoami
# netshoot-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: netshoot-pod
spec:
containers:
- name: netshoot-pod
image: nicolaka/netshoot
command: ["tail"]
args: ["-f", "/dev/null"]
# cluster-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: cluster-svc
spec:
type: ClusterIP
selector:
app: cluster-pod
ports:
- name: cluster
port: 8080
targetPort: 80
위 yaml을 배포한 후 파드 대역, SVC 대역을 확인하면 다음과 같습니다. NodeIP:NodePort
로 외부(클러스터 외부)에서 접근 가능# nodeport-pod.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nodeport-deploy
spec:
replicas: 2
selector:
matchLabels:
app: nodeport-deploy
template:
metadata:
labels:
app: nodeport-deploy
spec:
containers:
- name: container
image: traefik/whoami
# nodeport-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: nodeport-svc
spec:
type: NodePort
selector:
app: nodeport-deploy
ports:
- name: nodeport-svc
port: 80 # 서비스 포트 (클러스터 내부 사용)
targetPort: 80 # 실제 컨테이너 포트
nodePort: 31002 # 외부에서 접근할 포트
위 yaml을 배포하면 아래와 같이 엔드포인트를 확인할 수 있습니다. 역할
특징
호스트 이름 (도메인)을 기반으로 트래픽 라우팅 가능
api.example.com
/ www.example.com
을 각각 다른 Service 리소스와 연결
rules:
- host: foo.example.com
http: …
- host: bar.example.com
http: …
요청 경로 기반으로 트래픽 라우팅 가능
/service1
, /service2
경로를 각각 다른 Service 리소스와 연결
- path: /api
pathType: Prefix
backend: { serviceName: api-svc, servicePort: 80 }
- path: /web
pathType: Prefix
backend: { serviceName: web-svc, servicePort: 80 }
TLS 인증서를 활용하여 HTTPS 구성 가능
tls:
- hosts:
- example.com
secretName: example-tls-secret
web
서비스는 ingress
네트워크를 통해 클러스터 내 모든 노드의 80번 포트를 리스닝하고, 요청이 들어오면 실제 실행 중인 컨테이너로 자동 라우팅됩니다.예시
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
tls:
- hosts:
- example.com
secretName: example-tls-secret
rules:
- host: example.com
http:
paths:
- path: /foo(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: foo-service
port:
number: 80
- path: /bar(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: bar-service
port:
number: 80
사용 예제
Nginx Ingress Controller 설치
# Nginx Ingress Controller 설치
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml
# Service 타입 변경
kubectl patch svc ingress-nginx-controller -n ingress-nginx -p \
'{"spec":{"type":"NodePort","ports":[{"port":80,"targetPort":80,"nodePort":31000},{"port":443,"targetPort":443,"nodePort":31001}]}}'
위 명령어를 통해 배포를 진행하면 다음과 같이 설치된 Ingress Controller를 확인할 수 있다.
서비스 생성
apiVersion: v1
kind: Service
metadata:
name: growth-service
spec:
selector:
app: growth
ports:
- protocol: TCP
port: 80
targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: growth-deployment
spec:
replicas: 1
selector:
matchLabels:
app: growth
template:
metadata:
labels:
app: growth
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: growth-html
mountPath: /usr/share/nginx/html
volumes:
- name: growth-html
configMap:
name: growth-html
---
apiVersion: v1
kind: ConfigMap
metadata:
name: growth-html
data:
index.html: |
<html>
<body>
<h1>hello growth</h1>
</body>
</html>
apiVersion: v1
kind: Service
metadata:
name: log-service
spec:
selector:
app: log
ports:
- protocol: TCP
port: 80
targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: log-deployment
spec:
replicas: 1
selector:
matchLabels:
app: log
template:
metadata:
labels:
app: log
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: log-html
mountPath: /usr/share/nginx/html
volumes:
- name: log-html
configMap:
name: log-html
---
apiVersion: v1
kind: ConfigMap
metadata:
name: log-html
data:
index.html: |
<html>
<body>
<h1>hello log</h1>
</body>
</html>
Ingress 배포
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: growth-log-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: / # /growth, /log 요청을 서비스로 전달할 때 접두사 제거. ex) /growth -> growth-service '/'
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /growth
pathType: Prefix
backend:
service:
name: growth-service
port:
number: 80
- path: /log
pathType: Prefix
backend:
service:
name: log-service
port:
number: 80
위 yaml까지 배포한 후 확인해보면 ingress가 배포됨을 다음과 같이 확인할 수 있다.
emptyDir.medium: ""
), medium: "Memory"
로 설정하면 tmpfs(메모리)에도 마운트 가능