✅ 핵심 요약
kubectl port-forward는 "Pod 전체"에 대해 동작하고,
Pod 안에 있는 특정 컨테이너를 직접 선택해서 포워딩하지는 않습니다.
즉, Pod 안의 여러 컨테이너가 각각 다른 포트를 사용하면,
그 포트들로 Pod 전체에 포트 포워딩을 할 수 있어요.
어떤 컨테이너가 그 포트를 리슨 중인지에 따라 응답이 달라지는 거죠.
🛠 예시: 외부에서 각각 접근
mypod 안에 다음과 같은 구조가 있다고 가정할게요:
- mycon2 → 81번 포트에서 Nginx 실행
- mycon3 → 82번 포트에서 Nginx 실행
그리고 kubectl port-forward를 다음처럼 실행합니다:
kubectl port-forward pod/mypod 8081:81 8082:82
- 외부의 localhost:8081 → Pod 내부의 81번 포트로 연결 (즉, mycon2)
- 외부의 localhost:8082 → Pod 내부의 82번 포트로 연결 (즉, mycon3)
📌 주의할 점
- 포트 포워딩은 로컬 PC에서만 접근 가능합니다. 즉, kubectl port-forward를 실행한 그 PC에서만 유효합니다.
- Pod 내부에서 실행 중인 각 Nginx 인스턴스는 반드시 daemon off; 명령을 통해 foreground로 실행되어야 합니다
- 각각의 Nginx 설정에서 listen 81;, listen 82;가 정확히 되어 있어야 합니
🔄 로드밸런싱 테스트
Deployment + Service 조합
🔧 1. Nginx Deployment (3개의 Pod 생성)
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
🌐 2. ClusterIP 타입의 Service (내부 통신 테스트용)
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- port: 80
targetPort: 80
또는 NodePort로 외부에서 접근하고 싶다면 아래처럼 바꾸면 돼:
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 30080 # 포트는 네트워크 여유에 따라 조정
🔍 3. 로드밸런싱 확인 방법
# 반복적으로 호출해보기
curl <노드IP>:30080
Pod마다 HTML 내용이나 hostname 다르게 넣는 방법
✍ Pod마다 다르게 응답하게 만들기 (선택)
Dockerfile 만들기:
FROM nginx
RUN echo "Hello from NGINX $(hostname)" > /usr/share/nginx/html/index.html
이렇게 하면 각 Pod가 다른 hostname을 띄우니 curl 요청마다 다른 응답이 보여 → 부하분산 확인 가능! 😄
이 YAML 파일에서 정의된 두 개의 Pod(mypod3와 mypod4)는 부하 분산을 구현하지 않습니다.
단순히 두 개의 Pod가 각각 동일한 nginx 이미지를 사용하는 것뿐
이 두 Pod를 연결하는 **서비스(Service)**가 없기 때문
부하 분산을 하려면, Service를 사용하여 여러 Pod를 하나의 네트워크 엔드포인트로 묶어야 합니다.
서비스는 클러스터 내에서 여러 Pod를 자동으로 라운드로빈 방식으로 분산시켜줍니다.
apiVersion: v1
kind: Namespace
metadata:
name: myns2
---
apiVersion: v1
kind: Pod
metadata:
name: mypod3
namespace : myns2
spec:
containers:
- image: nginx
name: mycon
ports:
- containerPort: 80
protocol: TCP
---
apiVersion: v1
kind: Pod
metadata:
name: mypod4
namespace : myns2
spec:
containers:
- image: nginx
name: mycon
ports:
- containerPort: 80
protocol: TCP
별도 서비스 생성
부하분산을 구현하는 방법:
- Service 생성:
apiVersion: v1
kind: Service
metadata:
name: mynginx-service
namespace: myns2
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
- Pod에 라벨 추가:
Pod에 app: nginx 라벨을 추가하여 서비스와 연동될 수 있도록 해야 합니다.
apiVersion: v1
kind: Pod
metadata:
name: mypod3
namespace: myns2
labels:
app: nginx
spec:
containers:
- image: nginx
name: mycon
ports:
- containerPort: 80
protocol: TCP
---
apiVersion: v1
kind: Pod
metadata:
name: mypod4
namespace: myns2
labels:
app: nginx
spec:
containers:
- image: nginx
name: mycon
ports:
- containerPort: 80
protocol: TCP
설명:
- Service는 app: nginx 라벨을 가진 모든 Pod를 선택하여, 외부에서 하나의 IP와 포트로 접근할 수 있게 해줍니다.
- 서비스는 클러스터 내부에서 해당 Pod들로 트래픽을 분산시킵니다.
결과:
이렇게 하면, mypod3와 mypod4에 대한 트래픽이 mynginx-service를 통해 부하 분산됩니다. 이 서비스의 IP와 포트(예: mynginx-service:80)를 통해 두 Pod로 트래픽이 분배됩니다.
추가적으로 kubectl expose 명령어를 사용하여 서비스로 외부 접근을 설정할 수도 있습니다.
파드 내로 접속하는 방법
- 파드 이름 확인
kubectl get pods - 먼저, kubectl get pods 명령으로 파드 목록을 확인합니다. 여기서 접속하려는 파드의 이름을 확인합니다.
- kubectl exec 명령을 사용하여 파드 내로 접속
kubectl exec -it mypod -- /bin/bash- it: 인터랙티브 모드로 접속하도록 지정.
- mypod: 접속할 파드의 이름.
- /bin/bash: bash 셸을 사용하여 접속.
- kubectl exec -it mypod -c mycon1 -- /bin/bash
- 접속할 파드 이름을 확인한 후, kubectl exec 명령을 사용하여 파드 내로 접속할 수 있습니다. 예를 들어, mypod라는 이름의 파드에 접속하려면 다음과 같이 명령을 실행합니다:
- 파일 수정 및 명령 실행
echo "Hello from NGINX $(hostname)" > /usr/share/nginx/html/index.html - 파드에 접속한 후, 컨테이너 내에서 원하는 파일을 수정하거나 필요한 명령을 실행할 수 있습니다. 예를 들어, index.html 파일을 수정하려면 다음과 같이 할 수 있습니다:
각 Pod에 대해 고유한 ECHO 메시지를 설정하는 방법
각 Pod의 nginx 설정 파일을 수정
각 Pod가 반환하는 내용에 구분 방법
- nginx.conf 파일 수정
- ECHO를 각각의 Pod가 다르게 출력
server {
listen 80;
server_name localhost;
location / {
return 200 "This is Pod: ${HOSTNAME}\\n";
}
}
위 설정에서 ${HOSTNAME}은 각 Pod의 이름을 출력합니다. Kubernetes에서 HOSTNAME은 해당 Pod의 이름으로 자동 설정됩니다. 따라서, 이 설정을 각 Pod에 적용하면, 클라이언트는 각 Pod의 이름을 출력하는 메시지를 볼 수 있습니다.
- Pod를 위한 ConfigMap 생성
apiVersion: v1 kind: ConfigMap metadata: name: nginx-config namespace: myns2 data: nginx.conf: | server { listen 80; server_name localhost; location / { return 200 "This is Pod: ${HOSTNAME}\\n"; } } - nginx.conf 파일을 ConfigMap으로 생성하여 Pod에서 참조하게 할 수 있습니다.
- Pod에서 ConfigMap 사용하기
yaml 코드 복사 apiVersion: v1 kind: Pod metadata: name: mypod3 namespace: myns2 spec: containers: - name: mycon image: nginx ports: - containerPort: 80 volumeMounts: - name: nginx-conf mountPath: /etc/nginx/nginx.conf subPath: nginx.conf volumes: - name: nginx-conf configMap: name: nginx-config - Pod에 nginx.conf를 ConfigMap으로 마운트하여 nginx가 이를 읽고 사용하도록 설정합니다.
1. Dockerfile에서 hostname을 포함한 메시지 작성 (단 한번만 설정)
이 방법은 컨테이너를 실행할 때 hostname을 동적으로 반영할 수 없습니다. 이미지를 빌드할 때 hostname이 고정됩니다.
FROM nginx
RUN echo "Hello from NGINX $(hostname)" > /usr/share/nginx/html/index.html
이 방법은 nginx 서버가 시작될 때마다 변경된 호스트 이름을 반영할 수 없습니다.
대신, 컨테이너가 시작될 때마다 실행되는 스크립트를 사용해야 합니다.
2. 컨테이너가 실행될 때마다 hostname을 동적으로 반영하려면
컨테이너가 시작될 때마다 nginx의 index.html 파일을 동적으로 갱신하려면, entrypoint나 CMD를 사용하여 시작 시 스크립트를 실행해야 합니다. 이를 통해 실행 시마다 hostname을 반영하도록 할 수 있습니다.
예시) Dockerfile (동적으로 hostname을 반영하는 방법)
FROM nginx
# /etc/nginx/conf.d/default.conf 또는 다른 설정 파일을 수정할 수 있음
COPY ./default.conf /etc/nginx/conf.d/default.conf
# entrypoint를 사용해 컨테이너가 실행될 때마다 index.html을 동적으로 변경
ENTRYPOINT ["/bin/sh", "-c", "echo 'Hello from NGINX $(hostname)' > /usr/share/nginx/html/index.html && exec nginx -g 'daemon off;'"]
3. 설명
- ENTRYPOINT를 사용하여 컨테이너가 시작될 때마다 hostname을 동적으로 index.html에 반영하게 합니다.
- exec nginx -g 'daemon off;' 명령은 nginx를 포그라운드 모드로 실행하여 계속 작동하도록 합니다.
4. 추가 옵션: Nginx를 위한 환경 변수 활용
만약 nginx를 설정 파일을 통해 동적으로 수정하고 싶다면, 환경 변수를 사용하여 설정 파일에서 hostname을 반영할 수 있습니다. 예를 들어 nginx.conf에서 환경 변수를 참조하는 방법입니다.
FROM nginx
# 동적으로 환경 변수를 삽입하기 위해 envsubst 사용
RUN apt-get update && apt-get install -y gettext-base
# 환경 변수로 'hostname'을 사용하여 NGINX 설정 파일 동적 처리
COPY ./default.conf.template /etc/nginx/conf.d/default.conf.template
ENTRYPOINT ["/bin/sh", "-c", "envsubst < /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf && exec nginx -g 'daemon off;'"]
그리고 default.conf.template 파일을 다음과 같이 작성할 수 있습니다:
server {
listen 80;
location / {
root /usr/share/nginx/html;
index index.html;
# 환경 변수로 호스트명을 삽입
add_header X-Hostname ${HOSTNAME};
}
}
envsubst 명령은 환경 변수를 사용하여 템플릿 파일을 처리하고, 결과를 실제 nginx 설정 파일로 적용합니다.
이 방법은 컨테이너가 실행될 때마다 hostname을 자동으로 반영하게 합니다.
'IT 엔지니어 > CLOUD' 카테고리의 다른 글
| K8S Controller (0) | 2025.05.26 |
|---|---|
| 초기화/인프라 컨테이너 (0) | 2025.05.25 |
| K8S 실습 (1) | 2025.05.23 |
| K8S POD 생성 (0) | 2025.05.22 |
| DOCKER NAMESPACE/STATEFULSET (0) | 2025.05.22 |