• HOME
  • PRODUCT
  • DEVELOP
  • NEWS
  • CONSULTING
No Result
View All Result
illunex Blog
  • HOME
  • PRODUCT
  • DEVELOP
  • NEWS
  • CONSULTING
No Result
View All Result
일루넥스 블로그
No Result
View All Result

쿠버네티스로 운영 서버 구축하기

김 형진 by 김 형진
2020년 9월 14일
in DEVELOP, 백엔드
쿠버네티스로 운영 서버 구축하기

안녕하세요 일루넥스 개발팀 김형진입니다.
기존에 Spring Cloud와 Docker Swarm 으로 구축된 테스트 서버에서 Spring Cloud를 걷어내고
Kubernetes로 변경한 이야기를 할려고 합니다.

1. 젠킨스에서 도커 빌드 가능하게 설정하기

기존에 Docker Compose로 구성해서 서버에서 바로 docker 이미지를 만들었다면 이번에는 Jenkins에서 빌드를 해서 이미지를 생성하고 해당 이미지를 넥서스에 올린 후 각각의 서버에서 해당 이미지를 사용방식으로 만들려고 합니다. 가장 먼저 젠킨스에서 도커를 빌드하고 빌드된 이미지를 사내 dockerhub(Nexus)에 올릴 수 있게 해주어야 합니다. 도커로 구동된 젠킨스에서 도커를 실행하려면 docker.sock 파일을 볼륨해줘야 합니다.

sudo docker run -d -p 8080:8080 -v /home/jenkins:/var/jenkins_home -v /var/run/docker.sock:/var/run/docker.sock 

1.1 젠킨스 백업하기

만약 기존에 사용하던 젠킨스가 있다면 해당 젠킨스에 workspace폴더를 복사해 놓은 후에 새로 설치된 젠킨스에 덮어 씌우시면 됩니다.

2. 쿠버네티스 설정 사전작업

2.1 React 빌드 및 도커 이미지 만들기

먼저 프론트쪽 배포를 위해서 리액트 빌드를 해야 합니다. 그런데 이번에는 테스트 서버에만 배포하는 게 아닌 테스트와 실섭 두개로 구분을
해서 배포를 해야 하기 때문에 배포 설정을 해주어야 합니다. 그리고 빌드된 React파일은 Nginx 아래에서 실행이 됩니다.
또한 도커 이미지를 만들 때 빌드된 (build) 폴더가 실행되는 Nginx 서버에 설정을 위해 default.conf 설정파일을 미리 프로젝트 안에 준비
를 해놓습니다. 그리고 Dockerfile에 실행될 도커이미지의 설정을 작성합니다.

2.1.1. 서버에 따른 빌드 스크립트 package.json에 설정하기

"scripts": {
		  .
			.
    "build-test": "env-cmd -f .env.test react-scripts build",
    "build-dev": "env-cmd -f .env.dev react-scripts build",
    "build-prod": "env-cmd -f .env.prod react-scripts build",
			.
			.
  }, 

2.1.2. nginx 설정파일 만들기: conf/conf.d/default.conf 파일 만들기

server {
  listen 80;
  location / {
    root   /usr/share/nginx/html;
    index  index.html index.htm;
    try_files $uri $uri/ /index.html;
  }
  error_page   500 502 503 504  /50x.html;
  location = /50x.html {
    root   /usr/share/nginx/html;
  }
} 

2.1.3. Dockerfile 만들기

FROM nginx:1.13.9-alpine

EXPOSE 80

RUN rm -rf /etc/nginx/conf.d
COPY ./conf /etc/nginx
COPY ./build /usr/share/nginx/html

CMD ["nginx", "-g", "daemon off;"] 

Nginx를 기반으로 설정한 conf폴더와 빌드된 React폴더를 복사해 이미지 안에 넣고 Nginx를 시작한다.

2.2 Java 빌드 및 도커 이미지 만들기

자바 프로젝트를 Maven으로 빌드를 해서 도커이미지를 만들고 실행을 시킨다.

빌드

mvn clean install -Dmaven.test.skip=true -Pprod 

기존에 빌드되어 있던 파일을 지우고 빌드를 한다. 옵션으로는 테스트를 Skip하는 옵션과 프로파일을 설정했다.

Dockerfile

FROM openjdk:14-slim

EXPOSE  8081

ADD ./target/*.jar vc.jar

ENTRYPOINT ["java","-jar","/vc.jar"] 

오픈 JDK를 기반으로 각각의 프로젝트에 맞는 포트를 열어주고 빌드된 jar파일을 복사해서 이미지에 넣은 후 실행을 한다.

3. 쿠버네티스 설정하기

쿠버네티스를 AWS에서 설치해서 사용할 생각이며 사용할 툴로는 Kops를 사용할 생각이다.

3.1 kops 설치하기

먼저 kops를 사용할 인스턴스(CI서버)에 kops를 설치한다.
설치에 관련된 내용은 https://kops.sigs.k8s.io/getting_started/install/ 이 사이트에 자세히 나와있다.
일단 회사 CI 서버에 경우 우분투로 구성되어 있어서 리눅스 설치 명령어를 복사해서 실행시킨다.

curl -LO https://github.com/kubernetes/kops/releases/download/$(curl -s https://api.github.com/repos/kubernetes/kops/releases/latest | grep tag_name | cut -d '"' -f 4)/kops-linux-amd64
chmod +x kops-linux-amd64
sudo mv kops-linux-amd64 /usr/local/bin/kops 

3.2 AWS IAM 설정

AWS에서 IAM을 하나 설정한다. 필요한 권한으로는 아래 5가지 권한을 설정해 주면 된다.

  • AmazonEC2FullAccess
  • AmazonRoute53FullAccess
  • AmazonS3FullAccess
  • IAMFullAccess
  • AmazonVPCFullAccess

3.3 AWS CLI 설치&설정

기존에 설치된 AWSCLI가 없다면 설치를 해준다.

apt install awscli # awscli 설치

# aws 설정
aws configure
Access Key: [입력]
Secret Access Key: [입력]
Default region name: ap-northeast-2   # 한국 1은 일본
Default output format: [엔터] 

3.4 route53 설정

쿠버네티스 클러스터 정보가 저장될 S3 저장소를 하나 생성한다. 그리고 버킷에 버저닝을 기록하도록 설정한다.

aws s3api create-bucket --bucket [버킷이름] --create-bucket-configuration LocationConstraint=ap-northeast-1

aws s3api put-bucket-versioning --bucket [버킷이름] --versioning-configuration Status=Enabled 

3.5 ssh-key 설정

ssh-keygen -t rsa -N "" -f ./id_rsa 

3.6 쿠버네티스 클러스터 생성하기

kops create cluster --state [s3:저장소이름] --zones ap-northeast-1a - -networking calico --ssh-public-key ./id_rsa.pub [도메인 이름] 

3.7 노드 설정

kops edit ig master-ap-northeast-1a --name [도메인 이름] --state [s3:저장소이름]  # 마스터 노드 설정
kops edit ig nodes --name [도메인 이름] --state [s3:저장소이름] # 노드 설정\ 

3.8 쿠버네티스 클러스터 생성하기

kops update cluster --yes [도메인 이름] # 클러스터 생성하기
kops validate cluster --state [s3:저장소이름] # 진행사항 확인하기 

3.9 쿠버네티스에 private docker hub 설정하기

사내에 Docker Hub가 구축되어 있다면 해당 저장소에 이미지를 가져올 수 있게 설정을 해주어야 한다.

kubectl create secret docker-registry [시크릿 이름] 
	--docker-server=[사내 저장소 주소]
	--docker-username=[유저 이름]
	--docker-password=[비밀번호]
	--docker-email=[이메일] 

그리고 CI 서버에서 사내 Docker Hub에 이미지를 올려야 하기 때문에 저장소 설정을 해준다.

sudo vi /etc/docker/daemon.json

{
    "insecure-registries": ["저장소 주소"]
} 

마지막으로 쿠버네티스 pod을 만드는 설정안에 사내 저장소에 접근할 수 있게 설정을 추가한다.

imagePullSecrets:
        - name: [설정된 시크릿 이름] 

3.10 health 설정

쿠버네티스에 이미지가 배포 되었을 때 잘 실행이이 되었는 지 그리고 실행 중에 정지가 되지 않았는 지 확인을 하기 위한 설정을 해야합니다. Spring에 Actuator을 설정했고 쿠버네티스 설정파일에 해당 내용 관련 코드를 추가해준다.

livenessProbe:
  httpGet:
    path: /actuator/info
    port: 80
  initialDelaySeconds: 5
  periodSeconds: 10
  timeoutSeconds: 2
  failureThreshold: 10
  successThreshold: 1
readinessProbe:
  httpGet:
    scheme: HTTP
    path: /actuator/health
    port: 80
  initialDelaySeconds: 5
  periodSeconds: 10
  timeoutSeconds: 2
  failureThreshold: 3
  successThreshold: 1 

4. 젠킨스에서 배포 설정하기

자바 프로젝트의 경우 프로젝트를 빌드를 하고 빌드한 파일을 바탕으로 도커이미지 파일을 생성한다.
생성된 도커이미지파일을 사내 Docker-Hub에 올리고 쿠버네티스 노드로 배포한다.
올라가는 버전의 경우에는 따로 파라미터로 받아 설정한다.

#!/bin/bash
mvn clean install -Dmaven.test.skip=true -Pdev

docker build --tag docker.effectmall.com/startup-dev:v1.${major}.${minor} ./
docker push docker.effectmall.com/startup-dev:v1.${major}.${minor}

kubectl set image deployment startup startup-con=docker.effectmall.com/startup-dev:v1.${major}.${minor} --record --namespace=invest-dev 

5. 일래스틱 서치 설정해서 로그 가져오기

filebeat를 사용해서 일래스틱에 로그를 가져올 수 있게 한다.
아래 내용에 일래스틱 호스트 주소와 아이디 비밀번호를 설정해서 쿠버네티스에 등록한다.

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: filebeat-config
  namespace: default
  labels:
    k8s-app: filebeat
data:
  filebeat.yml: |-
    filebeat.inputs:
    - type: container
      paths:
        - /var/log/containers/*.log
      processors:
        - add_kubernetes_metadata:
            host: ${NODE_NAME}
            matchers:
            - logs_path:
                logs_path: "/var/log/containers/"
    processors:
      - add_cloud_metadata:
      - add_host_metadata:

    cloud.id: ${ELASTIC_CLOUD_ID}
    cloud.auth: ${ELASTIC_CLOUD_AUTH}

    output.elasticsearch:
      hosts: ['${ELASTICSEARCH_HOST:elasticsearch}:${ELASTICSEARCH_PORT:9200}']
      username: ${ELASTICSEARCH_USERNAME}
      password: ${ELASTICSEARCH_PASSWORD}
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: filebeat
  namespace: default
  labels:
    k8s-app: filebeat
spec:
  selector:
    matchLabels:
      k8s-app: filebeat
  template:
    metadata:
      labels:
        k8s-app: filebeat
    spec:
      serviceAccountName: filebeat
      terminationGracePeriodSeconds: 30
      hostNetwork: true
      dnsPolicy: ClusterFirstWithHostNet
      containers:
      - name: filebeat
        image: docker.elastic.co/beats/filebeat:7.5.2
        args: [
          "-c", "/etc/filebeat.yml",
          "-e",
        ]
        env:
        - name: ELASTICSEARCH_HOST
          value: [일래스틱 호스트 주소]
        - name: ELASTICSEARCH_PORT
          value: "9200"
        - name: ELASTICSEARCH_USERNAME
          value: elastic
        - name: ELASTICSEARCH_PASSWORD
          value: [비밀번호]
        - name: ELASTIC_CLOUD_ID
          value:
        - name: ELASTIC_CLOUD_AUTH
          value:
        - name: NODE_NAME
          valueFrom:
            fieldRef:
              fieldPath: spec.nodeName
        securityContext:
          runAsUser: 0
          # If using Red Hat OpenShift uncomment this:
          #privileged: true
        resources:
          limits:
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 100Mi
        volumeMounts:
        - name: config
          mountPath: /etc/filebeat.yml
          readOnly: true
          subPath: filebeat.yml
        - name: data
          mountPath: /usr/share/filebeat/data
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
        - name: varlog
          mountPath: /var/log
          readOnly: true
      volumes:
      - name: config
        configMap:
          defaultMode: 0600
          name: filebeat-config
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers
      - name: varlog
        hostPath:
          path: /var/log
      # data folder stores a registry of read status for all files, so we don't send everything again on a Filebeat pod restart
      - name: data
        hostPath:
          path: /var/lib/filebeat-data
          type: DirectoryOrCreate
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: filebeat
subjects:
- kind: ServiceAccount
  name: filebeat
  namespace: default
roleRef:
  kind: ClusterRole
  name: filebeat
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: filebeat
  labels:
    k8s-app: filebeat
rules:
- apiGroups: [""] # "" indicates the core API group
  resources:
  - namespaces
  - pods
  verbs:
  - get
  - watch
  - list
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: filebeat
  namespace: default
  labels:
    k8s-app: filebeat
--- 

마치며

여기까지 쿠버네티스로 운영서버 구축에 관한 내용이었습니다.
읽어주셔서 감사합니다.

Tags: Kubernetes도커운영서버쿠버네티스
ShareTweet
Previous Post

리엑트 네이티브 기본 강좌

Next Post

TRX(ERC20) 개발 Basic 2

Next Post
TRX(ERC20) 개발 Basic 2

TRX(ERC20) 개발 Basic 2

  • Copyright © 2020 illunex., Inc., All Rights Reserved.
  • 개인정보보호정책
No Result
View All Result
  • HOME
  • PRODUCT
  • DEVELOP
  • NEWS
  • CONSULTING