쿠버네티스 내용과 코드

이현우·2022년 8월 24일
0

쿠버네티스

목록 보기
4/11

이 글은 쿠버네티스의 기능들을 간단히 설명하고 해당 기능들의 코드 예시를 작성함.

공식 홈페이지

https://kubernetes.io/ko/docs/concepts/overview/what-is-kubernetes/

쿠버네티스란?

컨테이너화된 워크로드와 서비스를 관리하기 위한 이식성이 있고, 확장가능한 오픈소스 플랫폼이다.
좀 더 간단히 이야기하면 컨테이너 관리 시스템이다.

1. 쿠버네티스의 구성요소

1.1 컨트롤 플레인

클러스터에 관한 전반적인 결정(예를 들어, 스케줄링)을 수행하고 클러스터 이벤트를 감지하고 반응

  • kube-apiserver
    • 쿠버네티스 API를 노출 ( = 쿠버네티스 컨트롤 플레인의 프론트엔드)
    • 쿠버네티스 API 서버의 주요 구현체
    • 더 많은 인스턴스를 배포해서 확장 가능 및 트래픽 조절 가능
  • etcd
    • 쿠버네티스 백엔드 저장소 (일관성, 고가용성 키-값 저장소)
  • kube-scheduler
    • 노드가 배정되지 않은 새로 생성된 파드 감지 및 실행 노드 선택
  • kube-controller-manager
    • 컨트롤러 프로세스를 실행
    • 논리적으로는 각 컨트롤러는 분리된 프로세스
    • 복잡성을 낮추기위해 모두 단일 바이너리로 컴파일, 단일 프로세스 내에서 실행됨
      • 노드 컨트롤러: 노드가 다운되었을 때 통지와 대응
      • 레플리케이션 컨트롤러: 시스템의 모든 레플리케이션 컨트롤러 오브젝트에 대해 알맞은 수의 파드들을 유지
      • 엔드포인트 컨트롤러: 서비스와 파드를 연결
      • 서비스 어카운트 & 토큰 컨트롤러: 새로운 네임스페이스에 대한 기본 계정과 API 접근 토큰 생성
  • cloud-controller-manager
    • 클러스터를 클라우드 공급자의 API에 연결하고, 해당 클라우드 플랫폼과 상호 작용하는 컴포넌트와 클러스터와만 상호 작용하는 컴포넌트를 구분

1.2 노드

동작 중인 파드를 유지시키고 쿠버네티스 런타임 환경을 제공하며, 모든 노드 상에서 동작

  • kubelet
    • 클러스터의 각 노드에서 실행되는 에이전트
    • 파드에서 컨테이너가 확실하게 동작하도록 관리
  • kube-proxy
    • 클러스터의 각 노드에서 실행되는 네트워크 프록시
    • 쿠버네티스 서비스 개념의 구현부
    • 노드의 네트워크 규칙을 유지 및 관리
  • 컨테이너 런타임
    • 컨테이너 실행을 담당하는 소프트웨어
      • containerd, CRI-O 등

1.3 애드온

쿠버네티스 리소스(데몬셋, 디플로이먼트 등)를 이용하여 클러스터 기능을 구현

  • DNS
    • 절대적으로 요구되지는 않지만 많은 예시에서 필요로함
    • 쿠버네티스 서비스를 위해 DNS 레코드를 제공해주는 DNS 서버
  • 웹 UI
    • 범용 웹 기반 UI
  • 컨테이너 리소스 모니터링
    • 중앙 데이터베이스 내의 컨테이너들에 대한 포괄적인 시계열 매트릭스를 기록하고 그 데이터를 열람하기 위한 UI를 제공
  • 클러스터-레벨 로깅
    • 검색/열람 인터페이스와 함께 중앙 로그 저장소에 컨테이너 로그를 저장

2. 어떻게 사용할 수 있을까?

  1. minikube를 이용하여 사용
  2. rancher-desktop 를 이용하여 사용
  3. docker-desktop 으로 사용
    • 기본 내장으로 쿠버네티스가 존재
  4. kubeadm으로 설치
  5. rancher-cluster로 구축

3. 쿠버네티스를 조작하기 위해서는?

3.1 kubectl을 사용한다

kubectl이란?

  • 쿠버네티스 클러스터를 제어하기 위한 커맨드라인 도구
  • KUBECONFIG 환경변수 설정이나 $HOME/.kube 및 config 파일 설정으로 쿠버네티스 설정을 할 수 있다.
  • 대부분은 커맨드라인으로 조작할 수 있다.

4. kubectl로 자주 사용하는 명령어

1) pod 조회 및 접근

  • default namespace에 실행중인 파드를 조회한다
  • pod란?
    • 쿠버네티스의 컨테이너를 묶어 관리하는 단위
    • 파드 하나에 속한 컨테이너들은 모두 노드 하나 안에서 실행 됨
  • pod의 생명주기
    • Pending: 파드 생성 중
    • Running: 파드 안 모든 컨테이너 실행 중
    • Succeeded: 파드 안 모든 컨테이너가 정상 실행 종료
    • Failed: 파드 안 모든 컨테이너 중 정상적으로 실행 종료 되지 않은 컨테이너가 있는 상태
    • Unknown: 파드의 상태를 확인할 수 없는 상태
  • namespace란?
    • 여러 개의 팀이나, 프로젝트에 걸쳐서 많은 사용자가 있는 환경에서 사용하기위해 만들어짐
    • 클러스터 자원을 여러 사용자 사이에서 나누는 방법
  • 레이블과 애너테이션
    • 쿠버네티스 자원들의 메타데이터를 관리하는 데 사용
    • 레이블
      • 셀렉터와 함께 특정 레이블이 있는 자원들을 선택할때 주로 사용
      • 오브젝트 구분용
    • 애너테이션
      • 주석 성격의 메타데이터를 기록하는데 사용
      • 시스템 정보 표시용
# default 네임스페이스 조회
$ kubectl get pod
 
# 특정 네임스페이스만 조회
$ kubectl get pod -n <해당 네임스페이스>
 
# 모든 네임스페이스 조회
$ kubectl get pod -A
 
# 상세 조회
$ kubectl get pod -o wide
 
# 조회한 파드에 접근할 때 (bash 쉘이 있을 경우에만 아래 사용가능)
$ kubectl exec -it <조회한 파드명> bash
 
# 파드 로그 확인
$ kubectl logs -f <조회한 파드명>

# yaml파일로 생성 및 수정
$ kubectl apply -f <파일명>

# yaml파일로 생성
$ kubectl create -f <파일명>

apply VS create

  • apply : 리소스가 존재하지 않을 경우 새로운 리소스가 생성/ 리소스가 이미 존재할 경우 리소스를 구성(부분적인 spec을 적용)
  • create : 리소스가 존재하지 않을 경우 새로운 리소스가 생성 / 리소스가 이미 존재할 경우 ERROR가 발생

4.1 Pod 예제

apiVersion: v1
kind: Pod
metadata:
  name: sample
  labels:
    app: sample
  annotations:
    manager: "sunjiho"
    contact: "010-1234-5679"
    release-version: "v1.0.0"
spec:
  containers:
  - name: <컨테이너 명>
    image: <이미지 명>
    imagePullPolicy: Always
    ports:
    - containerPort: 8080

4.2 Deployment 예제

Deployment란?

쿠버네티스가 애플리케이션의 인스턴스를 어떻게 생성하고 업데이트해야 하는지를 지시하는 것

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample
  labels:
    app: sample
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sample
  template:
    metadata:
      name: sample
      labels:
        app: sample
    spec:
      nodeSelector:
        kubernetes.io/hostname: <특정 노드로만 실행 시키고 싶을 경우>
      hostname: krr
      containers:
      - name: <컨테이너 명>
        image: <이미지 명>
        imagePullPolicy: Always
        volumeMounts:
        - name: log
          mountPath: /home/danawa/log
      volumes:
      - name: log
        hostPath:
          path: /data/danawa/log

조회

# deployment 조회, 같은 결과가 나온다.
$ kubectl get deployments
$ kubectl get deployment
$ kubectl get deploy
 
$ kubectl get deploy -n <해당 네임스페이스>

4.3 CronJob 예제

apiVersion: batch/v1
kind: CronJob
metadata:
  name: sample
  labels:
    app: sample
spec:
  schedule: "30 22 * * 2"
  failedJobsHistoryLimit: 1
  successfulJobsHistoryLimit: 4
  jobTemplate:
    metadata:
      name: sample
      labels:
        app: sample
    spec:
      template:
        spec:
          restartPolicy: Never
          nodeSelector:
            kubernetes.io/hostname: <해당 노드 명>
          containers:
          - name: <컨테이너 명>
            image: <이미지 명>
            imagePullPolicy: Always
            volumeMounts:
            - name: log
              mountPath: /home/danawa/log
          volumes:
          - name: log
            hostPath:
              path: /data/log

조회

$ kubectl get cronjob
$ kubectl get cronjob -n <해당 네임스페이스>

4.4 service 조회

서비스란?

  • 쿠버네티스 파드 위에서 실행중인 애플리케이션을 네트워크 서비스로 노출
  • 즉, 쿠버네티스 내부에서 동작만 하는 프로세스에 접근 가능하게 만든다

서비스 타입

  • ClusterIP: 기본 서비스 타입, 쿠버네티스 클러스터 안에서만 사용 가능
  • NodePort: 서비스 하나에 모든 노드의 지정된 포트 할당
  • LoadBalancer: 클라우드에서 제공하는 로드밸런서와 파드를 연결한 후 해당 로드밸런서의 IP를 이용해 클러스터 외부에서 파드에 접근할 수 있도록 해줌
  • ExternalName: 서비스를 .spec.externalName 필드에 설정한 값과 연결함(클러스터 안에서 외부에 접근할 때 주로 사용)
apiVersion: v1
kind: Service
metadata:
  name: sample
  labels:
    app: sample
spec:
  type: NodePort
  ports:
  - port: 9000
    targetPort: 9000
    name: sample1
  - port: 9001
    targetPort: 9001
    name: sample2
  selector:
    app: sample

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sample
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: sample
    spec:
      containers:
      - name: sample
        image: nginx:latest
        env:
        - name: TZ
          value: Asia/Seoul
        - name: LANG
          value: ko_KR.utf8
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: sample
  labels:
    app: sample
spec:
  type: LoadBalancer
  ports:
  - port: 10000   # 10000번 포트로 접근하면 접근 됨
    targetPort: 80
  selector:
    app: sample

조회

# 같은 결과
$ kubectl get services
$ kubectl get service
$ kubectl get svc
 
$ kubectl get svc -n <해당 네임 스페이스>

4.5 ingress 조회

ingress란?

  • 쿠버네티스 클러스터 외부에서 클러스터 내부 서비스로 HTTP/HTTPS 경로를 노출
  • 인그레스는 임의의 포트 또는 프로토콜을 노출시키지 않는다.
  • HTTP와 HTTPS 이외의 서비스를 인터넷에 노출하려면 보통 Service.Type=NodePort 또는 Service.Type=LoadBalancer 유형의 서비스를 사용한다
  • 사용을 위해서는 ingress controller를 따로 쿠버네티스에 설치를 하여 사용해야 한다

ServiceType=NodePort일 경우

  • 127.0.0.1 IP 를 rancher.example.com 으로 셋팅
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sample
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: sample
    spec:
      containers:
      - name: sample
        image: nginx:latest
        env:
        - name: TZ
          value: Asia/Seoul
        - name: LANG
          value: ko_KR.utf8
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: sample
  labels:
    app: sample
spec:
  type: NodePort
  ports:
  - port: 10000
    targetPort: 80
  selector:
    app: sample
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: sample
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
  - host: rancher.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: sample
            port:
              number: 10000

조회

$ kubectl get ingress
$ kubectl get ingress -n <해당 네임 스페이스>

4.6 kubeconfig 설정보기

$ kubectl config view

4.7 쿠버네티스에 리소스를 생성 및 업데이트, 삭제

# 파일로 작성 시
## 생성 및 업데이트
$ kubectl apply -f <파일명>
 
## 삭제
$ kubectl delete -f <파일명>
 
# 일반적으로 실행 시(도커랑 거의 동일)
kubectl run <파드 명칭> --image=<이미지 > -n <해당 네임 스페이스>

4.8 파드, 서비스 등 쿠버네티스 리소스 상태 확인

에러가 났을 경우에 확인하는 용도 및 현재 상태 확인 용도

$ kubectl describe pod <파드 >
$ kubectl describe service <서비스 >
$ kubectl describe cronjob <크론잡 >
$ kubectl describe deployment <디플로이먼트 >

4.9 volume 연결

쿠버네티스에서는 volume을 두개를 써야함

  • persistentVolume
    • 쿠버네티스에서 지정한 물리 디스크 경로
  • persistentVolumeClaim
    • persistentVolume과 pod를 연결

volume.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: sample-pv
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 100Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/d/storage"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: sample-pvc
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 100Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sample
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: sample
    spec:
      containers:
      - name: sample
        image: nginx:latest
        env:
        - name: TZ
          value: Asia/Seoul
        - name: LANG
          value: ko_KR.utf8
        ports:
        - containerPort: 80
        volumeMounts:
        - mountPath: /data
          name: sample-pvc
      volumes:
      - name: sample-pvc
        persistentVolumeClaim:
          claimName: sample-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: sample
  labels:
    app: sample
spec:
  type: NodePort
  ports:
  - port: 10000
    targetPort: 80
  selector:
    app: sample
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: sample
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
  - host: rancher.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: sample
            port:
              number: 10000

조회 예시

# persistentVolumeClaim
$ kubectl get pvc
$ kubectl get pvc -n <해당 네임 스페이스>
 
# persistentVolume
$ kubectl get pv
$ kubectl get pv -n <해당 네임스페이스>
profile
GitHub - https://github.com/jenu8628

0개의 댓글