Kubernetes Persistent Volumes 사용하기

준비 작업

가장 쉽게 돈 안들이고 구성하기 위해서 Network file system(NFS)을 설치하여 사용한다.

CentOS에 NFS 설치 & 구성

우선 설치는 다음과 같이 쉽게 할 수 있다.

$ yum install nfs-utils

설치가 끝났면, nfs 데몬을 시작하고 재부팅시 자동으로 실행 될수 있도록 설정한다.

# nfs 서버 기동
$ systemctl start nfs-server
# 서버 재기동시 nfs 서버 기동
$ systemctl enable nfs-server

이후 exports 할 디렉토리를 생성하고 exports에 해당 위치를 설정 합니다.

$ mkdir /nfs
$ vi /etc/exports
/nfs *(rw,root-squash,sync)

수정이 다 되었다면, 다음 명령으로 변경된 내역을 반영합니다.

$ exportfs -r

이후 해당 서비스를 다른 서버에서 사용하기 위해 방화벽을 허용해야 합니다.

$ firewall-cmd --permanent --add-service=nfs
$ firewall-cmd --reload
$ firewall-cmd --list-all

마지막으로 NFS 공유가 잘되었는지 확인합니다.

$ showmount -e
Export list for server:
/nfs *

$ sudo exportfs -v
/nfs              <world>(sync,wdelay,hide,no_subtree_check,sec=sys,rw,secure,root_squash,all_squash)

추가 정보 /etc/exports 설정 정보

옵션 기능
ro 파일 시스템을 읽기전용으로 마운트
rw 파일시스템을 읽기/쓰기 로 마운트
root_squash 클라이언트에서 루트를 서버상에 nobody 사용자로 매핑
no_root_squash 서버와 클라이언트 모두 같은 root를 사용
secure 클라이언트 마운트 요청시 포트를 1024 이하로 설정
anonuid 익명 사용자를 위한 사용자 ID를 지정하실 수 있음
anongid 익명 사용자를 위한 그룹 ID를 지정하실 수 있음
insecure 인증되지 않은 액세스도 가능
noaccess 액세스 거부
link_relative 서버에 있는 루트와의 링크를 포함하는 디렉토리에서 얻는 "../" 만큼 링크 앞에 두어 절대 심볼릭 링크를 상대 심볼릭 링크로 바꿀때 사용
sync 파일 시스템이 변경되면 즉시 동기화합니다.
async sync 옵션을 사용하지 않는 경우에 해당 하며, 서버는 데이터가 저장소에 안전히 저장됐는지를 확인하지 않음 클라이언트의 데이터 쓰기 요청이 들어오면 바로 응답을 보냄 데이터 curruption이 발생할 수 있지만 성능 향상을 기대할 수 있음
no_subtree_check 파일 시스템의 전체 디렉토리가 아닌 하부 디렉토리가 내보내진 경우, 서버는 내보낸 하부 디렉토리에 요청된 파일이 존재하는지를 검사 함 이러한 검사 과정을 하부구조 검사라고 부르는데, 이 옵션을 선택하시면 하부구조 검사를 사용하지 않음 전체 파일 시스템이 내보내진 경우에 이 옵션을 선택하면 하부구조 검사를 하지 않음으로서 전송률을 높일 수 있음
all_squash root를 제외하고 서버와 클라이언트의 사용자를 동일한 권한으로 설정
no_all_squash root를 제외하고 서버와 클라이언트의 사용자들을 하나의 권한을 가지도록 설정
NFS Exporting 설정 예
/*
/home/redhat  디렉토리를 one.linux.co.kr과 two.linux.co.kr 
두 개의 클라이언트 컴퓨터들이 마운트할 수 있으며, 
one 클라이언트 컴퓨터는 오직 읽기로만 마운트되고, 
two 클라이언트 컴퓨터에는 읽기/쓰기로 마운트 된다.
*/

/home/redhat   one.linux.co.kr  (ro)  two.linux.co.kr  (rw)
# linux.co.kr 도메인 내에 있는 모든 컴퓨터들이 /usr/local/bin 파일 시스템을 읽기 전용으로 마운트된다.
/usr/local/bin    *.linux.co.kr    (ro)
# /pub 디렉토리에 대해서 읽기로만 마운트할 수 있고, 사용자 인증이 없이 액세스가 가능하며, 이 데렉토리 파일 시스템에 액세스 하는 모든 컴퓨터의 루트를 서버에서 nobody 사용자로 액세스할 수 있게 한다는 의미이다.
/pub                                        (ro, insecure,root_square)

클라이언트 설치 테스트

우선 nfs 패키지를 설치 한다.

$ yum install nfs-utils

export 위치를 확인한다.

# 192.168.0.1 서버 IP
$ showmount -e 192.168.0.1
Export list for server:
/nfs *

NFS 디렉토리와 마운트 한다.

마운트할 디렉토리 생성
$ mkdir /test/nfs
# 마운트
$ mount -t nfs -o sync 192.168.0.1:/nfs /test/nfs
# 확인
$ df -h | grep nfs
192.168.0.1:/nfs  228G  9.8G  218G   5% /test/nfs

만약 리부팅시 자동으로 마운트 하기를 원한다면 다음과 같이 설정한다.

$ vim /etc/fstab
192.168.0.1:/nfs     /test/nfs       nfs     sync    0 0

mount를 끊기를 원한다면 다음과 같이 하면 된다.

$ umount -f -l /test/nfs

오류 발생 Linux: clnt_create: RPC: Program not registered 를 확인하면,

nfs service가 제대로 기동 되지 않은 것이다. 다시 시작하자!

$ service nfs status
rpc.svcgssd is stopped
rpc.mountd is stopped
nfsd is stopped
rpc.rquotad is stopped

$ service nfs start
Starting NFS services:                                     [  OK  ]
Starting NFS quotas:                                       [  OK  ]
Starting NFS daemon:                                       [  OK  ]
Starting NFS mountd:                                       [  OK  ]

$ chkconfig nfs on

Persistent Volumes 추가

kuberctl로 추가 하는 방법도 있고, 지금 사용하는 Rancher UI에서 처리 하는 방법도 있다.

간단하게 Rancher UI에서 설정하는 방식은 우선 아래 메뉴로 이동 한다.

이후 Add Volumes 버튼을 클릭해서 Volume을 설정을 한다.

설정을 저장하면 다음과 같이 추가된 내역을 확인 할 수 있다.

Claim 설정

Available 된 Persistent Volumes을 pod와 연동을 위해서 Claim과 연결 해야 한다.

다음 메뉴로 이동 한다.

Add Volumn 버튼을 클릭하고, 아래와 같이 설정 한다.

저장을 하고 나면, Bound 된 상태 확인이 가능하다.

사용해보기

이제 설정이 다 되었으면 다음과 같이 사용 하면 된다.

---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: elasticsearch
  namespace: devops-tool
  labels:
    app: elasticsearch
spec:
  replicas: 1
  selector:
    matchLabels:
      app: elasticsearch
  template:
    metadata:
      labels:
        app: elasticsearch
    spec:
      containers:
      - name: elasticsearch
        image: elasticsearch:latest
        ports:
        - containerPort: 9200
        imagePullPolicy: Always
        volumeMounts:
        - mountPath: /usr/share/elasticsearch/data
          name: elasticsearchdata
      volumes:
      - name: elasticsearchdata
        persistentVolumeClaim:
          claimName: mongodb-claim
---
apiVersion: v1
kind: Service
metadata:
  namespace: devops-tool
  name: elasticsearch
spec:
  ports:
    - port: 9200
      targetPort: 9200
      protocol: TCP
      name: http
      nodePort: 30560
  selector:
    app: elasticsearch
  type: LoadBalancer
---

중간에 내용을 보면,

        volumeMounts:
        - mountPath: /usr/share/elasticsearch/data
          name: elasticsearchdata
      volumes:
      - name: elasticsearchdata
        persistentVolumeClaim:
          claimName: mongodb-claim

여기를 잘 보면 된다.

참고 자료

Posted by lahuman

댓글을 달아 주세요

fluentd를 활용해 kubernetes 로그를 elasticsearch에 저장하고 kibana로 표출 해보자!

kubernetes를 셋팅을 하고 다음으로 해야 할일은 모니터링이다.

그 작업의 기초가 되는일이 바로 로깅을 쌓는 일이다.

모든 컨테이너의 로그들을 모아서 한 곳에서 확인할 수 있도록 구성했다.

각 컨테이너에서 로그를 가져오는 것은 fluentd를 이용했다.

fluentd에서 elasticsearch로 데이터를 적재 하도록 설정하였고, kibana를 통해서 해당 데이터를 표출했다.

kubernetes <-로그수집- fluentd -데이터 적재-> elasticsearch <-표출- kibana

구축 순서

  1. elasticsearch
  2. kibana
  3. fluentd

elasticsearch 구성

kubernetes의 오브젝트를 생성하기 위한 yaml 파일을 다음과 같이 생성한다.

# elastic.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: elasticsearch
  labels:
    app: elasticsearch
spec:
  replicas: 1
  selector:
    matchLabels:
      app: elasticsearch
  template:
    metadata:
      labels:
        app: elasticsearch
    spec:
      containers:
      - name: elasticsearch
        image: elastic/elasticsearch:6.8.6
        env:
        - name: discovery.type
          value: "single-node"
        ports:
        - containerPort: 9200
        - containerPort: 9300
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: elasticsearch
  name: elasticsearch-svc
  namespace: default
spec:
  ports:
  - name: elasticsearch-rest
    nodePort: 30482
    port: 9200
    protocol: TCP
    targetPort: 9200
  - name: elasticsearch-nodecom
    nodePort: 30930
    port: 9300
    protocol: TCP
    targetPort: 9300
  selector:
    app: elasticsearch
  type: NodePort

kubectl 명령어를 이용해서 오브젝트를 kubernetes에 생성한다.

$ kbuectl apply -f elastic.yml
deployment.apps/elasticsearch created
service/elasticsearch-svc created

설정된 노드포트를 통해서 서비스를 확인할 수 있다.

http://${kubernetes_host}:30842/

kibana 구성

kubernetes의 오브젝트를 생성하기 위한 yaml 파일을 다음과 같이 생성한다.

# kibana.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: kibana
  labels:
    app: kibana
spec:
  replicas: 1
  selector:
    matchLabels:
      app: kibana
  template:
    metadata:
      labels:
        app: kibana
    spec:
      containers:
      - name: kibana
        image: elastic/kibana:6.8.6
        env:
        - name: SERVER_NAME
          value: "kibana.kubenetes.example.com"
        - name: ELASTICSEARCH_URL
          value: "http://elasticsearch-svc.default.svc.cluster.local:9200"
        ports:
        - containerPort: 5601
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: kibana
  name: kibana-svc
  namespace: default
spec:
  ports:
  - nodePort: 30920
    port: 5601
    protocol: TCP
    targetPort: 5601
  selector:
    app: kibana
  type: NodePort

연결하는 elasticsearch 주소는 http://elasticsearch-svc.default.svc.cluster.local:9200이다.
kubectl 명령어를 이용해서 오브젝트를 kubernetes에 생성한다.

$ kbuectl apply -f kibana.yml
deployment.apps/kibana created
service/kibana-svc created

설정된 노드포트를 통해서 서비스를 확인할 수 있다.

fluentd 구성

kubernetes의 오브젝트를 생성하기 위한 yaml 파일을 다음과 같이 생성한다.

# fluentd.yml

apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    k8s-app: fluentd
  name: fluentd
  namespace: kube-system

---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: fluentd
rules:
  - apiGroups:
      - ""
    resources:
      - "namespaces"
      - "pods"
    verbs:
      - "list"
      - "get"
      - "watch"

---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: fluentd
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: fluentd
subjects:
- kind: ServiceAccount
  name: fluentd
  namespace: kube-system

---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd
  namespace: kube-system
  labels:
    k8s-app: fluentd-logging
    version: v1
    kubernetes.io/cluster-service: "true"
spec:
  selector:
    matchLabels:
      k8s-app: fluentd-logging
  template:
    metadata:
      labels:
        k8s-app: fluentd-logging
        version: v1
        kubernetes.io/cluster-service: "true"
    spec:
      serviceAccount: fluentd
      serviceAccountName: fluentd
      tolerations:
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
      containers:
      - name: fluentd
        image: fluent/fluentd-kubernetes-daemonset:v1.4.2-debian-elasticsearch-1.1
        env:
          - name:  FLUENT_ELASTICSEARCH_HOST
            value: "elasticsearch-svc.default.svc.cluster.local"
          - name:  FLUENT_ELASTICSEARCH_PORT
            value: "9200"
          - name: FLUENT_ELASTICSEARCH_SCHEME
            value: "http"
          - name: FLUENTD_SYSTEMD_CONF
            value: "disable"
          - name: FLUENT_UID
            value: "0"
        resources:
          limits:
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 200Mi
        volumeMounts:
        - name: varlog
          mountPath: /var/log
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
      terminationGracePeriodSeconds: 30
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers

위의 설정에서 보면 /var/log를 모두 로그를 가져오며 가져온 데이터는 http://elasticsearch-svc.default.svc.cluster.local:9200에 적재 한다.

kubectl 명령어를 이용해서 오브젝트를 kubernetes에 생성한다.

$ kbuectl apply -f fluentd.yml
serviceaccount/fluentd created
clusterrole.rbac.authorization.k8s.io/fluentd created
clusterrolebinding.rbac.authorization.k8s.io/fluentd created
daemonset.apps/fluentd created

설치시 오류 발생에 따른 해결책

unable to recognize “filebeat-kubernetes.yaml”: no matches for kind “DaemonSet” in version “extensions/v1beta1” 과 같은 오류가 발생한 이유는 apiVersion이 extensions/v1beta1을 사용하지 말고 apps/v1을 사용하도록 되어 있다.

다음과 같은 오류가 발생할 경우,

2018-11-26 23:19:44 +0000 [warn]: suppressed same stacktrace
2018-11-26 23:19:50 +0000 [info]: stats - namespace_cache_size: 3, pod_cache_size: 6, namespace_cache_api_updates: 15, pod_cache_api_updates: 15, id_cache_miss: 15
2018-11-26 23:20:14 +0000 [warn]: temporarily failed to flush the buffer. next_retry=2018-11-26 23:20:44 +0000 error_class="MultiJson::AdapterError" error="Did not recognize your adapter specification (cannot load such file -- bigdecimal)." plugin_id="out_es"

debian 계열의 이미지를 사용하면 된다.

containers:
- name: fluentd
image: fluent/fluentd-kubernetes-daemonset:v1.4.2-debian-elasticsearch-1.1

Did not recognize your adapter specification #230

설치가 완료되고 나면, 각 worker node에서 기동하는 것을 확인 할 수 있다.

kibana 설정

Management => kibana => Index Patterns => Create Index Pattern => "logstash-*" 추가

위와 같이 처리 하면 다음과 같은 결과를 확인 할 수 있다.

마치며

한땀 한땀 설치 kubernetes의 오부젝트에 대하여 더 많이 이해하게 되었다.

데이터 적재의 형태나, node의 error 로그 적재 등은 좀더 확인해봐야겠다.

참고자료

Posted by lahuman

댓글을 달아 주세요

참고 자료

Posted by lahuman

댓글을 달아 주세요