k8s

문성하·2023년 9월 26일
0

k8s

목록 보기
3/6

k8s

컨테이너 한 개로 어플리케이션을 구동한다면 기존 방식도 나쁘지 않습니다.
하지만 요즘 서비스 규모가 커지며 마이크로 서비스 아키텍처가 트랜드입니다.
한 개의 어플리케이션에 수 많은 컨테이너가 필요합니다.
여러 대의 컨테이너를 안정적으로 구동하기 위해 멀티 호스트 도커 플랫폼을 사용하기도 하지만,
여러 대의 호스트, 여러 개의 컨테이너를 관리하기는 쉽지 않습니다.
효율적인 관리 측면에서 쿠버네티스가 등장합니다. - 컨테이너 오케스트레이션

컨테이너 계층구조

k8s

kubernetes.io
운영 수준의 컨테이너 오케스트레이션
컨테이너화된 애플리케이션을 자동으로 배포, 스케일링 및 관리해주는 오픈소스 시스템입니다.
그리스어: 조타수

  • 특징
    워크로드 분리
    어디서나 실행 가능 - 온프레미스, 퍼블릭 클라우드
    선언적 api

쿠버네티스 설치하기

1) 설치하지 않고 사용하기
카타코다 쿠버네티스 플레이그라운드 - 서비스 종료

Play with the kubernets

2) 가상머신에 설치하기
virtureMachine 8 - 생략

설지전 ..

Container Network Interface란?

Container간 통신을 지원하는 VxLAN. Pod Network라고도 부릅니다.
다양한 종류의 플러그 인이 존재합니다.
플라넬, 칼리코, 위브넷 등 다양한 종류가 존재합니다.

쿠버네티스 클러스터 구성

  • control plane
    워커 노드들의 상태를 관리하고 제어
    single master
    multi amster(3,5개의 master nodes)

  • workder node
    도커 플랫폼을 통해 컨테이너를 동작하며 실제 서비스 제공

쿠버네티스 설치

https://www.virtualbox.org/wiki/Downloads

-macOS 지원이 안되어 실제 설치 환경 구축은 생략하겠습니다.

쿠버네티스 환경 설정

실습 환경을 구축해보겠습니다.

kubectl --help명령어를 통해 제대로 설치가 되어있는지 확인해봅시다.

kubectl이란 ?

control plane이 worker node들에게
" 웹 서버 3개 실행해줘 " 와 같은 명령어를 요청할 때 사용하는 명령어입니다.

kubectl 명령어 구조

kubectl [command] [type] [name] [flags]

ex) kubectl get pod webserver -o wide

command : 자원(Object)에 실행할 명령

  • create, get, delete, edit

type : 자원의 타입

  • node, pod, service

name : 자원의 이름

  • websever와 같이 사용자가 원하는이름을 지정할 수 있습니다.(소문자,-,숫자로 구성)

flags : 부가적으로 설정할 옵션

  • --help, -o options

kubectl 명령어 자동완성

  • bash
    source <(kubectl completion bash)
    source <(kubeadm completion bash)

echo "source <(kubectl completion bash)" >> ~/.bashrc
echo "source <(kubeadm completion bash)" >> ~/.bashrc

kubectl 명령어 실습

저는 컴퓨터에 직접 vm을 설치하는 방법이 아닌
playground에서 실습을 진행해 playground 예시를 보여드리겠습니다.

앞에 설명한 playground 링크를 접속해 docker 나 github계정으로 로그인하면 아래 화면처럼 나오게 됩니다.

좌측에 + ADD NEW INSTENCES를 세번 눌러
3개의 node를 구성해줍니다.

명령어 3개가 보이실텐데
1번 명령어는 마스터 노드를 설정하는 명령어입니다.
2번 명령어는 앞에 설명한 CNI 설치 명령어입니다.
3번 명령어는 nginx 웹서버 설치 명령어입니다.

마스터 노드(node1)에 위 명령어를 모두 실행 후
worker node를 구성해주어야합니다.

instance를 한 개 더 만들고 master node(node1)과 join시켜줍니다.

이제 아래 명령어를 실행해봅니다.

kubectl run webserver --image=nginx:1.14 --port 80

kubectl get pods
#run = 컨테이너 1개
kubectl create deployment mainui --image=httpd --replicas=3
kubectl get deployments.apps 

webserver 내부로 들어가서 내용을 바꾸어봅시다.

kubectl exec webserver -it -- /bin/bash
#exec는 pod에서만 이루어져 type을 생략가능합니다.

ls
cd /usr/share/nginx/html/
ls
cat index.html
echo "MoonSH WebPage" > index.html
exit

curl <ip>

edit 예제

kubectl edit deployments.apps mainui

내부의 replicas를 3 -> 5로 바꿔봅시다.

kubectl run webserver --image=nginx --port 80 --dry-run -o yaml
kubectl run webserver --image=nginx --port 80 --dry-run -o yaml > webserver-pod.yaml

vi webserver-pod.yaml
#수정
kubectl create -f webserver-pod.yaml

명령어는 추후 예제를 통해 익숙해지니 간단한 예제만 알아보았습니다.

쿠버네티스 아키텍처

  • 쿠버네티스 동작원리
  • namespace
  • yaml
  • api version

쿠버네티스 동작원리

개발자 혹은 운영자가 컨테이너를 만들어
docker push 를 이용해 hub에 저장합니다.

kubectl을 이용해 kuberneties가 hub에 있는 컨테이너를 실행하도록
master node(control plane)에게 요청합니다.

master에 있는 api가 요청을 받아들여
worker node(작업 노드)에 스케줄러에게 컨테이너를 실행하도록 요청합니다.

스케줄러는 컨테이너를 실행하기 적합한 node를 찾아 해당 kubelet에
컨테이너 실행 요청을 합니다.

요청받은 node의 kubelet이 요청을 docker 명령어로 변환해
dockerd에 전달합니다.

dockerd은 hub에 해당 컨테이너가 있는지 확인 후 컨테이너로 실행하게됩니다.
k8s는 pod라는 단위로 이를 관리하게 됩니다.

쿠버네티스 컴포넌트

  • 마스터 컴포넌트
    • etcd
      : key-value타입의 저장소입니다.
      : worker node들의 상태가 저장되어 있습니다.
    • kube-apiserver
      : k8s API를 사용하도록 요청을 받고 요청이 유호한지 검사합니다.
    • 스케줄러
      : 컨테이너 실행에 있어 어떤 노드가 적합한지 체크합니다.
    • 컨트룰러 매니저
      : 파드를 관찰하며 개수를 보장합니다.
  • 워커노드 컴포넌트
    • kubelet
      : 모든 노드에서 실행되는 k8s 에이전트입니다.
      : 데몬 형식으로 동작합니다.
    • kube-proxy
      : k8s의 네트워크 동작을 관리합니다.
      : iptables rule을 구성합니다.
    • 컨테이너 런타임
      : 컨테이너를 실행하는 엔진입니다.
      : docker, containerd, runc

-애드온 생략 (cAdvisor, CNI, coreDNS ...)

K8s namespace

물리적인 클러스터는 하나이지만 여러개로 동작하도록 네임스페이스를 만들어 각각 관리하는 방식입니다

  • namespace
    클러스터 하나를 여러 개의 논리 적인 단위로 나눠서 사용
  • 쿠버네티스 클러스터 하나를 여러 팀이나 사용자가 함께 공유
  • 용도에 따라 실행해야 하는 앱을 구분할 때 사용

namespace 사용하기

namespace 보기 kubectl get namespaces

기본은 default namespae가 동작중입니다.
현재 namespace에서 동작중인 pod를 보기위해 아래 명령어들을 사용할 수 있습니다.

kubectl get pod
kubectl get pod --namespace default
kubectl get pod -n default

cat > nginx.yaml

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    - image: nginx:1.14
      name: nginx
      ports:
        - containerPort: 80
        - containerPort: 443
kubectl create -f nginx.yaml
kubectl get pods -n default

모든 namespace에서 실행중인 모든 pod들을 아래 명령어로 불러올 수 있다.
-> k8s 시스템을 위한 pod들도 가져오기 때문에 파드 관리가 힘들어 질 것이다.

kubectl get pods --all-namespaces

네임스페이스 만들어 사용해보기

  • 네임스페이스 만들어 사용해보기 - CLI방법
kubectl create namespace blue
  • 네임스페이스 만들어 사용해보기 - yaml방법
kubectl create namespace red --dry-run -o yaml > red-ns.yaml

ls

vi red-ns.yaml

creationTimestamp 지우기
spec, status 지우기

kubectl get namespace
  • 만들었던 nginx.yaml파일을 red namespace로 실행해보기
kubectl create -f nginx.yaml -n red

vi nginx.yaml
metadata에 namespace:red로 설정해주면 실행될 때 명령어를 입력하지 않아도 됩니다.

사용할 네임스페이스 switch

쿠버네티스는 기본적으로 default namespace를 사용합니다.
이 기본 설정값을 변경하는 법을 알아보겠습니다.

kubectl config -- help

kubectl config view

kubectl config set-context blue@kubernetes --cluster=kuberneties --user=kubernetes-admin --namespace=blue
 
kubectl config current-context
kubectl config use-context blue@kubernetes

네임스페이스 삭제하기

네임스페이스 삭제 시 내부 pod, api 들 모두 삭제됩니다.
kubectl delete namespace blue

yaml 템플릿

사람이 쉽게 읽을 수 있는 데이터 직렬화 양식

  • 기본 문법
    - 구조화된 데이터를 표현하기 위한 데이터 포맷
    • Python처럼 들여쓰기로 데이터 계층을 표기
    • 가독성이 좋아 설정 파일에 적합한 형식
    • Scalar 문법 : ':'을 기준으로 key:value 설정
    • 배열 문법 : '-' 문자로 여러개를 나열

API Version

  • alpha -> beta -> stable
  • k8s object 정의 시 apiVersion이 필요
  • k8s가 update하는 API가 있으면 새로운 API가 생성됨

API Object의 종류

  • deployment
  • Pod
  • ReplicaSet
  • ReplicationController
  • Service
  • PersistentVolume

explain으로 버전 확인
kubectl explain pod -> pod의 version을 알려줌

Pod-Container 정리와 Single/Multi Container Pod

Pod 개념 및 사용

  • Pod
    컨테이너를 표현하는 K8S API의 최소 단위
    Pod에는 하나 또는 여러 개의 컨테이너가 포함될 수 있습니다

Pod 생성

  • kubectl run 명령으로 생성
    kubectl run webserver --image=nginx:1.14
  • pod yaml을 이용해 생성
#kubectl run nginx --image=nginx --dry-run -o yaml > pod-nginx.yaml

apiVersion: v1
kind: pod
metadata:
  name: webserver
spec:
  containers:
  - name: nginx-container
    image: nginx:1.14
    imagePullPolicy: Always
    ports:
    - containerPort: 80
      protocol: TCP
#Pod 실행
kubectl create -f pod-nginx.yaml

#동작중인 Pod확인
kubectl get pods

#확인
curl <pod's IP address>

Muti-container Pod 생성하기

#vi pod-multi.yaml
apiVersion: v1
kind: Pod
metadata:
  name: multipod
spec:
  containers:
  - name: nginx-container
    image: nginx:1.14
    ports:
    - containerPort: 80
  - name: centos-container
    image: centos:7
    command:
    - sleep
    - "10000"
kubectl create -f pod-multi.yaml
kubectl get pods
kubectl get pods -o wide
kubectl exec multipod -it -c centos-container -- /bin/bash
kubectl logs mutipod -c nginx-container

Pod 동작 flow

  • 사용자가 api에게 실행 요청을 합니다
    kubectl run webserver --image=nginx:1.14

  • API가 합당한 명령어인지 체크 후 이를 실행하게 됩니다.
    ->Pending상태

  • 이 Pod를 실행할 node에게 배치해 실행한다면 -> Running

  • 실패한다면 -> Succeeded Failed

kubectl get pod -o wide -watch

명령어를 활용해 STATUS값이 어떻게 변하는지 확인해봅시다.

livenessProbe

self Healing : 컨테이너 실행을 보장해주는 기능
livenessProbe definition은 일반 pod definition과 하단 livenessProbe 부분이 생긴 것을 볼 수 있습니다.
아래 파일에서는 주기적으로 80번 포트로 '/'로 접속해 연결을 확인한다는 뜻입니다.

apiVersion: v1
kind: Pod
metadata:
  name: multipod
spec:
  conotainers:
  - name: nginx-container
    image: nginx:1.14
    livenessProbe:
      httpGet:
        path: /
        port: 80

livenessProbe 매커니즘

  • httpGet : 지정한 IP주소, port, path에 http get 요청을 보내, 해당 컨테이너가 응답하는지 확인합니다.
    반환코드가 200이 아니라면 오류, 컨테이너를 다시 시작합니다.
livenessProbe:
  httpGet
    path: /
    port: 80
  • tcpSocket : 지정된 포트에 TCP연결을 시도, 연결되지 않으면 컨테이너를 재시작합니다.
livenessProbe:
  tcpSocket:
    port: 22
  • exec : exec 명령을 전달하고, 명령의 종료코드가 0이 아니면 다시 시작합니다.
livenessProbe:
  exec:
    command:
    - ls
    - /data/file

livenessProbe 매개변수

  • periodSeconds: health check 반복 실행 시간
  • initalDelaySeconds: Pod 실행 후 delay할 시간
  • timeoutSeconds: health check후 응답을 기다리는 시간

init container를 적용한 Pod

  • init Container
    메인 컨테이너를 실행할 환경셋팅 / 초기화 구성을 지원하는 컨테이너입니다.
    앱 컨테이너 실행 전에 미리 동작시킬 컨테이너입니다.
    본 컨테이너가 실행되기 전에 사전 작업이 필요할 경우 사용합니다.
    초기화 컨테이너가 모두 실행된 후에 앱 컨테이너를 실행합니다.
#vi init-container=exam.yaml
apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app.kubernetes.io/name: MyApp
spec:
  containers:
  - name: myapp-container
    image: busybox:1.28
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers:
  - name: init-myservice
    image: busybox:1.28
    command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
  - name: init-mydb
    image: busybox:1.28
    command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]

'''
#cat > init-container-exam-svc.yaml
apiVersion: v1
kind : Service
metadata:
name: myservice
spec:
ports:

  • protocol: TCP
    port: 80
    targetPort: 9376

'''

kubectl create -f init-container-exam-svc.yaml
#cat > init-container-exam-svc.yaml
apiVersion: v1
kind : Service
metadata: 
  name: mydb
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9376

infra container

Pod마다 내부에 'pause'라는 컨테이너가 있습니다.
Pod 컨테이너는 특별히 작업하는 일은 없으며,
Pod의 환경을 만들어주는 컨테이너라고 생각해주시면 됩니다.
Pod생성 시 생성되며, 다른 컨테이너와 같이 Pod delete 시 삭제됩니다.

kubectl delete pod --all

kubectl run web --image=nginx --port=80

static Pod

  • api에게 요청을 보내지 않습니다
    kubelet이 관리하는 static pod Dir에 yaml파일을 저장하면 알아서 실행합니다.
  • kubelet Daemon에 의해 동작하는 Pod입니다.

static Pod 만들기

vi /var/lib/kubelet/config.yaml
...#아래 위치에 yaml파일 생성으로 pod 시행
staticPodPath: /etc/kubernetes/manifests

#디렉터리 수정시 명령어
systemctl restart kubelet

cd /etc/kubernetes/manifests
vi pod-nginx.yaml


apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
spec:
  containers:
  - name: nginx-container
    image: nginx:1.14
    livenessProbe:
      httpGet:
        path: /
        port: 80

Pod에 리소스 할당

Pod Resource 요청 및 제한

  • Resource Request
    파드를 실행하기 위한 최소 리소스 양을 요청
  • Resource Limits
    파드가 사용할 수 있는 최대 리소스 양을 제한
    Memory limit을 초과해서 사용되는 파드는 종료되며 다시 스케줄링 됩니다.

예시)

apiVersion: v1
kind: Pod
metadata:
  name: frontend
spec:
  containers:
  - name: app
    image: images.my-company.example/app:v4
    resources:
      requests:
      #파드를 실행하기 위한 최소 리소스 양을 요청
        memory: "64Mi"
        cpu: "250m"
      limits:
      #최대 , 초과 시 kill 후 다시 스케쥴링
        memory: "128Mi"
        cpu: "500m"
  - name: log-aggregator
    image: images.my-company.example/log-aggregator:v6
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

메모리 단위
1MB = 1000KB
1MiB = 1024Kib

1Gi
1Mi
10Ki

CPU 단위
1000m = 1core or 1

Pod의 환경변수 설정하기

환경변수

  • Pod 내의 컨테이너가 실행될 때 필요로 하는 변수
  • 컨테이너 제작 시 미리 정의
    Nginx Dockerfile의 예시
ENV NGINX_VERSION 1.19.2
ENV NJS_VERSION 0.4.3
  • Pod 실행 시 미리 정의된 컨테이너 환경변수를 변경할 수 있습니다.
#vi pod-nginx-env
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod-env
spec:
  containers:
  - name: nginx-container
    image: nginx
    ports:
    - containerPort: 80
      protocol: TCP
    env:
    - name: MYVAR
      value: "testvalue"
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"
        
kubectl create -f pod-nginx-env

kubectl exec nginx-pod-env -it -- /bin/bash

env

Pod 실행 패턴

  • Pod를 구성하고 실행하는 패턴
  • multi container Pod

1) Sidecar

  • 파드 내부에 두 개의 컨테이너가 함께 동작해야지만 동작하는 패턴입니다.
  • ex) webServer(로그 생성), 분석

2) Adaptor

  • 외부의 시스템 상태에 대한 모니터 정보가 들어있는 공간으로부터 데이터를 받아와 UI를 띄워주는 다른 컨테이너에게 전달해주는 패턴입니다.

3) Ambassador

  • 웹 서버가 생성한 데이터를 캐시 형태로 외부로 분산시키는 (로드밸런서 역할) 패턴입니다.

Controller - ReplicationController

Controller

  • pod의 개수를 보장

Controller 종류

  • Replication Controller
  • Deployment , Replicaset
  • Daemon Set
  • statueful set
  • Cronjob, job

Replication Controller

  • 요구하는 Pod의 개수를 보장하며 파드 집합의 실행을 항상 안정적으로 유지하는 것을 목표로 합니다.
    • 요구하는 Pod의 개수가 부족하면 template를 이용해 Pod를 추가합니다.
    • 요구하는 Pod 수 보다 많으면 최근에 생성된 Pod를 삭제합니다.
  • 기본구성
    • selector
    • replicas
    • template
...
spec:
  replicas: <배포개수>
  selector:
    key: value (label에 이 key value가 필수로 있어야 한다.)
  template:
    <컨테이너 템플릿>
 ...
#공식 페이지 예제
#vi rc-nginx.yaml
apiVersion: v1
kind: ReplicationController
metadata:
  name: nginx
spec:
  replicas: 3
  selector:
    app: nginx
  template:
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80

예제)

kubectl create rc-exam --image=nginx --replicas=3 --selector=app=webui

위 명령어들을 통해 rc-nginx이 3개가 실행되는 중에 아래 명령어를 통해 만든 새로운 yaml파일로 생성한 pod를 실행시키면 -> fail
(replicationController가 pod의 개수를 3개 보장하기 때문입니다.)

(yaml 파일을 빠르게 만들기 위한 --dry-run > ~~.yaml)

kubectl run redis --image=redis --labels=app=nginx --dry-run -o yaml > redis.yaml

해결하기 위해 아래 명령어를 통해 replicas의 개수를 조정하면 됩니다.(scale-out)

kubectl edit rc nginx


kubectl scale rc rc-nginx --replicas=4

->성공

kubectl scale rc rc-nginx --replicas=4

ReplicaSet

  • ReplicationController와 비슷한 역할을 합니다
  • Replication보다 풍부한 seleoctor가 있습니다.
selector:
  matchLabels:
    component: redis
  matchExpressions:
    - {key: tier, operator: ln, values: [cache]}
    - {key: enciroment, operator: Notln, values: [dev]}
  • matchExpressions 연산자
    • In: key와 values를 지정하여 key, value가 일치하는 Pod만 연결
    • NotIn: key는 일치하고 value는 일치하지 않는 Pod에 연결
    • Exists: key에 맞는 label의 pod를 연결
    • DoesNotExist: key와 다른 label의 pod를 연결
#레플리카셋 삭제 후 파드 삭제 안하기
kubectl delete rs rs-nginx --cascade=false

Deployment

  • ReplicaSet을 컨트롤해서 Pod수를 조절합니다.

  • Rolling Update & Rolling Back

    • Rolling update : 파드 인스턴스를 점진적으로 새로운 것으로 업데이트하여 디플로이먼트 업데이트가 서비스 중단 없이 이루어질 수 있도록 하는 것입니다.

yaml파일은 kind의 value부분만 replicaSet -> deployment로 고치면 됩니다.

Rolling update

set 명령어를 통해 롤링 업데이트를 진행할 수 있습니다.

kubectl set image deployment <deploy_name> <container_name>=<new_version_image>
kubectl rollout status deployment <deploy_name> #상태정보 확인
kubectl rollout pause deployment <deploy_name> #정지
kubectl rollout resume deployment <deploy_name> #재시작

kubectl rollout resume history <deploy_name> #히스토리 보기
# revisionHistoryLimit : defalut = 10 //조절가능

롤백

# history 기준 한단계 전으로 롤백
kubectl rollout undo deployment <deploy_name>

# x번 리비전으로 롤백
kubectl rollout undo deployment <deploy_name> --to-revision=x

yaml로 업데이트

vi deployment-exam.yaml

'''
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

'''
kubectl create -f deployment-exam.yaml --record

kubectl describe pod nginx-deployment-cbdccf466-9hlqz

kubectl set image deploy nginx-deployment nginx=ngonx:1.15 --record

kubectl rollout history deployment nginx-deployment 

kubectl rollout undo deployment nginx-deployment --to-revision=1

kubectl 


kubectl apply -f deployment-exam2.yaml

쿠버네티스 서비스

서비스 개념
서비스 타입
서비스 사용
헤드리스 서비스
kube-proxy

서비스 개념

동일한 서비스를 제공하는 Pod 그룹의 단일 진입점을 제공

서비스 타입 4가지

ClusterIP
NodePort
LoadBalancer
ExternalName

잠깐 휴식 -> 카카오 예제 진행

남은 쿠버네티스 기본 개념들

남은 강의

  • 컨트룰러
    • daemonSet
    • statefulSet
    • job Controller
    • CronJob
  • 멀티마스터 쿠버네티스 클러스터
  • 쿠버네티스 서비스 개념 및 종류
    • 쿠버네티스 서비스 4가지 실습
  • Handless Service , Kube Proxy
  • K8s Ingress개념, Ingress Controller 설치
    • 실습
  • K8s label
    • K8s node label
  • K8s annotaion
  • K8s Canary Deployment
  • K8s ConfigMap
  • K8s Secret

0개의 댓글