본문 바로가기
도커&쿠버네티스

[katakoda] Deploying from source onto Kubernetes

by bzerome240 2022. 4. 3.

컨테이너에 포함되는 것
1) 소스 코드의 컴파일된 버전 
2) 소스 코드를 실행하는 데 필요한 모든 런타임 종속성

 
 
이 튜토리얼에서 Docker를 컨테이너 형식으로 사용합니다. 
우리는 hello-webapp인 Python으로 간단한 웹 애플리케이션을 만들었습니다. 
웹앱을 Docker 컨테이너로 패키징하기 위해 Dockerfile을 생성합니다.

dockerfile

# Run server
FROM alpine:3.5
RUN apk add --no-cache python py2-pip py2-gevent
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . /app
WORKDIR /app
EXPOSE 8080
ENTRYPOINT ["python"]
CMD ["app.py"]

 

 

Dockerfile을 읽은 다음 웹 앱을 실행하는 데 필요한 모든 것이 포함된 바이너리 이미지를 빌드한다.

docker build -t hello-webapp:v1 .

 

 

컨테이너 실행하기

이 명령은 컨테이너를 실행하고 컨테이너의 포트 8080을 호스트 포트 80에 매핑합니다.

docker run -d -p 80:8080 hello-webapp:v1

 

 

웹 앱이 성공적으로 실행 중인지 확인할 수 있습니다.

이제 host01의 포트 80으로 HTTP 요청을 보내고 컨테이너의 8080에 매핑됩니다.

curl host01

 

 

쿠버네티스가 왜 필요한가요? 
요컨대 Kubernetes는 컨테이너 실행의 모든 ​​세부 사항을 처리합니다. 
컨테이너를 실행할 VM/서버, 컨테이너에 적절한 양의 메모리/CPU/등이 있는지 확인합니다.

Kubernetes가 컨테이너 실행 방법을 알기 위해서는 Kubernetes 매니페스트가 필요합니다.

hello-webapp 서비스에 대한 Kubernetes 매니페스트 YAML

Docker 이미지에 대한 포인터, 메모리/CPU 제한 및 노출된 포트를 포함하여 서비스에 대한 몇 가지 주요 정보가 포함되어 있음을 알 수 있습니다.

---
apiVersion: v1
kind: Service
metadata:
  name: hello-webapp
spec:
  selector:
    app: hello-webapp

  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
  type: NodePort

---
apiVersion: extensions/v1beta1
kind: Deployment
metadata: {name: hello-webapp}
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hello-webapp
      track: stable
  strategy:
    rollingUpdate: {maxSurge: 1, maxUnavailable: 0}
    type: RollingUpdate
  revisionHistoryLimit: 1
  template:
    metadata:
      labels:
        app: hello-webapp
        track: stable
      name: hello-webapp
    spec:
      containers:
      - image: IMAGE_URL
        imagePullPolicy: IfNotPresent
        name: hello-webapp
        resources:
          limits:
            memory: 0.25G
            cpu: 0.25
        terminationMessagePath: /dev/termination-log
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      securityContext: {}
      terminationGracePeriodSeconds: 30

 

 

이제 우리는 런타임 구성을 갖게 되었습니다.
1) 컨테이너에서 실행할 코드
2) Kubernetes 매니페스트에서 코드를 실행하는 방법

 

이제 실제로 컨테이너를 실행하기 전에 구성 요소가 하나 더 필요합니다. 바로 컨테이너 레지스트리입니다.

 


 

Kubernetes 클러스터가 이미지를 실행하려면 이미지 사본을 가져와야 합니다.

일반적으로 이미지를 호스팅하는 중앙 서비스인 컨테이너 레지스트리를 통해 이 작업을 수행합니다. 
온프레미스 및 클라우드 전용 사용 사례 모두에 대해 컨테이너 레지스트리에 대한 수십 가지 옵션이 있습니다.

이 튜토리얼에서 Katacoda 환경은 빌드된 이미지를 저장할 개인 Docker 레지스트리를 프로비저닝했습니다. 

 


레지스트리 URL을 환경 변수로 설정하기

export REGISTRY=2886795290-5000-simba09b.environments.katacoda.com

 


Docker 이미지를 레지스트리에 푸시하려면 Docker 리포지토리 이름이 포함된 Docker 이미지에 대한 태그를 생성해야 합니다.

docker tag hello-webapp:v1 $REGISTRY/hello-webapp:v1



이미지를 Docker 레지스트리에 푸시하기

docker push $REGISTRY/hello-webapp:v1



이제 실제로 Kubernetes에서 이 서비스를 실행해 보겠습니다. 
특정 서비스의 이미지를 가리키도록 deployment.yaml 파일을 업데이트해야 합니다.
IMAGE_URL 변수를 사용하여 배포 파일을 템플릿화했습니다. 그런 다음 sed 명령으로 인스턴스화합니다.

sed -i -e 's@IMAGE_URL@'"$REGISTRY/hello-webapp:v1"'@' deployment.yaml

 

YAML

---
apiVersion: v1
kind: Service
metadata:
  name: hello-webapp
spec:
  selector:
    app: hello-webapp

  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
  type: NodePort

---
apiVersion: extensions/v1beta1
kind: Deployment
metadata: {name: hello-webapp}
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hello-webapp
      track: stable
  strategy:
    rollingUpdate: {maxSurge: 1, maxUnavailable: 0}
    type: RollingUpdate
  revisionHistoryLimit: 1
  template:
    metadata:
      labels:
        app: hello-webapp
        track: stable
      name: hello-webapp
    spec:
      containers:
      - image: 2886795290-5000-simba09b.environments.katacoda.com/hello-webapp:v1
        imagePullPolicy: IfNotPresent
        name: hello-webapp
        resources:
          limits:
            memory: 0.25G
            cpu: 0.25
        terminationMessagePath: /dev/termination-log
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      securityContext: {}
      terminationGracePeriodSeconds: 30

 

 

Kubernetes 클러스터에 액세스하려면 마스터에서 Kubernetes 구성 파일을 다운로드해야 합니다. 
구성 파일에는 Kubernetes와 안전하게 통신하는 데 필요한 IP 주소 및 인증서가 포함되어 있습니다.

scp -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no root@host01:/root/.kube/config ~/.kube/

 

 

kubectl apply -f deployment.yaml



 

이제 서비스에 HTTP 요청을 보내려고 합니다. 
대부분의 Kubernetes 서비스는 명백한 이유로 인터넷에 노출되지 않습니다. 
따라서 클러스터에서 실행 중인 서비스에 직접 액세스할 수 있어야 합니다.

 

 

이제 서비스에 HTTP 요청을 보내려고 합니다. 
대부분의 Kubernetes 서비스는 명백한 이유로 인터넷에 노출되지 않습니다. 
따라서 클러스터에서 실행 중인 서비스에 직접 액세스할 수 있어야 합니다.



서비스가 배포될 때 동적 NodePort가 Pod에 할당되었습니다.

 

 

나중에 사용할 수 있도록 할당된 포트를 변수로 저장합니다.

export PORT=$(kubectl get svc hello-webapp -o go-template='{{range.spec.ports}}{{if .nodePort}}{{.nodePort}}{{"\n"}}{{end}}{{end}}')



이제 서비스에 HTTP 요청을 보낼 수 있습니다.

curl host01:$PORT



우리는 방금 4가지 주요 작업을 수행했습니다. 
1) 컨테이너 생성 
2) Kubernetes 매니페스트 생성 
3) 컨테이너를 레지스트리에 푸시하고
4) 업데이트된 매니페스트를 사용하여 이 모든 부분을 Kubernetes에 알렸습니다.


따라서 이것은 여러 단계를 거쳐야 했으며 개발을 위해 하듯이 이 작업을 계속 반복해야 하는 경우 빠르게 지루해질 것입니다. 
보다 유용한 워크플로를 만들 수 있도록 이러한 단계를 스크립트로 작성하는 방법을 간단히 살펴보겠습니다.

 

 

귀하의 서비스는 이제 Hacker News에 있으며 사용자 정의 인사말을 만들고 싶습니다. 소스 코드 중 일부를 변경해 보겠습니다.

sed -i -e 's/Hello World!/Hello Hacker News!!!/' app.py



컨테이너를 다시 빌드하고 레지스트리에 푸시하고 배포를 편집할 수 있지만 이미 정확한 명령을 모두 잊어버렸을 것입니다. 그렇죠?

운 좋게도 Forge는 Kubernetes에 서비스를 배포하기 위한 오픈 소스 도구이며 이미 자동화(및 일부!)를 수행합니다. 
Forge를 사용하여 이 배포를 수행해 보겠습니다. 
Forge를 빠르게 설정해야 합니다.

forge setup



Forge를 설정하려면 Docker 레지스트리의 URL을 입력하십시오.

2886795290-5000-simba09b.environments.katacoda.com
forge deploy



Forge는 Docker 컨테이너(Dockerfile 기반)를 자동으로 빌드하고 컨테이너를 선택한 Docker 레지스트리에 푸시하고 이미지를 가리키는 deployment.yaml 파일을 빌드한 다음 컨테이너를 Kubernetes에 배포합니다.

Kubernetes가 기존 컨테이너를 종료하고 새 코드를 교체하므로 이 프로세스는 몇 분 정도 걸립니다. 
새 포트 전달 명령을 설정해야 합니다. 포드 상태를 다시 가져오겠습니다.

kubectl get pods



이전과 마찬가지로 배포에 할당된 NodePort를 가져옵니다.

export PORT=$(kubectl get svc hello-webapp -o go-template='{{range.spec.ports}}{{if .nodePort}}{{.nodePort}}{{"\n"}}{{end}}{{end}}')
curl host01:$PORT



소스 코드를 개발하고 Kubernetes에 배포하는 데 필요한 기본 개념을 적용했습니다.

728x90
반응형

댓글