본문 바로가기

개인공부

쿠버네티스 : 무작정 따라해보자. 초보자 / 듀토리얼

반응형

다음일 이용해서 로컬 환경에서의 쿠버네티스 실습을 위한 환경설정을 한다.

aws있으면 그걸로한다. (하루에 천원정도 발생)

https://redbinalgorithm.tistory.com/709

 

쿠버네티스 : minikube , kubelctl 로 시작해보기

실습 실제로 운영 환경에서 쿠버네티스를 적요하기 위해서는 최소 3대의 마스터 서버와 컨테이너 배포를 위한 N개의 노드서버 로드밸런서(프록시)가 필요합니다. 쿠버네티스 학습이 목표이기

redbinalgorithm.tistory.com

 

기본적인 명령어

minikube status

minikube start

minikube start --driver=hyperkit

minikube ip

minikube stop

minikube delete

 

일단 아무거나 띄어보기

 

실습용 도커 컴포즈 배포

version: "3"

services:
  wordpress:
    image: wordpress:5.5.3-apache
    environment:
      WORDPRESS_DB_HOST: mysql
      WORDPRESS_DB_PASSWORD: password
    ports:
      - "30000:80"
      
  mysql:
    image: mysql:5.6
    environment:
      MYSQL_ROOT_PASSWORD: password

해당 경로로 들어가서 docekr compose를 실행시켜주자.

그러면 docker필요한 이미지 다운받고 알아서 run 까지 실행

 

도커란 정말 좋은것 같다.. 이거없으면 어떻게 개발해

 

도커를 모른다면 docker와 docekr-compose 두개를 학습

https://docs.docker.com/opensource/

 

Contribute to documentation

 

docs.docker.com

 

도커 컴포즈 실행

docker-compose up -d

 

잘 실행되는 모습.. 이제 준비는 끝낫다

잘되는거 확인 했으니 docker 내린다음 이제 쿠버네티스로 적용해보자.

docker-compose down

 

쿠버네티스로 배포 하기에 앞서 WordPress라는 컨테이너는 쿠버네티스에서는 Pod라는 개념으로 실행되게 된다.

 

Pod < ReplicaSet < Deployment 로 감싸는 식으로 구성되어 있고 

 

외부 NodePort에 접속하면 내부 ClusterIp를 이용해서 Pod과 통신하게 된다.

 

쿠버네티스 설정 파일

wordpress-k8s.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpress-mysql
  labels:
    app: wordpress
spec:
  selector:
    matchLabels:
      app: wordpress
      tier: mysql
  template:
    metadata:
      labels:
        app: wordpress
        tier: mysql
    spec:
      containers:
        - image: mariadb:10.7
          name: mysql
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: password
          ports:
            - containerPort: 3306
              name: mysql

---
apiVersion: v1
kind: Service
metadata:
  name: wordpress-mysql
  labels:
    app: wordpress
spec:
  ports:
    - port: 3306
  selector:
    app: wordpress
    tier: mysql

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  selector:
    matchLabels:
      app: wordpress
      tier: frontend
  template:
    metadata:
      labels:
        app: wordpress
        tier: frontend
    spec:
      containers:
        - image: wordpress:5.5.3-apache
          name: wordpress
          env:
            - name: WORDPRESS_DB_HOST
              value: wordpress-mysql
            - name: WORDPRESS_DB_PASSWORD
              value: password
          ports:
            - containerPort: 80
              name: wordpress

---
apiVersion: v1
kind: Service
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  type: NodePort
  ports:
    - port: 80
  selector:
    app: wordpress
    tier: frontend

 

실행 (wordpress-k8s 에 적용된 내용을 쿠버네티스에 적용하겠다라는 내용)

kubectl apply -f wordpress-k8s.yml

deploment와 service가 생성되었다.

다음 명령어로 쿠버네티스에 어떤것이 있는지 알 수 있다.

kubectl get all

그럼 아까 30000이라고 임의로 주었던 포트가 쿠버네티스는 동적으로 30842라고 할당한것을 볼 수 있다.

접속하고싶으면 minikube ip에서 조회되는 ip와 포트번호로 접속하면 도커 컴포즈와 똑같은 실행을 볼 수 가 있다.

 

하지만 쿠버네티스로 실행 했기 때문에 내가 임의로 워드프로세스를 죽인다면 어떻게 될까??

kubectl delete {NAME}

죽였다...

하지만 얼마 후 다시 서버가 재실행 되는 것을 볼 수 있다.

 

와 쿠버네티스 개쩐다..

 

근데 실제 서버에서는 한대로 한다면 문제가 있지 않을까?? 설정파일에 replicas 설정을 추가하자.

50번째 코드에 스펙을 추가하자.

한번더 설정 적용

kubectl apply -f wordpress-k8s.yml

 

그럼 이렇게 추가된것을 확인 할 수 있음..

이제 다음 실습을 위해서 제거합니다.

 

kubectl delete -f wordpress-k8s.yml

 

기본 명령어

명령어 설명
apply 원하는 상태를 적용합니다. -f 와 함께 사용
get 리소스 목록 확인 : all pod node 자주씀 옵션으로 -o wide
describe 리소스의 상태를 자세하게 보여준다
delete 리소스를 제거
logs 컨테이너의 로그 확인
exec 컨테이너에 명령어를 전달. 컨테이너에 접근할 때 주로 사용함 (exec -it {name} -- sh || bash)
config kubectl 설정 관리

 

apply

 

배포에서 사용하는 명렁어이다. 원하는 리소스의 상태를 yml 으로 작성 후 사용한다.

kubectl apply -f [파일명 || URL]

kubectl get pod -o wide : IP같은 상세 옵션 보기

kubectl get pod -o yaml : yaml 으로 보기 (CI 할때 파싱해서 활용가능)

kubectl get pod --show-labels : 현재 pod에 할당된 레이블을 확인할 수 있음

 

descrive 리소스 상세보기

get으로 못봣던애들 상세하게 볼 수 있음 pod으로 떠야하는데 안떳을 때 확인해야하는데 이때 dscribe를 사용해서 확인한다.

kubectl describe [TYPE]/[NAME] 또는 [TYPE][NAME]

 

Pod에 로그를 보고 싶을 때 사용

kubectl logs [NAME]

 

Pod에 접속하고 싶을 때

kubectl exec -it [NAME] -- bash

config

kubectl config current-context // 현재 컨텍스트 확인

kubectl config use-context minikube // 컨텍스트 설정

 

Pod

 

Pod은 쿠버네티스에서 관리하는 가장 작은 배포단위입니다.

 

pod안에는 하나의 컨테이너또는 여러개의 컨테이너를 만들 수 있다.

 

Pod 생성

kubectl run echo --image ghcr.io/subicura/echo:v1

생성되었다.

Pod 상태를 확인해보자.

kubectl describe pod/echo

 

어떻게 생성되었는지 알 수 잇음.

제거 해보자

kubectl delete pod/echo

 

근데 보통은 이렇게 명렁어로 쓰지 않고 yaml 파일에 설정을 통해서 관리한다.

 

echo-pod.yml 생성

apiVersion: v1
kind: Pod
metadata:
  name: echo
  labels:
    app: echo
spec:
  containers:
    - name: app
      image: ghcr.io/subicura/echo:v1

- apiVersion, kind,metadata 는 필수 값

 

쿠버네티스 컨트롤러 적용

kubectl apply -f echo-pod.yml

pod을 만들 때는 조심해야 할 점은 상태를 모니터링 해야한다. 그럴때 사용하는 것이 livenessProbe 를 사용한다.

apiVersion: v1
kind: Pod
metadata:
  name: echo-lp
  labels:
    app: echo
spec:
  containers:
    - name: app
      image: ghcr.io/subicura/echo:v1
      livenessProbe:
        httpGet:
          path: /not/exist
          port: 8080
        initialDelaySeconds: 5
        timeoutSeconds: 2 # Default 1
        periodSeconds: 5 # Defaults 10
        failureThreshold: 1 # Defaults 3

- initalDelaySecond : 기다렷다가 path 경로에 접속해서 실행

- failureThreadhold 1번이라도 실패하면 재시작하겠다 라는 뜻

- path : 일부러 없는 패스를 만들어서 실패를 유도함 상태를 확인하면

 

보면 2번 재시작햇다고뜸

 

readinessProbe : livenessProbe는 재시작하는 거라면 컨테이너가 정상적으로 준비되어 있지 않으면 Pod으로 들어오는 요청을 제외합니다.

 

apiVersion: v1
kind: Pod
metadata:
  name: echo-rp
  labels:
    app: echo
spec:
  containers:
    - name: app
      image: ghcr.io/subicura/echo:v1
      readinessProbe:
        httpGet:
          path: /not/exist
          port: 8080
        initialDelaySeconds: 5
        timeoutSeconds: 2 # Default 1
        periodSeconds: 5 # Defaults 10
        failureThreshold: 1 # Defaults 3

레디니스는 재시작하지않고 그냥 가마니 있음.

 

이것 두개를 적절히 쓰면 어떻게 될까 livenessProbe + readinessProbe

apiVersion: v1
kind: Pod
metadata:
  name: echo-health
  labels:
    app: echo
spec:
  containers:
    - name: app
      image: ghcr.io/subicura/echo:v1
      livenessProbe:
        httpGet:
          path: /
          port: 3000
      readinessProbe:
        httpGet:
          path: /
          port: 3000

 

다중 컨테이너

하나의 Pod에 속한 컨테이너는 서로 네트워크를 localhost로 공유하고 동일한 디렉토리를 공유 할 수 잇음

 

apiVersion: v1
kind: Pod
metadata:
  name: counter
  labels:
    app: counter
spec:
  containers:
    - name: app
      image: ghcr.io/subicura/counter:latest
      env:
        - name: REDIS_HOST
          value: "localhost"
    - name: db
      image: redis

컨테이너가 2개임

logs를 사용하고 싶다면 컨테이너가 하나이기 때문에 생략해도 되지만 이제는 pod을 명시해줘야함

kubectl logs counter db || app

카운터 컨테이너에 접속

kubectl exec -it counter -c app -- sh

kubectl get po 한다음 delete 로 다삭제

현재 경로의 yml파일 설정 다삭제 가능

kubectl delete -f ./

 

ReplicaSet

Pod을 단독으로 만들면 Pod에 어떤 문제가 생겼을 때 자동으로 복구되지 않습니다. 이러한 Pod을 정해진 수만큼 복제하고 관리하는 것이 ReplicaSet입니다.

 

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: echo-rs
spec:
  replicas: 1
  selector:
    matchLabels:
      app: echo
      tier: app
  template:
    metadata:
      labels:
        app: echo
        tier: app
    spec:
      containers:
        - name: echo
          image: ghcr.io/subicura/echo:v1

- replicas: 몇개 사용?

- selector : 어떤 레이블을 찾을 거냐? 여기선 app은 echo면서 tier는 app

- template: 만약 셀렉터에서 못찾으면 template에서 pod을 만든다

레플리카셋을 만들었는데 pod 이 만들어짐

이걸 보면 레플리카셋이 pod을 관리하는 거라고 알 수 있다. 여기서 중요한점은 pod의 레이블을 보고 레플리카셋이 관리한다는 것이다.

레이블의 정보를 변경하면 레플리카셋이 자동으로 할당하거나 제거한다.

 

Deployment

ReplicaSet은 단독으로 사용하지 않고 Deployment를 이용해서 ReplcaSet을 사용한다.

 

apiVersion: apps/v1
kind: Deployment
metadata:
  name: echo-deploy
spec:
  replicas: 4
  selector:
    matchLabels:
      app: echo
      tier: app
  template:
    metadata:
      labels:
        app: echo
        tier: app
    spec:
      containers:
        - name: echo
          image: ghcr.io/subicura/echo:v1

이전 레플리카셋과 대부분 차이는 없다.

 

실행후 get all 해보면 다음과 같이 뜬다.

 

여기서 만약 yml의 설정을 변경하고 다시 실행하면 어떻게 될까?

기존의거는 아직 실행중이고 새로운것을 생성하고있다. 다시 조회해보면

버전을 pod를 레플리카셋이 변경한다. 

 

1. 버전을 업데이트하면 새로운 래플리카셋을 만든다.

2. 새로 만들어진 레플리카와 기존에 있던 레플리카가 존재하고 Pod의 개수를 조절해가면서 다음버전의 v2가 있는 리플리카셋의 개수를 늘려나가면서 이전한다.

3. 기존에 있던 레플리카가 0개가 되면 사라진다.

 

kubectl describe deploy/echo-deploy

레플리카 셋을 조절하는 deployment..

버전관리

Deployment는 변경된 상태를 기록합니다.

 

# 히스토리 확인
kubectl rollout history deploy/echo-deploy

# revision 1 히스토리 상세 확인
kubectl rollout history deploy/echo-deploy --revision=1

# 바로 전으로 롤백
kubectl rollout undo deploy/echo-deploy

# 특정 버전으로 롤백
kubectl rollout undo deploy/echo-deploy --to-revision=2
kubectl rollout history deploy/echo-deploy

만약 버전이 문제있어서 롤백해야한다면 명령어들을 이용해서 롤백할 수도 있다.

 

 

배포전략 설정

apiVersion: apps/v1
kind: Deployment
metadata:
  name: echo-deploy-st
spec:
  replicas: 4
  selector:
    matchLabels:
      app: echo
      tier: app
  minReadySeconds: 5
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 3
      maxUnavailable: 3
  template:
    metadata:
      labels:
        app: echo
        tier: app
    spec:
      containers:
        - name: echo
          image: ghcr.io/subicura/echo:v1
          livenessProbe:
            httpGet:
              path: /
              port: 3000

RollingUpdate라는 전략 설정

한번에 하나식 업데이트되던걸 3개식 변경되도록 설정을 추가함

 

Service

지금까지는 컨테이너를 관리하는 법을 배웠다면 이 컨테이너를 외부에 노출하는 방법을 배워보자.

Pod은 자체 IP를 가지고 다른 Pod과 통신하지만 계속 변경되서 사용하기 어렵다 그래서

Service(ClusterIp)를 이용해서 다른 Pod들과 통신하게 된다.

 

apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
spec:
  selector:
    matchLabels:
      app: counter
      tier: db
  template:
    metadata:
      labels:
        app: counter
        tier: db
    spec:
      containers:
        - name: redis
          image: redis
          ports:
            - containerPort: 6379
              protocol: TCP

---
apiVersion: v1
kind: Service
metadata:
  name: redis
spec:
  ports:
    - port: 6379
      protocol: TCP
  selector:
    app: counter
    tier: db

service를 생성하게되는데 redis란 이름으로 등록된다. 고정 ip가 할당되면서 6379 포트를 통해서 pod의 레디스와 통신이 가능하다.

특이한점은 같은 클러스터에서 생성된 Pod이라면 redis라는 도메인으로 redis Pod에 접근 할 수 있다.

 

spec.ports.targetPort 도 설정해줘야하지만 containerPort와 port가 동일하기 때문에 생략가능하다.

 

app도 만들어본다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: counter
spec:
  selector:
    matchLabels:
      app: counter
      tier: app
  template:
    metadata:
      labels:
        app: counter
        tier: app
    spec:
      containers:
        - name: counter
          image: ghcr.io/subicura/counter:latest
          env:
            - name: REDIS_HOST
              value: "redis"
            - name: REDIS_PORT
              value: "6379"

 

NodePort 

이전 가지는 kubctl 명령어를 이용해서 배시셀을 시용해서 접근가능 했다. 이제는 브라우저에서도 접근 가능하게 외부 포트를 만들어보자. 그게 노드 포트다

 

apiVersion: v1
kind: Service
metadata:
  name: counter-np
spec:
  type: NodePort
  ports:
    - port: 3000
      protocol: TCP
      nodePort: 31000
  selector:
    app: counter
    tier: app

- 타입을 추가해야 NodePort를 해야한다. nodePort: <- 실제로 오픈되는 노드번호 내부적으로는 3000 외부적으로는 31000

- minikube ip를 이용해서 외부로 접속해보자.

 

이제 클러스터 외부에서도 접속 할수 있다.

 

LoadBalancer 만들기

 

minikube에 가상 LoadBalacer 만들기

Load Balancer를 사용할 수 없는 환경에서 가상 환경을 만들어 주는 것이 MetalLb 라는 것이다. minikube에서는 현재 떠 있는 노드를 Load Balancer로 설정합니다. minikube의 addons 명령어로 활성화합니다.

 

apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses:
      - 192.168.64.2/32

config-Map을 설정한다. addresss는 minkube ip를 적습니다.

 

상태를 확인하면 <pending> 이라고 뜨던게 서버가 할당되어있다.

 

 

특별한 상황이 아니라면 LoadBalacer 를 이용한다 NodePort 보다

반응형

'개인공부' 카테고리의 다른 글

MySQL 쿼리 성능 진단  (0) 2022.03.15
MySQL의 특징  (0) 2022.03.14
쿠버네티스 : minikube , kubelctl 로 시작해보기  (0) 2022.02.04
YAML 문법  (1) 2022.02.04
Server 용어정리  (0) 2021.12.07