파드 운영하기
Pod
- Pod란 컨테이너를 표현하는 k8s API의 최소 단위
- Pod에는 하나 또는 여러 개의 컨테이너가 포함될 수 있음
nginx 웹 서버 컨테이너를 pod로 동작시키기
CLI
# web 파드 생성, 이미지는 nginx:1.14, 포트 80
kubectl run web --image=nginx:1.14 --port=80
kubectl get pods # 파드 생성 확인
kubectl get pods -o wide # 파드 상세 확인
kubectl delete pod web # web 파드 삭제
kubectl run web --image=nginx:1.14 --port=80 --dry-run=client # 동작 확인YAML
# yaml 결과 출력 (output -> yaml)
kubectl run web --image=nginx:1.14 --port=80 --dry-run=client -o yaml
# yaml 결과를 web.yaml에 저장
kubectl run web --image=nginx:1.14 --port=80 --dry-run=client -o yaml > web.yaml
# vi web.yaml
apiVersion: v1
kind: Pod
metadata:
name: web
spec:
containers:
- image: nginx:1.14
name: web
ports:
- containerPort: 80
# 파드 생성
kubectl apply -f web.yaml
kubectl get pods web
kubectl get pods web -o wide
# 파드 삭제
kubectl delete -f web.yaml
cka-exam이라는 namespace를 만들고, 'cka-exam' namespace에 아래와 같은 Pod를 생성하세요.
- Pod name: pod-01
- image: busybox
- env: CERT="CKA-cert"
- command: /bin/sh
- args: -c "while true; do echo $(CERT); sleep 10;done"
# 현재 context 확인
kubectl config current-context
# context k8s로 switching
kubectl config use-context k8s
# cka-exam 네임스페이스 생성
kubectl create namepsace cka-exam
kubectl run pod-01 --image=busybox --dry-run=client -o yaml > 3-1.yaml
# vi 3-1.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-01
namespace: cka-exam # 네임스페이스 지정
spec:
containers:
- image: busybox
name: pod-01
env: # 환경변수 설정
- name: CERT
value: "CKA-cert"
command: ["/bin/sh"]
args: ["-c", "while true; do echo $(CERT); sleep 10;done"]
# 파드 생성
kubectl apply -f 3-1.yaml
# 네임스페이스가 cka-exam인 파드 확인
kubectl get pods -n cka-exam
Pod "custom-app"의 log를 모니터링하고 "file not found" 메세지를 포함하는 로그 라인을 추출하세요. 추출된 결과는 /opt/REPORT/2022/custom-app-log에 기록하세요.
kubectl config current-context
kubectl config use-context hk8s
kubectl get pods
# custom-app 파드의 로그 확인
kubectl logs custom-app | grep 'file not found'
# custom-app 파드의 로그를 /opt/REPORT/2022/custom-app-log에 저장
kubectl logs custom-app | grep 'file not found' > /opt/REPORT/2022/custom-app-log
Static Pod
- API 서버 없이 특정 노드에 있는 kubelet에 의해 직접 관리
- 해당 워커 노드에서 kubelet이 컨테이너 파드를 생성
- /etc/kubernetes/manifests/ 디렉토리에 파드의 구성정보가 담긴 yaml 파일을 저장시 적용
- static pod 디렉토리 구성
- static pod를 삭제하기 위해서는 static pod가 구동되고 있는 노드의 /etc/kubernetes/manifests 디렉토리 아래 삭제하려는 파드의 구성정보가 명시된 yaml 파일을 삭제해야 한다.
# 워커노드 접속
ssh node1
# staticPodPath 확인
sudo cat /var/lib/kubelet/config.yaml | grep -i staticpodpath
cat /var/lib/kubelet/config.yaml
...
staticPodPath: /etc/kubernetes/manifests
...
# static pod path 이동
cd /etc/kubernetes/manifests
# pod yaml 파일 생성
kubectl run webserver --image=nginx:1.14 --port=80 --dry-run=client -o yaml > webserver.yaml
# 위에서 생성한 webserver 파드 yaml 파일로 인해 생성된 파드 확인
kubectl get pods -o wide
...
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox-sleep 1/1 Running 2 (16h ago) 37h 192.168.104.26 node2 <none> <none>
campus-01 1/1 Running 2 (16h ago) 37h 192.168.166.150 node1 <none> <none>
cka-webserver 1/1 Running 2 (16h ago) 37h 192.168.104.28 node2 <none> <none>
custom-app 1/1 Running 2 (16h ago) 37h 192.168.166.152 node1 <none> <none>
eshop-cart-app 1/1 Running 2 (16h ago) 37h 192.168.166.151 node1 <none> <none>
fast-01 1/1 Running 2 (16h ago) 37h 192.168.104.24 node2 <none> <none>
front-end-6f49fd5bf9-dws4k 1/1 Running 0 16h 192.168.166.147 node1 <none> <none>
front-end-6f49fd5bf9-gqw8h 1/1 Running 0 16h 192.168.104.29 node2 <none> <none>
podtest 1/1 Running 0 15h 192.168.104.30 node2 <none> <none>
webserver-node1 1/1 Running 0 11s 192.168.166.157 node1 <none> <none>
# 파드 상세 확인
kubectl describe pod webserver-node1
# yaml 파일 삭제
sudo rm- rf webserver.yaml
# 파드 삭제 확인
kubectl get pods -o wide
node1 노드에 nginx-static-pod.yaml라는 이름의 Static Pod를 생성하세요.
- Pod name: nginx-static-pod
- image: nginx
- port: 80
sudo -i
# static pod path 확인
cat /var/lib/kubelet/config.yaml | grep -i staticpodpath
# 실행 확인
kubectl run nginx-static-pod --image=nginx --port=80 --dry-run=client -o yaml
# 결과 yaml 파일 생성
kubectl run nginx-static-pod --image=nginx --port=80 --dry-run=client -o yaml > nginx-static-pod.yaml
# 파드 생성 확인
kubectl get pods -o wide
멀티 컨테이너
- 하나의 파드에 여러 개의 컨테이너가 포함되어 함께 실행
4개의 컨테이너를 동작시키는 eshop-frontend Pod를 생성하세요.
- pod image: nginx, redir, memcached, consul
# yaml 파일 생성
# 명령에서는 이미지 단일로만 선택 가능
kubectl run eshop-frontend --image=nginx --dry-run=client -o yaml > 3-2.yaml
# vi 3-1.yaml
apiVersion: v1
kind: Pod
metadata:
name: eshop-frontend
spec:
containers:
- image: nginx # nginx
name: nginx-container
- image: redis # redit
name: redis-container
- image: memcached # memcached
name: memcached-container
- image: consul # consul
name: consul-container
# 파드 생성
kubectl apply -f 3-2.yaml
# 파드 확인
kubectl get pods eshop-frontend
# 상세 확인
kubectl describe pod eshop-frontend
사이드카 컨테이너
- 오토바이에 부착된 사이드카를 연상
- 기존 컨테이너의 변경 없이 기능을 확장하고 향상시킬 수 있다.
- 기본 컨테이너 기능을 확장하기 위해 사용하며 본래의 컨테이너는 기본 서비스에 충실하고, 추가 기능을 별도의 컨테이너를 이용해 적용
- 웹서버는 기본 서비스에 충실하고, 추가로 생성되는 웹서버 로그는 별도의 사이드카 컨테이너가 수집하여 외부 log aggregator로 전송하는 형태의 서비스
사이드카 패턴 예시
- 보안을 위해 사이드카로 NGINX reverse proxy 등을 붙여서 HTTPS 통신을 한다.
- 성능을 위해 사이드카로 NGINX content cache 등을 붙인다.
- 컨테이너 외부로 로그를 모으기 위해 logstash, fluentd 등을 붙인다. (로그 중앙화)
장점
- 상호 의존성을 줄일 수 있다.
- 사이드카 장애 시 애플리케이션이 영향을 받지 않는다.
- 사이드카 적용/변경/제거 등의 경우 애플리케이션 수정이 필요하지 않다.
- 애플리케이션과 사이드카를 각각 독립적인 환경에서 구성할 수 있다.
- 동일한 스토리지를 공유할 수 있다.
단점
- 프로세스간 통신이 많고 최적화 해야 한다면 애플리케이션에서 함께 처리하는 것이 더 용이하다.
- 어플리케이션이 작은 경우 관리포인트가 늘어날 수 있다.
사이드카 프록시
쿠버네티스 환경에서의 사이드카는 특히 파드(pod)와 컨테이너 관계에 주목해야 합니다. 동일한 파드의 모든 컨테이너는 동일한 가상 네트워크 장치를 공유하므로 네트워크를 통해 서로 안전하게 상호작용할 수 있습니다. 이런 특성을 이용해서 사이드카 프록시만 외부에 노출하고 프록시와 애플리케이션 사이는 보안 네트워크로 연결할 수 있습니다.
만약 쿠버네티스가 아닌 환경이라면 Nginx와 같은 리버스 프록시를 통해 애플리케이션을 캡슐화하고 해당 애플리케이션에 대한 인증을 제공할 수도 있습니다. 하지만 쿠버네티스 환경에서 레플리카셋(ReplicaSet)이나 디플로이먼트(Deployment)로 배포한 경우 파드가 속한 노드가 지속해서 바뀔 수 있으며, 이때 네트워크 정보도 모두 바뀌게 됩니다. 스테이트풀셋(StatefulSets)으로 배포한다면 이런 염려가 없겠지만, HPA(Horizontal Pod Autoscale)나 확장/가용성이 필요한 일반적인 애플리케이션의 배포 형태는 레플리카셋이나 디플로이먼트입니다.
현재 운영중인 eshop-cart-app Pod의 로그를 Kubernetes built-in logging 아키텍처(예: kubectl logs)에 통합하는 로그 스트리밍 사이드카 컨테이너를 운영하세요.
- busybox 이미지를 사용하여 price라는 이름의 사이드카 컨테이너를 기존 eshop-cart-app에 추가합니다.
- 새 price 컨테이너는 다음과 같은 command를 실행해야 합니다.
- Command: /bin/sh, -c, "tail -n+1 -f /var/log/cart-app.log"
- /var/log에 마운트 된 볼륨을 사용하여 사이드카 컨테이너에서 로그 파일 cart-app.log를 사용해야 합니다.
- eshop-cart-app Pod와 cart-app 컨테이너를 수정하지 마세요.
# 현재 구동중인 eshop-cart-app 파드의 구성 정보를 yaml 파일에 저장
kubectl get pod eshop-cart-app -o yaml > 3-3.yaml
# vi 3-3.yaml
apiVersion: v1
kind: Pod
metadata:
name: eshop-cart-app
spec:
containers:
- command:
- /bin/sh
- -c
- 'i=1;while :;do echo -e ": Price: $((RANDOM % 10000 + 1))" >> /var/log/cart-app.log; i=$((i+1)); sleep 2; done'
image: busybox
name: cart-app
volumeMounts:
- mountPath: /var/log
name: varlog
- name: price # price 사이드카 컨테이너 추가
image: busybox
args: [/bin/sh, -c, 'tail -n+1 -f /var/log/cart-app.log']
volumeMounts:
- name: varlog # cart-app 컨테이너와 볼륨 공유
mountPath: /var/log # 볼륨 마운트
volumes:
- emptyDir: {}
name: varlog
# 파드 삭제
kubectl delete pod eshop-cart-app
# 파드 생성
kubectl apply -f 3-3.yaml
# 파드 확인
kubectl get pods
# price 컨테이너 로그 확인
kubectl logs eshop-cart-app -c price
- https://kubernetes.io/docs/concepts/workloads/pods/
- https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/
- https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/
- https://engineering.linecorp.com/ko/blog/service-authentication-sidecar-proxy
- https://kubernetes.io/docs/tasks/access-application-cluster/communicate-containers-same-pod-shared-volume/
- https://kubernetes.io/docs/concepts/cluster-administration/logging/