Persistence Volume(PV)

docker에도 volume이 있음.

-> 컨테이너의 데이터를 영구적으로 보관하기 위해서 이용함.

-> POD 에도 이를 지원하는 기능이 있음.

 

 

apiVersion: v1
kind: Pod
metadata:
  name: tmp
spec:
  containers:
  - image:
    ...
    volumeMounts:
    - mountPath: /opt  //컨테이너 내부 경로
      name: data-volume
    
  volumes:
  - name: data-volume
    hostPath:
      path:/data
      type: Directory

하지만 클러스터에서는 권장하지 않는 방법이라고 함.(단일 노드는 상관이 없음.)

-> 이는 모든 노드의 /data 에 모두 같은 데이터가 있기를 기대하기 때문임.

-> 이를 해결하기 위해서는 k8s가 지원하는 다양한 솔루션을 이용하면 됨.

(NFS, amazon web services 등)

 

volumes:
- name: data-volume
  awsElasticBlockStore:
    volumeID: <volume-id>
    fsType: ext4

이런 식으로 사용 가능.

 

apiVsersion: v1
kind : PersistentVolume
metadata:
  name: pv-voll
spec:
  accessModes:
    - ReadWriteOnce //ReadOnlyMany, ReadWriteMany 옵션도 있음.
  capacity:
    storage: 1Gi
  hostPath: // 앞에서 처럼 aws 등 다양한 솔루션 사용 가능.
    path: /tmp/data

 

access mode 관련 설명

https://kubernetes.io/ko/docs/concepts/storage/persistent-volumes/#%EC%A0%91%EA%B7%BC-%EB%AA%A8%EB%93%9C

 

 

 

Persistence Volume Claim

이는 하나의 PV 로 묶여 있음.

-> 더 큰 용량의 PV에 묶일 수도 있음.

-> 사용 가능한 볼륨이 없으면, 보류 상태가 됨.

 

 

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: cl
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    reqeusts:
      storage: 500Mi

 

이는 이전에 생성된(위의 yaml)에 bine 됨.

(위에서는 1기가이며 accessMode가 일치해서)

 

만약이 PVC가 삭제되면, 해당 볼륨에 어떠한 작업을 수행하는지?

- Retain : 리소스를 수동으로 삭제할 때 까지 다른 claim에서 사용하지 못함.

- Delete: 데이터, PV 삭제

- Recycle: 더 이상 사용하지 않는다고 함.(공식 홈페이지) 대신 동적 프로비저닝이라는 것을 사용한다고 함. 기존 데이터만 삭제

 

 

Pod - PVC - PV 를 통해 PVC 를 볼륨처럼 사용할 수 있음.

-> 이렇게 하는 이유는 파드의 각각 상황에 따라서 다양한 스토리지를 사용할 수 있게 해줌.

 

 

Storage

앞에서는 PVC를 이용하여 요청하려면, PV 를 계속 만들어줘야 하는 단점이 있음.

-> 이를 static provisioning 이라고 함.

 

반대는 dynamic provisioning. 이를 위해서 Storage 가 있음.

 

apiVersion: storage.k8s.io/v1
kind: StroageClass
metadata:
  name: google-storage
provisioner: kubernetis.io/gce-pd

parameters: 
  ... //프로비저너에 전달하는 파라미터들. 이는 홈페이지 참고

 

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: cl
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: google-storage // 추가된 부분
  resources:
    reqeusts:
      storage: 500Mi

 

StorageClass에 의해서 PV가 자동으로 생성이 됨.

(PV가 생성되지 않는 것은 아님!!)

 

 

 

ConfigMap

이를 이용하여 Pod에 값을 전달할 수 있음(ENV 등)

k create configmap <config-name> --from-literal=<key>=<value>


k create configmap <config-name> --from-file=<file>

 

yaml로도 생성 가능.

apiVersion: v1
kind: ConfigMap
metadata:
  name: game-demo
data:
  # 속성과 비슷한 키; 각 키는 간단한 값으로 매핑됨
  player_initial_lives: "3"
  ui_properties_file_name: "user-interface.properties"

  # 파일과 비슷한 키
  game.properties: |
    enemy.types=aliens,monsters
    player.maximum-lives=5    
  user-interface.properties: |
    color.good=purple
    color.bad=yellow
    allow.textmode=true

 

주의 사항은 이는 암호화를 제공하지 않음.

-> 이를 위해서 k8s의 Secret을 이용하거나 써드파티 도구를 이용하면 됨.

 

pod 에 해당 정보를 주기 위해서는

apiVersion: v1
kind: Pod
metadata:
  name: configmap-demo-pod
spec:
  containers:
    - name: demo
      image: alpine
      command: ["sleep", "3600"]
      envFrom:
        - configMapRef:
          name: app-config // config 이름

 

 

env 등 주입할 때 다양한 방법이 있음.

apiVersion: v1
kind: Pod
metadata:
  name: configmap-demo-pod
spec:
  containers:
    - name: demo
      image: alpine
      command: ["sleep", "3600"]
      env:
        # 환경 변수 정의
        - name: PLAYER_INITIAL_LIVES # 참고로 여기서는 컨피그맵의 키 이름과
          # 대소문자가 다르다.
          valueFrom:
            configMapKeyRef:
              name: game-demo           # 이 값의 컨피그맵.
              key: player_initial_lives # 가져올 키.
        - name: UI_PROPERTIES_FILE_NAME
          valueFrom:
            configMapKeyRef:
              name: game-demo
              key: ui_properties_file_name
      volumeMounts:
        - name: config
          mountPath: "/config"
          readOnly: true
  volumes:
    # 파드 레벨에서 볼륨을 설정한 다음, 해당 파드 내의 컨테이너에 마운트한다.
    - name: config
      configMap:
        # 마운트하려는 컨피그맵의 이름을 제공한다.
        name: game-demo
        # 컨피그맵에서 파일로 생성할 키 배열
        items:
          - key: "game.properties"
            path: "game.properties"
          - key: "user-interface.properties"
            path: "user-interface.properties"

 

반응형

Sevice

서비스는 사용자(포드 그룹, db 등)와 통신하는 데에 도움을 줌.

 

 service를 통해서 node 내부의 pod와 사용자를 연결시켜 줄 수 있음.(docker의 port forwarding 느낌?)

 

 

이런 식으로 통신 가능(udemy의 이미지 저작권 때문에 직접 그려서 넣었습니다.)

 

 

즉 node의 포트 - service의 port - pod 포트(targt port)로 통신이 가능함.

 

apiVersion: v1
kind: Service
metadata:
	name : myapp-service
    
spec:
  type: NodePort
  ports:
    - targetPort: 80
      port : 80
      nodePort : 30008
  selector: //다른 pod와 연결이 됨.
    app: myapp
    type: front-end

 

selector를 이용하여 다른 pod와 연결이 될 수 있음.(로드 밸런서 처럼 동작하게 됨)

 

노드가 여러 개라도 상관 없음. 

 

 

apiVersion: v1
kind: Service
metadata:
  name : myapp-service
    
spec:
  type: ClusterIP
  ports:
    - targetPort: 80
      port : 80
  selector: //다른 pod와 연결이 됨.
    app: myapp
    type: front-end

이를 이용하여 여러 node들에 접근 가능.

 

 

Ingress

 

아예 완전 다른 서비스를 만들면?

-> 이를 어떻게 접근을 해야할 지?

 

ingerss를 이용하여 다양한 서비스에 접근하게 만들어줌.

 

즉, 서비스들 - ingress - 외부 이런 식으로 연결이 됨.

출처 : https://kubernetes.io/ko/docs/concepts/services-networking/ingress/

 

apiVersion: networking.k8s.io/v1
kind: ingress
metadata:
  name: ingress-wear
spec:
  rules:

  - http:
    paths:
    - path: /wear
      pathType: Prefix
      backend: // 어디로 전송되는 지
        service:
          name: wear-service
          port:
            number: 80
    - path: /watch
      pathType: Prefix
      backend: // 어디로 전송되는 지
        service:
          name: watch-service
          port:
            number: 80

 

 

 

 

 

 

반응형

사내 쿠버네티스 스터디

 

 

POD

POD 는 K8S에서 만들 수 있는 가장 작은 단위

POD는 보통은 컨테이너와 1 대 1로 매핑

확장을 위해서 기존 POD에 컨테이너를 추가하지 않음.(새로운 POD를 생성하거나 POD를 지움)

 

POD 하나에 여러 컨테이너를 넣을 수 있음.

(파일 관리 같은 Helper Container가 필요할 수 있음.)

-> POD만 정의하면 모든 컨테이너가 함께 작동하기 때문에 관리하기 용이.

 

이들은 서로 같은 공간을 공유하기 때문에 파일이나 통신이 용이.

 

 

 

//pod 생성
kubectl run [pod name] --image [image_name]

//pod 목록
kubectl get pods

 

 

POD들은 YAML 파일 기반으로 만들 수 있음.

# pod-def.yml

apiVersion : v1 # API 버전
kind:Pod # replicaset 등 종류
metadata: #개체에 대한 데이터
  name : myServer-pod #obeject 이름
  labels: #레이블. 이 레이블 이름을 기반으로 필터링을 할 수 있음.
    app: myServer
    type: back-end
spec: #object에 관련된 추가 정보 제공하는 곳.
  containers:
    - name: server-contaniner
    imgae: server
          
          
          
  #이를 이용하여 실행 가능        
  #kubectl create -f pod-def.yml

 

 

 

Replica Sets

pod가 다운되면, 끝남.

replication controller는 pod가 죽으면, 다시 실행시킴.

또한 node에 리소스가 부족하면, 다른 node에 pod를 실행함.

 

replica set 과의 차이점은?

replica controller가 replica set드로 대체되고 있다고 함.

 

# rc-def.yml. replica controller

apiVersion : v1 # API 버전
kind:ReplicaController
metadata: 
  name : myServer-pod #obeject 이름
  labels: #레이블. 이 레이블 이름을 기반으로 필터링을 할 수 있음.
    app: myServer
    type: back-end
spec: #object에 관련된 추가 정보 제공하는 곳.
  template: # pod 정보 작성
    # pod 정보
    metadata:
      name: myServer-pod
      labels:
        app: myServer
        type: bacek-end
    spec:
      containers:
        - name: server-contaniner
        imgae: server
        
  replicas: 3
          
          
          
  #이를 이용하여 실행 가능        
  #kubectl create -f rc-def.yml
  
  
  
# rs-def.yml. replica set
  
  
apiVersion : apps/v1 # replica controller와 다름. 이렇게 선언 안 하면 에러 발생?
kind:ReplicaSet
metadata: 
  name : myServer #obeject 이름
  labels: 
    app: myServer
    type: back-end
spec: #object에 관련된 추가 정보 제공하는 곳.
  template: # pod 정보 작성
    # pod 정보
    metadata:
      name: myServer-pod
      labels:
        app: myServer
        type: bacek-end
    spec:
      containers:
        - name: server-contaniner
        imgae: server
        
  replicas: 3
  selector: # controller와 다른 점. set은 필수로 선언 필요. contrlloer는 기본으로 정의파일에서 정의한 레이블이랑 같다고 판단
    matchLabels:
      type: back-end
    
  #이를 이용하여 실행 가능        
  #kubectl create -f rs-def.yml

 

select가 정확히 무슨 역할을 하는지?

이미 생성되어 있던 pod를 모니터링할 수 있음.

하나가 고장나면 재배포도 가능.

 

만약 이미 3개가 있는 상태에서 replicas를 3으로 설정하면?

이미 3개가 있으니까 다시 pod를 재배포하지 않음.

-> pod를 재배포하지는 않지만, spec은 적어야 함. 나중에 다운될 수도 있기 때문.

 

scale 하고 싶으면,

// replicas 설정하고
k replace -f rs-def.yml

k scale --replicas=6 -f rs-def.yml

k scale --replicas=6 replicaset myServer

 

 

Deployments

여러 pod가 있을 경우, 모두 한 번에 업데이트하는 것보다는 하나 씩 하는 것이 좋음

-> 이를 롤링 업데이트라고 함.

 

만약 하다가 문제가 생기면 롤백을 할 수 있어야 함.

보통 pod 들은 replica set을 이용.

deployment는 롤링 업데이트 등 인스턴스를 매끄럽게 업데이트 해줌.

 

deployment > replica set > pod

# df-def.yml
  
  
apiVersion : apps/v1 # replica controller와 다름. 이렇게 선언 안 하면 에러 발생?
kind: Deployment # 대문자 지켜야 함
metadata: 
  name : myServer-deployment #obeject 이름
  labels: 
    app: myServer
    type: back-end
spec:
  template:
    # pod 정보
    metadata:
      name: myServer-pod
      labels:
        app: myServer
        type: bacek-end
    spec:
      containers:
        - name: server-contaniner
        imgae: server
        
  replicas: 3
  selector:
    matchLabels:
      type: back-end
    
  #이를 이용하여 실행 가능        
  #kubectl create -f df-def.yml

 

파일은 replica set이랑 큰 차이가 없음.

 

 

 

Namespaces

dev, stg, prod 처럼 서로 공간을 분리할 수 있음.

-> 다른 name space의 리소스를 실수로 건들이지 않도록 할 수 있음.

 

dns

같은 name space안에서는 service 이름으로 서로 호출 가능.

 

다른 name space의 service를 부르려면? 

-> [service 이름].[name space].svc.cluster.local ..?

cluster.local은 domain, svc는 service 를 뜻함.

 

 

# pod-def.yml

apiVersion : v1 # API 버전
kind:Pod # replicaset 등 종류
metadata: #개체에 대한 데이터
  name : myServer-pod #obeject 이름
  namespace: dev
  labels: #레이블. 이 레이블 이름을 기반으로 필터링을 할 수 있음.
    app: myServer
    type: back-end
spec: #object에 관련된 추가 정보 제공하는 곳.
  containers:
    - name: server-contaniner
    imgae: server
          
          
          
  #이를 이용하여 실행 가능        
  #kubectl create -f pod-def.yml

namespace는 metadata아래에 선언하면 됨.

 

 

namesapce를 만들려면?

apiVersion : v1
kind:Namespace 
metadata: #개체에 대한 데이터
  name : dev

 

 

 

반응형

+ Recent posts