VPC(Virtual Private Cloud)는 퍼블릭 클라우드 환경에서 사용할 수 있는 고객 전용 사설 네트워크입니다. 다른 네트워크와 논리적으로 분리되어 있어 IT 인프라를 안전하게 구축하고 간편하게 관리할 수 있습니다. 또한 기존의 데이터 센터 네트워크와 유사하게 구현할 수 있습니다.
ingress-nginx-controller 공식 홈페이지의 베어서버 버전 컨트롤러를 설치하면 x-forwarded-for 기능이 올바르게 작동도지 않았다 그이유는 공식 홈페이지의 버전이 조금 더 높아서여서 버전이 낮은 컨트롤러를 이용해서 x-forwarded-for를 확인
ingress-nginx-controller 설치
k apply -f https://raw.githubusercontent.com/Beas-github/test/master/T2/nginx-ingress1.yaml
설치 시 k get -n ingress-nginx -o wide 를 통해서 확인 할 수 있다.
ingress-nginx-controller를 설치하게 되면 ingress-nginx라는 namespace가 생성이되면서 ingress - controller는 분리되어 동작이 된다.
Ingress Controller는 Ingress가 동작하기 위해서 반드시 필요한 존재로 ingress Controller가 Ingress를 선택해서 사용한다.
이상적으로, 모든 인그레스 컨트롤러는 참조 사양이 맞아야 한다. 실제로, 다양한 인그레스 컨트롤러는 조금 다르게 작동한다.
인그레스 클래스
인그레스는 서로 다른 컨트롤러에 의해 구현될 수 있으며, 종종 다른 구성으로 구현될 수 있다. 각 인그레스에서는 클래스를 구현해야하는 컨트롤러 이름을 포함하여 추가 구성이 포함된 IngressClass 리소스에 대한 참조 클래스를 지정해야 한다.
apiVersion: networking.k8s.io/v1 // 인그레스 정보가 있는 API
kind: IngressClass // IngressClass 오브젝트 생성
metadata:
name: external-lb // 오브젝트 이름
spec:
controller: example.com/ingress-controller // 사용할 인그레스 컨트롤러
parameters: // 환경설정 값들이 정의되어 있는 값을 참조하기 위해 사용
apiGroup: k8s.example.com // api resource들을 묶어 놓은 그룹
kind: IngressParameters //
name: external-lb
인그레스 컨트롤러
인그레스 리소스가 작동하려면, 클러스터는 실행 중인 인그레스 컨트롤러가 반드시 필요하다.
kube-controller-manager바이너리의 일부로 실행되는 컨트롤러의 다른 타입과 달리 인그레스 컨트롤러는 클러스터와 함께 자동으로 실행되지 않는다. 클러스터에 가장 적합한 인그레스 컨트롤러 구현을 선택하는데 이 페이지를 사용한다.
쿠버네티스 환경에서서비스(Service)는파드들을 통해 실행되고 있는 애플리케이션을 네트워크에 노출(expose)시키는 가상의 컴포넌트다.
쿠버네티스 내부의 다양한 객체들이 애플리케이션과, 그리고 애플리케이션이 다른 외부의 애플리케이션이나 사용자와 연결될 수 있도록 도와주는 역할을 한다.
쿠버네티스에서의 파드는 무언가가 구동 중인 상태를 유지하기 위해 동원되는 일회성 자원으로 언제든 다른 노드로 옮겨지거나 삭제될 수 있다. 또한 파드는 생성될 때마다 새로운 내부 IP를 받게 되므로, 이것만으로 클러스터 내/외부와 통신을 계속 유지하기는 어렵다.
쿠버네티스에서는파드가 외부와 통신할 수 있도록클러스터 내부에서 고정적인 IP를 갖는 서비스(Service)를 이용하도록 하고 있다.
서비스를 정의하고 생성할 때에는spec.ports아래에 연결하고자 하는 항목 별로 각각 2개씩의 포트가 지정되어야 한다. 아래의 항목 명칭은 클러스터 안에서 트래픽을 중계하는 서비스의 입장에서 기술된 것임을 이해하자.
targetPort: 파드의 애플리케이션 쪽에서 열려있는 포트를 의미한다. 서비스로 들어온 트래픽은 해당 파드의<클러스터 내부 IP>:<targetPort>로 넘어가게 된다.
port: 서비스 쪽에서 해당 파드를 향해 열려있는 포트를 의미한다.
서비스 유형
ClusterIP (기본 형태)
NodePort
LoadBalancer
ExternalName
ClusterIP
ClusterIP는파드들이 클러스터 내부의 다른 리소스들과 통신할 수 있도록 해주는 가상의 클러스터 전용 IP다. 이 유형의 서비스는<ClusterIP>로 들어온 클러스터 내부 트래픽을 해당 파드의<파드IP>:<targetPort>로 넘겨주도록 동작하므로,오직 클러스터 내부에서만 접근 가능하게 된다. 쿠버네티스가 지원하는 기본적인 형태의 서비스다.
NodePort
NodePort는외부에서 노드 IP의 특정 포트(<NodeIP>:<NodePort>)로 들어오는 요청을 감지하여, 해당 포트와 연결된 파드로 트래픽을 전달하는 유형의 서비스다. 이때 클러스터 내부로 들어온 트래픽을 특정 파드로 연결하기 위한ClusterIP역시 자동으로 생성된다.
LoadBalancer
도의 외부 로드 밸런서를 제공하는 클라우드(AWS, Azure, GCP 등)환경을 고려하여, 해당 로드 밸런서를 클러스터의 서비스로 프로비저닝할 수 있는LoadBalancer유형도 제공된다.
ExternalName
서비스에 selector 대신 DNS name을 직접 명시하고자 할 때에 쓰인다.spec.externalName항목에 필요한 DNS 주소를 기입하면, 클러스터의 DNS 서비스가 해당 주소에 대한CNAME레코드를 반환하게 된다.
노드 상의 에이전트(예: 시스템 데몬, kubelet)는 해당 노드의 모든 파드와 통신할 수 있다.
Namespaces
도커에서의 Namespace와는 다른 개념이다
도커에서의 Namespace는 호스트 내에서 Namespace로 분리하여 독립적인 리소스를 할당받아서 관리할 수 있는 개념이다
쿠버네티스에서의 Namespace는 하나의 Control Plane(Master)와 Worker Node들을 하나의 독립적인 Namespace로 관리한다.
쿠버네티스에서,네임스페이스는 단일 클러스터 내에서의 리소스 그룹 격리 메커니즘을 제공한다. 리소스의 이름은 네임스페이스 내에서 유일해야 하며, 네임스페이스 간에서 유일할 필요는 없다. 네임스페이스 기반 스코핑은 네임스페이스 기반 오브젝트(예: 디플로이먼트, 서비스 등)에만 적용 가능하며 클러스터 범위의 오브젝트(예: 스토리지클래스, 노드, 퍼시스턴트볼륨 등)에는 적용 불가능하다
리소스를 논리적으로 나누기 위한 방법을 제공하는 것
Pod, Deployment, Service와 같은 여러 오브젝트들을 하나의 Namespace로 그룹핑해서 관리 할 수 있다.
namespace는 많은 사용자가 여러 팀 또는 프로젝트에 분산되 었는 환경에서 사용하기 위한 것입니다. 사용자가 몇 명에서 수십 명에 이르는 kubernetes cluster의 경우 새롭게 namespaces를 생성할 필 요가 없으며, default-cluster 로 충분합니다.
Labels을 사용하여 동일한 Namespace 내의 resource를 구별 할 수 있습니다.
Pod 생성 및 컨테이너 구성 확인
**kubectl api-resources**는 Kubernetes 클러스터 내에서 사용 가능한 API 리소스 목록을 보여주는 명령어입니다. Kubernetes API는 클러스터 내의 다양한 개체(object)를 관리하는 데 사용되며, 이 명령어를 통해 어떤 종류의 리소스가 사용 가능한지, 그리고 해당 리소스의 종류와 버전을 확인할 수 있습니다.
kubectl api-resources 명령어는 다음과 같은 정보를 제공합니다:
이름 (Name): 리소스의 종류를 나타내는 문자열입니다. 예를 들어, "pods", "services", "deployments" 등이 리소스 이름의 예시입니다.
짧은 이름 (Short Names): 리소스에 대해 짧은 이름의 약어를 제공합니다. 이를 사용하여 리소스를 더 간단하게 참조할 수 있습니다.
API 그룹 (API Group): Kubernetes API는 여러 그룹으로 나누어질 수 있습니다. 대부분의 리소스는 "core" 그룹에 속하며, 이 외에도 커스텀 리소스 정의를 통해 사용자 지정 그룹을 만들 수 있습니다.
버전 (Version): 리소스의 API 버전을 나타냅니다. Kubernetes는 API 버전 관리를 통해 업그레이드 및 호환성을 유지합니다.
리소스 타입 (Resource Type): 리소스의 유형을 나타냅니다. 예를 들어 "namespaces", "pods", "services" 등이 리소스 타입의 예시입니다.
kubectl api-resources 명령어를 실행하면 현재 사용 가능한 모든 API 리소스의 목록이 표시됩니다. 이를 통해 클러스터 내의 다양한 리소스를 살펴보고, 해당 리소스에 대한 자세한 정보나 명령어를 실행하여 상호작용할 수 있습니다.
쿠버네티스 Pod 생성 실습
myweb.yaml : nginx 이미지를 사용하는 컨테이너를 생성한다.
apiVersion: v1 // stable release API 기본 Pod 생성시 쓰는 api
kind: Pod // 리소스 종류 Pod를 쓴다.
metadata: // pod의 이름과 라벨을 ㅇ지정
name: myweb // pod 이름은 myweb
spec: // Pod에서 실행될 컨테이너의 스펙
containers: // 컨테이너 정보
- image: nginx:latest //사용할 이미지
name: myweb-container // 컨테이너 이름
ports: // 사용할 포트
- containerPort: 80 // 80번 포트 오픈
protocol: TCP // TCP로 통신
nginx 및 netshoot 컨테이너 생성하여 서로 통신하기
apiVersion: v1
kind: Pod
metadata:
name: myweb2
spec:
containers:
- name: myweb2-nginx
image: nginx
ports:
- containerPort: 80
protocol: TCP
- name: myweb2-netshoot // 2번째 컨테이너 이름
image: nicolaka/netshoot // 2번째 컨테이너 이미지
# netshoot : 네트워크 관련 유틸이 설치된 이미지
command: ["/bin/bash"]
args: ["-c", "while true; do sleep 5; curl localhost; done"]
# /bin/bash로 5초 간격으로 웹 페이지를 접속하도록 설정
로그 기록을 통해 확인 가능
f 또는 -follow: 로그를 실시간으로 스트리밍하는 옵션입니다. 새로운 로그 메시지가 기록될 때마다 계속해서 출력됩니다.
c <container-name> 또는 -container=<container-name>: 컨테이너의 이름을 지정하는 옵션입니다. 만약 Pod 내에 여러 개의 컨테이너가 있는 경우, 이 옵션을 사용하여 특정 컨테이너의 로그를 확인할 수 있습니다.
Pause 컨테이너
역할: Pause 컨테이너는 파드의 네트워크 네임스페이스를 공유하며, 파드 내의 다른 컨테이너들이 공유하는 리눅스 네임스페이스를 유지합니다. 이 컨테이너는 실제 응용프로그램을 실행하지 않고, 단지 네트워크 및 네임스페이스 관리를 위한 역할을 합니다.
통신: 파드 내의 다른 컨테이너들은 공유하는 Pause 컨테이너를 통해 네트워크 통신을 할 수 있습니다. Pause 컨테이너를 통해 파드 내부의 모든 컨테이너는 동일한 IP 주소 범위를 공유하며, localhost를 통해 통신할 수 있습니다.
파드 내의 컨테이너들이 동일한 IP 주소를 가지는 주된 이유는 다음과 같습니다:
Pause 컨테이너를 공유: 파드 내의 모든 컨테이너, 포함하여 일반적인 애플리케이션 컨테이너들, Pause 컨테이너를 공유합니다. Pause 컨테이너는 파드의 네트워크 네임스페이스를 관리하고, 모든 컨테이너가 동일한 네트워크 네임스페이스 내에서 실행됩니다.
네트워크 네임스페이스 공유: 파드 내의 모든 컨테이너들은 같은 네트워크 네임스페이스를 공유합니다. 이는 네트워크 주소 공간을 파드 단위로 격리하지 않고, 파드 내의 컨테이너들이 동일한 IP 범위와 서브넷을 공유하도록 함으로써 이루어집니다.
로컬호스트 통신: 파드 내의 컨테이너들은 로컬호스트 주소(127.0.0.1)를 사용하여 서로 통신할 수 있습니다. Pause 컨테이너가 모든 컨테이너들이 공유하는 네트워크 네임스페이스를 관리하므로, 로컬호스트 주소를 통해 컨테이너들이 통신할 수 있습니다.
파드 내 컨테이너에게 부모처럼 net namespace 제공해준다. 파드 내 복수의 컨테이너는 공통으로 pause 컨테이너가 제공한 network namespace를 공유한다.
중간 프로젝트가 끝나고 말도 안 되는 억까로 코로나에 걸려 겨우 살아나 블로그를 쓰지 못했다.
쿠버네티스 오브젝트
쿠버네티스 시스템에서 영속성을 가지는 오브젝트이다. 클러스터의 상태를 나타내기 위해 오브젝트를 이용한다.
어떤 컨테이너화된 애플리케이션이 동작 중인지 (그리고 어느 노드에서 동작 중인지)
그 애플리케이션이 이용할 수 있는 리소스
그 애플리케이션이 어떻게 재구동 정책, 업그레이드, 그리고 내고장성과 같은 것에 동작해야 하는지에 대한 정책
쿠버네티스 오브젝트는 하나의 "의도를 담은 레코드"이다.
오브젝트는 2개의 필드를 포함해야 하는데 spec, status이다.
spec : 오브젝트를 생성할 때 원하는 특징(의도한 상태)에 대한 설명을 제공해서 설정한다.
status : 쿠버네티스 시스템과 컴포넌트에 의해 제공되고 업데이트된 오브젝트의 현재 상태를 설명한다.
쿠버네티스에서 오브젝트를 생성할 때, 기본정보 + spec을 yaml 파일로 kubectl에 제공해야 한다.
기본 오브젝트 4가지
파드(Pod)
쿠버네티스에서 생성하고 관리 할 수 있는 배포 가능한 가장 작은 컴퓨팅 단위이다.
하나 이상의 컨테이너 그룹으로 그룹은 스토리지 및 네트워크를 공유하고 해당 컨테이너를 구동하는 방식에 대한 명세를 갖는다.
pod 생성 yaml 예시
apiVersion: v1 //스크립트를 실행하기 위한 쿠버네티스 API 버전
kind: Pod //리소스의 종류 정의 Pod 쿠버네티스 선언
metadata: // 리소스의 라벨, 이름 등을 지정함
name: nginx // namespace 상에서 유일한 값
spec: // 생성할 오브젝트의 구체적 내용을 정의하는 spec -> object마다 형식이 다르다.
containers: // 컨테이너 명세를 배열로 기술
- name: nginx // 컨테이너 이름
image: nginx:1.14.2 // 컨테이너 생성시 사용할 이미지
ports: // 외부 요청을 전달하기 위한 포트 목록
- containerPort: 80 // 80번 포트를 사용한다.
쿠버네티스에서,네임스페이스는 단일 클러스터 내에서의 리소스 그룹 격리 메커니즘을 제공한다. 리소스의 이름은 네임스페이스 내에서 유일해야 하며, 네임스페이스 간에서 유일할 필요는 없다. 네임스페이스 기반 스코핑은 네임스페이스 기반 오브젝트(예: 디플로이먼트, 서비스 등)에만 적용 가능하며 클러스터 범위의 오브젝트(예: 스토리지클래스, 노드, 퍼시스턴트볼륨 등)에는 적용 불가능하다.
쿠버네티스 클러스터에서 사용되는 리소소들을 구분해 관리하는 그룹이다. pod와 service 등은 네임스페이스별로 생성 및 관리될 수 있으며, 네임스페이스별로 사용자 접근 권한을 다르게 설정할 수도 있다.
쿠버네티스는 namespace 즉 논리적인 분리 단위를 제공해 준다. -> 물리적 분리가 아닌 논리적 분리
볼륨 Volume
pod가 사라지더라도 사용할 수 있는 디렉터리는 볼륨 오브젝트를 통해 host에 저장할 수 있다.
서비스 Service
파드의 집합으로 쿠버네티스의 네트워크를 나타낸다.
ClusterIP - 클러스터 내부에서만 접근 가능한 pod끼리 통신하게 해주는
NodePort - 클러스터 node위의 open port를 의미하며 고정 포트로 각 노드의 포트를 열어 외부에서 접속할 수 있게 한다.
LoadBalancer - 클라우드 공급자의 로드밸런서를 사용해 서비스를 외부에 expose 한다.
ExternalName - 잘 모르겠음
ex) Deployment
파드와 레플리카셋에 대한 선언적 업데이트를 제공한다.
디플로이먼트에서의도하는 상태를 설명하고, 디플로이먼트컨트롤러(Controller)는 현재 상태에서 의도하는 상태로 비율을 조정하며 변경한다. 새 레플리카셋을 생성하는 디플로이먼트를 정의하거나 기존 디플로이먼트를 제거하고, 모든 리소스를 새 디플로이먼트에 적용할 수 있다.
apiVersion: apps/v1 // api 버전과 디플로이는 apps/v1을 사용해야 한다.
kind: Deployment // 해당 yaml은 deployment라고 정의
metadata: // metadata 설정
name: nginx-deployment // namespace 필드 nginx-deployment를 만든다.
labels: // 라벨을 만든다.
app: nginx // app=nginx라는 key : value 형식
spec: // spec 요구사항을 적는다.
replicas: 3 // 레플리카는 3개로
selector: // 생성된 레플리카셋을 관리할 파드를 찾아내는 방법을 정의
matchLabels: // 라벨이 맞는 파드들을 관리한다.
app: nginx // app=nginx라는 라벨을 가진 파드를 관리한다.
template: // 새 파드를 런칭하는데 사용할 템플릿 -> selector와 labels 가 일치 해야 한다.
metadata: // 파드 메타데이터
labels: // 파드 라벨
app: nginx // app=nginx
spec: //파드 템플릿 사양
containers: // 컨테이너 정보
- name: nginx // 컨테이너 이름 nginx
image: nginx:1.14.2 // 컨테이너에 사용할 이미지
ports: // 컨테이너 사용 포트
- containerPort: 80 // 80포트를 사용한다.
이렇게 수정된 환경에서 실행되는 프로그램은 지정된 디렉터리 트리 밖의 파일들의 이름을 지정할 수 없으므로(즉, 일반적으로는 접근이 불가능하므로) chroot 감옥으로 부른다. chroot는 chroot(2)시스템 호출이나 chroot(8) 래퍼 프로그램을 가리킬 수 있다.
root(/)폴더 위치를 바꾸는 명령어로 Linux의 기본 /가 아닌 다른 폴더를 root 폴더로 재 정의 하는 명령어이다.
chroot를 통해서 사용자나 프로세스가 특정 파일 시스템 구역에서 벗어나지 못하도록 울타리를 치는 역할을 한다.
# syntax=docker/dockerfile:1
FROM python:3.7-alpine -기본 바탕 이미지
WORKDIR /code - 실행할 영역
ENV FLASK_APP=app.py - 플라스크 환경변수
ENV FLASK_RUN_HOST=0.0.0.0 - 플라스크 동작할 호스트
RUN apk add --no-cache gcc musl-dev linux-headers - 파이썬 apk 패키지 실행
COPY requirements.txt requirements.txt - 호스트의 txt 파일 복사
RUN pip install -r requirements.txt - txt에 명시된 파이썬 패키지 설치
EXPOSE 5000 - 포트 설정
COPY . . - 호스트에있는 파일들 복사
CMD ["flask", "run"] - 컨테이너를 시작하면 시작할 명령어
docker-compose.yaml 파일
services:
web:
build: . - 호스트에 있는 Dockerfile을 빌드한다.
ports: - 포트포워딩
- "8000:5000"
volumes: - 볼륨마운트한다. = 호스트에있는 app.py를 사용한다.
- .:/code
environment: - 환경변수로 flask의 debug를 시작한다.
FLASK_DEBUG: "true"
redis: - 레디스를 설치 후 실행한다.
image: "redis:alpine"