[쿠버네티스] 서비스 & 인그레스 & 볼륨(emptyDir, gitRepo)

신현식·2023년 2월 17일
0

구름_Kubernetes

목록 보기
5/25
post-thumbnail

서비스

파드 집합에서 실행중인 애플리케이션을 네트워크 서비스로 노출하는 추상화 방법이다.
쿠버네티스를 사용하면 익숙하지 않은 서비스 디스커버리 메커니즘을 사용하기 위해 애플리케이션을 수정할 필요가 없다. 쿠버네티스는 파드에게 고유한 IP 주소와 파드 집합에 대한 단일 DNS 명을 부여하고, 그것들 간에 로드-밸런스를 수행할 수 있다.

  • 서비스라고 하는것은 프록시를 설정하는 것이라 볼 수 있다. 이 프록시도 컨테이너는 아니기에 컴퓨팅 자원이 아닌 네트워크의 가상화된 기능이라고 보면 된다. 즉 파드가 프록시를 통해서 타켓파드에 접근한다고 보면 된다.

  • 파드는 비영구적 리소스이다. 만약 앱을 실행하기 위해 디플로이먼트를 사용한다면, 동적으로 파드를 생성하고 제거할 수 있다.

  • 각 파드는 고유한 IP 주소를 갖지만, 디플로이먼트에서는 한 시점에 실행되는 파드 집합이 잠시 후 실행되는 해당 파드 집합과 다를 수 있다.

서비스의 역할

  • Proxy (LoadBalancer)
  • service discovery
    요즘은 프록시가 로드밸런서의 역할을 하기에 따로 구별은 하지 않는다.
cd ../../05_network/01_internal_service/

vi myapp-svc.yaml

apiVersion: v1
kind: Service
metadata:
  name: myapp-svc
spec:
  ports:
  - port: 80            # 서비스(프록시와 동일)를 찾아올 포트
    targetPort: 8080    # 서비스와 연결할 대상
  selector:             # 서비스와 파드의 관계는 파드의 레이블과 서비스의 셀렉터로 이루어진다.
    app: myapp-rs

# 서비스 생성
kubetl create -f myapp-svc.yaml

# 서비스 생성된 것 확인, IP 자동생성
kubectl get services
kubectl get pods

# 3번 보내면 로드밸런싱되어 각기 다른 파드에 접속하는 것을 확인할 수 있다. 
프록시의 IP를 80번으로 요청, 프록시와 연결된 3개의 파드에 라우팅함
curl http://10.233.43.109
  • 따로 만든적이 없지만 서비스를 만들면 똑같은 이름의 엔드포인트가 만들어진다. 앤드포인트는 타켓을 의미하며 파드의 IP와 포트정보를 가지고 있다. selector 때문에 만들어진 것이다.
kubectl get endpoints (ep)

service discovery: 이름으로 서비스 찾기

service discovery: 하나의 서비스가 다른 서비스를 찾는 것을 의미한다. 프론트엔드가 백엔드를 찾는다. 백엔드가 DB를 찾는다. 프록시가 프론트엔드를 찾는 등의 서비스를 찾는데 도움을 주는 매케니즘을 의미한다.

  • 쿠버네티스의 모든것은 다 도커에서의 -d인 detack로 작동된다. 기본이 d이기때문에 따로 선언 안해줘도 되고 밑은 쉘을 실행시켜줘야하기 떄문에 -it 옵션이 들어간다.
# 파드를 임시로 띄움, 바로 삭제되도록 --rm 옵션 추가
client 파드를 하나 띄었다고 생각
kubectl run -it nettool --image ghcr.io/c1t1d0s7/network-multitool --rm

서비스는 실행중

# host 질의, IP주소를 반환
host myapp-svc

# 서비스의 IP로 접속확인
curl 본인의 서비스의 IP주소

# 서비스의 이름으로 접속확인
curl http://myapp-svc

# 이름으로 접속하는 방법 풀네임: 
              이름 네임스페이스 타입 기본세팅 도메인
curl http://myapp-svc.default.svc.cluster.local
  • 서비스 이름만 가지고 service sidcovery를 진행해 서비스를 찾을 수 있다.

서비스 퍼블리싱 (ServiceTypes)

애플리케이션 중 일부(예: 프론트엔드)는 서비스를 클러스터 밖에 위치한 외부 IP 주소에 노출하고 싶은 경우가 있을 것이다.

쿠버네티스 ServiceTypes는 원하는 서비스 종류를 지정할 수 있도록 해준다. 기본 값은 ClusterIP이다.

Type 값과 그 동작은 다음과 같다.

ClusterIP

서비스를 클러스터-내부 IP에 노출시킨다. 이 값을 선택하면 클러스터 내에서만 서비스에 도달할 수 있다. 이것은 ServiceTypes의 기본 값이다.

NodePort

고정 포트 (NodePort)로 각 노드의 IP에 서비스를 노출시킨다. NodePort 서비스가 라우팅되는 ClusterIP 서비스가 자동으로 생성된다. < NodeIP>:< NodePort>를 요청하여, 클러스터 외부에서 NodePort 서비스에 접속할 수 있다.

# 레블리카셋으로 복제본 3개를 가지고 있음
vi myapp-rs.yaml

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: myapp-rs
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp-rs
  template:
    metadata:
      labels:
        app: myapp-rs
    spec:
      containers:
      - name: myapp
        image: ghcr.io/c1t1d0s7/go-myweb:alpine
        ports:
        - containerPort: 8080


kubectl create -f myapp-rs.yaml        

# nodeport 생성
vi myapp-svc-np.yaml

apiVersion: v1
kind: Service
metadata:
  name: myapp-svc-np
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 8080
    nodePort: 31111
  selector:
    app: myapp-rs

kubectl create -f myapp-svc-np.yaml

# 기존의 부분과 포트 부분이 다르다.
kubectl get svc

# 외부에서 접속 확인
kubectl get nodes -o wide
curl http://192.168.56.11:31111
curl http://192.168.56.21:31111
curl http://192.168.56.22:31111
curl http://192.168.56.23:31111
 
  • 노드의 지정한 포트인 31111로 접속하게 되면 파드까지 연결이 된다. 이를 윈도우에서 작업을 하게될 때 이는 가상컴퓨터를 벗어난 클러스터 외부에서 접근을 하는 것인데, 기존의 clusterIP 타입은 클러스터 내부에서만 접근이 가능했고 nodePort나 Loadbalancer는 외부용 타입이다.

  • edit 명령으로 nodePort의 범위를 수정하려고 할때 포트의 범위는 30000-32767로 설정해야 한다.

  • nodeport 타입이지만 내부에서도 접속이 가능하다. 즉 내부로는 clusterIP의 역할도 하면서 외부로도 통신이 가능하다는 것이다.

LoadBalancer

클라우드 공급자의 로드 밸런서를 사용하여 서비스를 외부에 노출시킨다. 외부 로드 밸런서가 라우팅되는 NodePort와 ClusterIP 서비스가 자동으로 생성된다.

kubectl delete -f myapp-svc-np.yaml

vi myapp-svc-lb.yaml

apiVersion: v1
kind: Service
metadata:
  name: myapp-svc-lb
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: myapp-rs


kubectl create -f myapp-svc-lb.yaml

# 서비스 확인, 외부 IP 생성됨
kubectl get svc
NAME           TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)        AGE
kubernetes     ClusterIP      10.233.0.1     <none>           443/TCP        3d20h
myapp-svc-lb   LoadBalancer   10.233.18.23   192.168.56.200   80:30290/TCP   47s

# 여러번 curl를 보내면 로드밸런스 되는 것을 확인 할 수 있다.
curl 192.168.56.200

Kubernetes용 네트워크 로드 밸런서

https://openelb.io/
https://github.com/openelb/openelb

ExternalName

값과 함께 CNAME 레코드를 리턴하여, 서비스를 externalName 필드의 콘텐츠 (예:example.com)에 매핑한다. 어떤 종류의 프록시도 설정되어 있지 않다.

cat myapp-svc-extname.yaml

apiVersion: v1
kind: Service
metadata:
  name: example
spec:
  type: ExternalName
  externalName: example.com


kubectl create -f myapp-svc-extname.yaml

kubectl get svc
NAME         TYPE           CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
example      ExternalName   <none>       example.com   <none>    5s
kubernetes   ClusterIP      10.233.0.1   <none>        443/TCP   3d21h



# client 파드를 하나를 임시로 띄움
kubectl run -it nettool --image ghcr.io/c1t1d0s7/network-multitool --rm

서비스는 실행중

# host에 질의해보면 example.com 의 실제 IP를 알려줌
host example

헤드리스(Headless) 서비스

때때로 로드-밸런싱과 단일 서비스 IP는 필요치 않다. 이 경우, "헤드리스" 서비스라는 것을 만들 수 있는데, 명시적으로 클러스터 IP (.spec.clusterIP)에 "None"을 지정한다.

쿠버네티스의 구현에 묶이지 않고, 헤드리스 서비스를 사용하여 다른 서비스 디스커버리 메커니즘과 인터페이스할 수 있다.

kubespary 디렉터리에 들어가서
vi invetory/mycluster/group_vars/k8s_cluster/k8s-cluster.yml
  • 서브넷에 의해 서비스와 파드는 2^14-2만큼만 생성 가능하다.
# 서비스를 생성할 때, 클러스터 IP를 None으로 해주면 된다.
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc-headless
spec:
  clusterIP: None
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: myapp-rs-headless
  • 원래는 서비스의 클러스터 IP가 나오는데 헤드리스 서비스는 파드의 IP가 나온다. 이는 원하는 파드로 갈 수 있다는 것을 의미한다.

인그레스 컨트롤러

인그레스 리소스가 작동하려면, 클러스터는 실행 중인 인그레스 컨트롤러가 반드시 필요하다.
즉 인그레스 자체는 이런 규칙들을 정의해둔 자원이고 실제로 동작시키는 것은 인그레스 컨트롤러이다.

kube-controller-manager 바이너리의 일부로 실행되는 컨트롤러의 다른 타입과 달리 인그레스 컨트롤러는 클러스터와 함께 자동으로 실행되지 않는다. 클러스터에 가장 적합한 인그레스 컨트롤러 구현을 선택하는데 이 페이지를 사용한다.

  • 프로젝트로서 쿠버네티스는 AWS, GCE와 nginx 인그레스 컨트롤러를 지원하고 유지한다.

인그레스(ingress)

인그레스는 주로 클러스터 외부에서 안에 있는 파드에 접근할 때 사용하는 방법이다. 서비스와의 차이점은 주로 L7 영역의 통신을 담당해서 처리한다는 점이다.
즉 클러스터 내의 서비스에 대한 외부 접근을 관리하는 API 오브젝트이며, 일반적으로 HTTP를 관리한다.

인그레스는 외부에서 서비스로 접속이 가능한 URL, 로드 밸런스 트래픽, SSL / TLS 종료 그리고 이름-기반의 가상 호스팅을 제공하도록 구성할 수 있다.
인그레스 컨트롤러는 일반적으로 로드 밸런서를 사용해서 인그레스를 수행할 책임이 있으며, 트래픽을 처리하는데 도움이 되도록 에지 라우터 또는 추가 프런트 엔드를 구성할 수도 있다.

  • 인그레스는 임의의 포트 또는 프로토콜을 노출시키지 않는다. HTTP와 HTTPS 이외의 서비스를 인터넷에 노출하려면 보통 Service.Type=NodePort 또는 Service.Type=LoadBalancer 유형의 서비스를 사용한다. 근본적으로는 nodeport라 보면 된다.
  • 인그레스는 파드로 작동, 이 파드가 외부 클라이언트에서 해당되는 트래픽을 받아서 실제 서비스를 넘겨준다.
  • 인그레스: L7프록시(로드밸런서, ALB 아마존 EKS) -> 라우팅 정책 수립 -> 서비스: L4프록시(로드밸런서, NLB/CLB 아마존 EKS)
  • 호스트 이름이나 URL 경로에 따라서 각 서비스로 라우팅 할 수 있는 규칙을 만들어서 분산시킬 수 있다.
  • 다른 어플리케이션은 특정 어플리케이션의 인그레스 정보를 확인한다.
    ingress-nginx용 어노테이션
kubectl api-resources | grep ingresses
  • 경로로 구별
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: simple-fanout-example
spec:
  rules:
  - host: foo.bar.com
    http:
      paths:
      - path: /foo
        pathType: Prefix
        backend:
          service:
            name: service1
            port:
              number: 4200
      - path: /bar
        pathType: Prefix
        backend:
          service:
            name: service2
            port:
              number: 8080
  • 호스트 이름으로 구별
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: name-virtual-host-ingress
spec:
  rules:
  - host: foo.bar.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: service1
            port:
              number: 80
  - host: bar.foo.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: service2
            port:
              number: 80

경로 유형

인그레스의 각 경로에는 해당 경로 유형이 있어야 한다. 명시적 pathType 을 포함하지 않는 경로는 유효성 검사에 실패한다. 지원되는 경로 유형은 세 가지이다.

  • ImplementationSpecific: 이 경로 유형의 일치 여부는 IngressClass에 따라 달라진다. 이를 구현할 때 별도 pathType 으로 처리하거나, Prefix 또는 Exact 경로 유형과 같이 동일하게 처리할 수 있다.

  • Exact: URL 경로의 대소문자를 엄격하게 일치시킨다.

  • Prefix: URL 경로의 접두사를 / 를 기준으로 분리한 값과 일치시킨다. 일치는 대소문자를 구분하고, 요소별로 경로 요소에 대해 수행한다. 모든 p 가 요청 경로의 요소별 접두사가 p 인 경우 요청은 p 경로에 일치한다.

  • 다중 일치
    경우에 따라 인그레스의 여러 경로가 요청과 일치할 수 있다. 이 경우 가장 긴 일치하는 경로가 우선하게 된다. 두 개의 경로가 여전히 동일하게 일치하는 경우 접두사(prefix) 경로 유형보다 정확한(exact) 경로 유형을 가진 경로가 사용 된다.

호스트네임 와일드카드

호스트는 정확한 일치(예: "foo.bar.com") 또는 와일드카드(예: "* .foo.com")일 수 있다. 정확한 일치를 위해서는 HTTP host 헤더가 host 필드와 일치해야 한다. 와일드카드 일치를 위해서는 HTTP host 헤더가 와일드카드 규칙의 접미사와 동일해야 한다.

  • 리스트는 위에서 아래순으로 진행하는 순서가 있다. 따라서 작은 정책을 위에 배치하는 것이 중요하다. 큰 정책이 위에 있을시 밑에 정책이 실행되지 않을 수 있기 때문이다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-wildcard-host
spec:
  rules:
  - host: "*.bar.com"
    http:
      paths:
      - pathType: Prefix
        path: "/bar"
        backend:
          service:
            name: service1
            port:
              number: 80
  - host: "foo.bar.com"      # 이 경우 위 정책이 더 큰 범위이기 떄문에 서비스2는 절대 실행되지 않는다.
    http:
      paths:
      - pathType: Prefix
        path: "/foo"
        backend:
          service:
            name: service2
            port:
              number: 80
              

인그레스 실습

레플리카셋, 노드포트 서비스, 인그레스 용 파드를 만든다.


# 인그레스용 파드 내용
vi myapp-ing.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myapp-ing
spec:
  defaultBackend:      # 밑에 룰에 의해서 라우팅 되지 않았을 떄 기본으로 라우팅되는 서비스를 의미
    service:
      name: myapp-svc-np
      port:
        number: 80
                     # 라우팅 규칙을 의미, path: 도메인 이름 뒤에 나오는 경로(예시. www.exple.com/testpath)
                     # backend: 인그레스 리소스가 보고있는 백엔드인 서비스를 의미      
  rules:             
  - host: www.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: myapp-svc-np
            port:
              number: 80


# 레플리카셋, 노드포트 서비스는 위에서 했던 것과 동일
kubectl create -f myapp-rs.yaml
kubectl create -f myapp-svc-np.yaml
kubectl create -f myapp-ing.yaml
  • 시간이 지나면 IP가 잡히는데 컨트롤러를 제외한 노드의 IP가 잡히는 것이다. 이는 nginx-ingress-controller가 없기 때문에 컨트롤러는 제외된 것이다.
# ingress정보 보기
kubectl get ing
# rules를 확인해보면 호스트와 경로, 백엔드를 확인가능
kubectl describe ing myapp-ing

# ingress-nginx에 있는 파드들 확인 
kubectl get po -n ingress-nginx -o wide
  • 만약 위 ingress의 내용에서 host를 제외했으면 IP 주소로 접속(curl 192.168.56.21)이 가능했지만 지금은 호스트인 myapp.example.com/ 이것으로 접속해야 하기때문에 IP 주소로 접속이 불가능하다.
# 호스트를 설정했기 때문에 인그레스 룰 정책에 매칭되는것이 없어서 404 Not Found가 나타남
# -v 옵션으로 http요청과 응답을 확인가능(>: 요청, <: 응답)
curl 192.168.56.21
  • 도메인 이름으로 접속하는 방법이 존재하는데 하나는 --resolve 옵션을 이용하는것, 다른 하나는 /etc/hosts에 도메인 이름을 등록하는 방법이 있다. 하지만 이는 내부에서만 접속이 가능하고 외부에서는 접근이 불가능하다.
# 편법으로 도메인 이름으로 접속하는 방법
curl --resolve www.example.com:80:192.168.56.21 http:www.example.com 

# /etc/hosts에 등록하는 방법, 추가
sudo vi /etc/hosts

192.168.56.21 www.example.com

# 내부에서 접속
curl http://www.example.com

스토리지 - 볼륨

컨테이너 내의 디스크에 있는 파일은 임시적이며, 컨테이너에서 실행될 때 애플리케이션에 적지 않은 몇 가지 문제가 발생한다.
한 가지 문제는 컨테이너가 크래시될 때 파일이 손실된다는 것이다. kubelet은 컨테이너를 다시 시작하지만 초기화된 상태이다.
두 번째 문제는 Pod에서 같이 실행되는 컨테이너간에 파일을 공유할 때 발생한다. 쿠버네티스 볼륨 추상화는 이러한 문제를 모두 해결한다. 파드에 대해 익숙해지는 것을 추천한다.

kubectl explain pod.spec.volumes

emptyDir

emptyDir 볼륨은 파드가 노드에 할당될 때 처음 생성되며, 해당 노드에서 파드가 실행되는 동안에만 존재한다. 이름에서 알 수 있듯이 emptyDir 볼륨은 처음에는 비어있다.
파드 내 모든 컨테이너는 emptyDir 볼륨에서 동일한 파일을 읽고 쓸 수 있지만, 해당 볼륨은 각각의 컨테이너에서 동일하거나 다른 경로에 마운트될 수 있다. 어떤 이유로든 노드에서 파드가 제거되면 emptyDir 의 데이터가 영구적으로 삭제된다.

즉, 동일한 내용의 파일을 공유해야하는 경우에 사용하는 것이고 예외적으로 파드의 라이프사이클과 함께가는 볼륨이다.

  • emptyDir 의 일부 용도

    • 디스크 기반의 병합 종류와 같은 스크레치 공간
    • 충돌로부터 복구하기위해 긴 계산을 검사점으로 지정
    • 웹 서버 컨테이너가 데이터를 처리하는 동안 컨텐츠 매니저 컨테이너가 가져오는 파일을 보관
  • 환경에 따라, emptyDir 볼륨은 디스크, SSD 또는 네트워크 스토리지와 같이 노드를 지원하는 모든 매체에 저장된다.

  • 그러나, emptyDir.medium 필드를 "Memory"로 설정하면, 쿠버네티스에 tmpfs(RAM 기반 파일시스템)를 마운트하도록 할 수 있다.
    tmpfs는 디스크와 다르게 매우 빠르다. 하지만 디스크와 다르게 노드 재부팅시 tmpfs가 지워지고, 작성하는 모든 파일이 컨테이너 메모리 제한에 포함된다.

# 스토리지 마운트
vi myapp-rs-emptydir.yaml

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: myapp-rs-fortune
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp-rs-fortune
  template:
    metadata:
      labels:
        app: myapp-rs-fortune
    spec:                 # 파드의 스펙
      containers:
      - name: web-server
        image: nginx:alpine
        volumeMounts:           # 컨테이너와 볼륨을 마운트 시키는 부분, 아래쪽 이름과 매칭됨
        - name: web-fortune
          mountPath: /usr/share/nginx/html    # nginx의 문서경로
          readOnly: true
        ports:
        - containerPort: 80
      - name: html-generator           
        image: ghcr.io/c1t1d0s7/fortune
        volumeMounts:
        - name: web-fortune
          mountPath: /var/htdocs       # http의 문서경로
      volumes:       # 위 컨테이너와 동일한 들여쓰기, 어떤 스토리지를 사용할지와 이름을 정해줘야함
      - name: web-fortune
  
  emptyDir: {}       # {}의 의미: default값을 사용한다는 의미, medium은 local disk, 사이즈는 제한없음

->  똑같은 볼륨을 서로 다른 위치에 마운트 하고있다. 즉 2개의 컨테이너가 같은 볼륨을 바라보고 있다는 것이다.

# 로드 밸런스 서비스 생성        
vi myapp-svc-emptydir.yaml
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc-fortune
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: myapp-rs-fortune  


# 서비스와 emptyDir 파드 생성
kubrctl create -f myapp-rs-emptydir.yaml       
kubectl create -f myapp-svc-emptydir.yaml


kubectl get rs,po,svc,ep

# 3초마다 새로운 내용을 갱신된다. 이는 fortune의 역할
curl 192.168.56.200

# 파드의 내용 확인해보기, volume의 내용!
kubectl describe myapp-svc-fortune
  • web-server는 ro(readOnly)로 마운트, html-generator는 rw(readWrite)로 마운트. 즉 html-generator에서 만들어낸 index.html을 같은 스토리지를 공유하고 있기 때문에 web-server에서 사용할 수 있는 것이다.
  • 동일한 파드 내에 여러개의 컨테이너가 존재하는 경우 -c옵션으로 컨테이너명을 입력해 다르게 구분한다.
# 컨테이너에 접속
kubectl exec myapp-rs-fortune-w9wz2 --sh
-> 파드에 컨테이너가 2개기 때문에 오류가 난다.

# 각 컨테이너의 로그 확인, -c옵션 사용
kubectl logs myapp-rs-fortune-w9wz2 -c web-server 
kubectl logs myapp-rs-fortune-w9wz2 -c html-generator



# html-generator의 쉘 실행
kubectl exec myapp-rs-fortune -it -c html-generator --sh
cd /var/htdocs
# 시간이 지날때마다 내용이 변경되는 것을 확인
cat index.html


# 쉘 스크립트로 내용이 변경되도록 작성해 둔 파일 확인, 이로인해 내용이 변경되는 것이다.
cd /bin
cat fortune.sh

# web-server의 쉘 실행
kubectl exec myapp-rs-fortune -it -c web-server --sh
cd /usr/share/nginx/html
# 이 파일이 스토리지에 의해 연결된 것
cat index.html

gitRepo

지금은 사용할 수 있지만 나중에 사라진다고 한다. git repo가 있는 컨테이너를 프로비전 하려면 초기화 컨테이너(InitContainer)에 EmptyDir을 마운트하고, 여기에 git을 사용해서 repo를 복제하고, EmptyDir을 파드 컨테이너에 마운트 한다.

  • 깃으로 동기화시켜서 볼륨을 제공하는 형태는 매우 많이 사용하는데 사라지기 때문에 대안을 가져왔다.
vi myapp-pod-git.yaml
apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod-git
spec:
  initContainers:            # 초기화 컨테이너
    - name: git-clone
      image: alpine/git     # git 이미지
      args:             # CMD 배치: git clone ...  명령어를 의미
        - clone
        - --single-branch
        - --
        - https://github.com/kubernetes/kubernetes     # 쿠버네티스 소스코드
        - /repo
      volumeMounts:
        - name: git-repository
          mountPath: /repo
  containers:
    - name: git-container
      image: busybox                 # 2MB짜리 작은 리눅스의 일종, 이는 쉘을 실행한다.
      args: ['tail', '-f', '/dev/null']    # 아무것도 없는 장치(/dev/null)를 tail -f를 하면 영구적으로 프로세스를 살아있게 만든다. 
                                           # 이는 컨테이너를 안죽게 만들기 위함이다.
      volumeMounts:
        - name: git-repository
          mountPath: /repo
  volumes:
    - name: git-repository      
      emptyDir: {}
      
2개의 창을 사용하여 초기화 컨테이너가 종료된 후 메인 컨테이너가 실행되는 것을 확인
# 실시간으로 상황 확인
watch -n1 -d kubectl get pods

# 파드 생성      
kubectl create -f myapp-pod-git.yaml 

# 컨테이너가 생성된 이후 접속하여 /repo 디렉터리에 소스코드가 다운되어있는 것을 확인
kubectl exec myapp-pod-git -it -c git-container --sh
cd /repo
  • init 컨테이너가 먼저 볼륨에 정보를 채워넣고 종료된다. 그후 메인 컨테이너가 실행되고 정보가 채워져있는 볼륨을 사용하는 것이다.

  • alpine: 비즈박스로 만든 리눅스의 일종, 패기지 관리자가 존재하지 않는다.(yum, apt 등) 따라서 모든걸 다 컴파인 해줘야한다. 일반 것과 동일하게 작동하는데 용량이 적다는 장점이 있다.

  • containers: Main 어플리케이션
    initContainers: 보조 어플리케이션으로 종료가 무조건 되어야한다. 즉 메인 컨테이너가 시작되기전에 초기화 작업을 하기위해 실행된다고 보면 된다. 종료를 보장해야되기 때문에 프로브를 설정할 수 없다.

    • 순서: 초기화 컨테이너 실행 -> 종료 -> 메인 컨테이너 실행
profile
전공 소개

0개의 댓글