Category: Kubernetes

쿠버네티스에 관한 글들의 모음.

Kubernetes, Terminated 테스트

Pod 의 Terminated 테스트를 위한 테스트 배포는 다음과 같다.

위 Manifest 를 배포하면 Pod 의 Terminated 를 테스트 할 수 있다.

Kubernetes 에 Grafana 설치

Grafana 는 TimeSeries 데이터베이스의 데이터를 불러와 시각화를 해주는 솔루션이다. 특히 TimeSeries 데이터베이스 Prometheus를 지원하고 있어 Kubernetes 에 각종 메트릭을 Grafana 로 시각화해서 볼 수 있다.

이번에는 Kubernetes 에 Grafana 설치 에 대해서 다룬다. Grafana 설치를 하기전에 Prometheus 가 이미 설치되어 있어야 한다.

Grafana 를 위한 PV, PVC

Grafana 도 데이터파일을 가지고 있다. 각종 그래프 정보과 설정 내용들을 저장하기위해 데이터파일을 사용한다. 이 데이터파일의 위치는 특별하게 지정하지 않는한 /var/lib/grafana 이며 이것을 PV 에 마운트해 영구저장소에 저장되도록 하면 된다.

knode 에 /opt/grafana 디렉토리를 마운트 하도록 했다. 그리고 PVC 가 반납되더라도 PV 는 데이터를 그대로 유지하도록 retain 으로 설정했다. 이제 생성해 준다.

정상적으로 생성이 되었다면 PVC 의 상태가 Bound 로 보인다.

Secret 생성

Kubernetes 는 Secret 객체를 제공 한다. 이것을 이용하면 패스워드와 같은 비밀이 필요한 필드 값들을 암호화해서 저장할 수 있다. 이렇게 하는 이유는 Pod 에 배포되는 소프트웨어들은 비상태여야 하며 언제든지 Pod 는 삭제되어 질 수 있어야 하기 때문에 각종 설정에 필요한 파라메터들도 외부에서 관리되어져야 한다.

Grafana 설치를 하는데 있어 Secret 를 이용하는 이유는 Grafana 의 관리자 계정 때문이다. 아무나 Grafana를 조작하지 못하도록 계정 정책을 가지고 있는데, ID 와 패스워드를 발급해야 한다. 관리자의 경우에 ID 는 admin 이고 패스워드는 설치할때에 지정해 줄 수 있는데 이것을 Kubernetes 의 Secret 으로 등록해 Pod 가 생성될때에 적용되게 한다.

Secret 은 Key – Value 쌍으로 간단하게 정의할 수 있다. 다음과 같이 적용한다.

Grafana Deployment

PV, Secret 을 생성했다면 이제 Deployment 를 만들어 Pod 를 생성해보자. Deployment 에는 Secret, PV 를 적용시켜야 한다.

nodeSelector 를 이용해 knode 에 생성하도록 했다. 앞에서 생성한 PVC 를 사용하도록 했으며 secretKeyRef 를 이용해 Grafana 의 변수에 Secret 에 초기 아이디, 패스워드를 지정해주고 있다.

다음과 같이 적용해 준다.

NodePort 서비스 생성

Grafana 가 제대로 설치되었는지를 확인하기 위해서 외부에서 접속이 되도록 NodePort 로 Service 를 생성해 보자.

Service 에 대한 포트는 3000 이며 Pod 에 포트도 3000 이여서 targetPort 를 3000 으로 지정했다. 그리고 nodePort 를 30004 으로 지정했다.

다음과 같이 적용해 준다.

이렇게 하면 Kmaster 서버의 IP:30004 로 웹 접속을 하면 Grafana 화면이 보여야 한다.

Grafana 에서 Prometheus 데이터소스 추가

Grafana 와 Prometheus 는 Kubernetes 상에서 작동되고 있다. Kubernetes 에서 서비스에 접속을 하기 위해서는 Service 객체에 등록해 IP와 Port를 할당하면 Kubernetes Cluster 내에서는 Service 객체에 등록한 IP:Port 로 접속이 가능하다.

Grafana 에 성공적으로 접속을 했다면 TimeSeries 데이터소스를 추가해줘야 한다. Prometheus 를 지원하고 있기 때문에 접속 URL 을 입력해줘야 하는데, 이때 Prometheus 가 Kubernetes 상에서 작동되고 있다는 것을 상기해야 하며 Service 객체에 등록되어 Cluster IP:Port 를 입력해 줘야 한다.

Service 객체를 확인한다.

확인된 내용은 10.103.84.171 과 8080 이다. 이것이 Prometheus 에 Cluster 내에 접속 지점이 된다.

Kubernetes Monitoring – Prometheus 설치

이 글은 Kubernetes 에 모니터링을 위해 Prometheus 설치에 대한 것이다. Kubernetes 는 여러가지 오브젝트들과 컴포넌트들로 구성 된다. 각각에 구성요소들은 컴퓨터의 자원을 사용하게 되는데 이러한 자원 사용량은 metric-server 를 설치함으로써 CLI 를 통해서 실시간으로 모니터링이 가능하다.

하지만 CLI 를 하나하나 다 치면서 하는데에는 한계가 있어, 각종 구성요소들의 자원 사용량을 데이터베이스로 저장하고 이것을 기반으로 그래프로 보여주는 것이 훨씬 좋을 것이다. 특히나 각종 자원의 모니터링은 시인성이 아주 좋아야 하는게 핵심이기도 한데 Kubernetes 는 이를 위해서 Prometheus 를 공식적(?) 으로 밀고 있다.

Prometheus

프로메테우스(Prometheus) 는 한 회사에서 만들기 시작해 오픈소스화 되었으며 현재는 Kubernetes 를 제작지원하는 CNCF(Cloud Native Computing Foundation) 의 두번째 프로젝트다. 이렇게 되면 당연히 Kubernetes 에서 Prometheus 는 거의 표준 모니터링 시스템이라고 봐야 한다.

인터넷을 검색해보면 위와같은 그림을 볼 수 있는데, 처음 접하는 사람들은 당연히 이게 뭔지 잘 모른다. Prometheus 를 이루는 기본 요소는 단 두개다.

  1. Prometheus Server
  2. Node Exporter

간단하게 Server/Client 구조를 가지는 것인데, 특이한 것은 Prometheus Server 가 데이터를 가지고 오는 방법이다. Node Exporter 는 어떤 정보를 수집할지에 대해서 정의를 해두고 정해진 시간마다 정보를 수집한다. 그리고네트워크를 통해서 Prometheus Server 가 가지고 갈 수 있도록 네트워크 데몬으로 존재한다.

Prometheus Server 는 Node Exporter 목록을 가지고 있으면서 주기적으로 접속해서 데이터를 긁어온다. 이렇게 긁어온 데이터는 Prometheus 가 TimeSeries 데이터베이스로 저장하게 된다.

위 그림에 왼쪽 아래쪽에 KUBERNETES NODES 로 향하는 화살표에 Pull 이라고 적혀있는데, 이것이 Prometheus 가 Node Exporter 에 접속해 데이터를 긁어오는 것을 말하는 것이다.

metric-server, metric-state-server

Kubernetes 는 자신의 상태를 자동으로 모니터링해서 보여주지 않는다. 이것도 관리자가 설치해야 한다. 이를 위해서 인터넷을 검색해보면 다음과 같이 두가지 정도가 나온다.

  • metric-server
  • kube-state-metrics

metric-server 는 Kubernetes 자신에 대한 자원 모니터링으로 Node, Pod 등의 자원을 모니터링 한다. 이것은 Resource Metrics API 를 구현한 것으로 보면 된다. 이를 설치하면 HPA(Horizontal Pod Autoscaler), Scheduler 등에서 활용하게 된다.

HPA, Scheduler 등은 실시간으로 CPU, Memory 등에 변화를 감지해야 하며 이를 통해서 액션을 취해야하기 때문에 Kubernetes 의 Health 상태도 더블어 체크 된다. 자원이 Health 상태가 되지 않는다면 Kubernetes 의 상태를 Unknown 으로 바꾸놓을 가능성이 있다. 그리고 이 상태가 지속되면 Terminated 시켜버리고 다른 오브젝트를 올릴려고 할 것이다.

문제는 Prometheus 에서 이들에 대해서 스크랩을 할 수 없다는데 있다.

kube-state-metrics 는 Kubernetes 자원의 Health 상태를 전혀 고려하지 않는다. 그냥 자원에 대한 정보를 뿌려줄뿐이고 어떤 원인으로 인해서 자원 모니터링이 안된다면 그냥 정보를 안 뿌려준다. 따라서 이렇게 되며 이것을 가지고 HPA, Scheduler 에서 사용하기가 불가능해진다.

대신, kube-state-metrics 는 Prometheus 에서 스크랩이 가능하다. 따라서 Prometheus 를 이용한 모니터링을 구축하기 위해서는 반드시 kube-state-metrics 를 설치해주는 걸 권장한다.

kube-state-metrics 설치

Prometheus 설치의 시작은 kube-state-metrics 설치로부터 시작 된다. 이것이 없으면 Prometheus 설치/운영을 못하는 것은 아니지만 Kubernetes 의 컴포넌트의 자세한 정보를 가지고 올 수 없다.

설치는 kube-state-metrics 의 GitHub 를 이용하면 간단하게 해결된다. 한 가지 주의해야 할 것은 Kubernetes 버전을 확인해 지원되는 버전을 설치해야 한다는 것이다.

소스코드를 clone 한 후에 다음과 같이 설치를 해준다. Kubernetes 가 최신버전이라 별도의 작업은 필요 없다.

정상적으로 설치가 되었다면 kube-system 네임스페이스에 pod 가 보인다.

Prometheus 설치

먼저 Prometheus 설치하는 방법에는 다양한 방법이 존재한다. helm 을 이용해도 되고 Prometheus Operator 를 이용해도 된다. 하지만 수동으로 설치를 해봐야 Kubernetes 에서 프로그램 배포를 위해서 필요한 것들이 무엇인지를 알게 된다. 따라서 여기서는 모든걸 수동으로 한번 해보도록 하겠다.

계획

일단, 계획이 필요한데 뭔가 대단한게 아니라 Prometheus 를 운영하는데 필요한 설정과 파일들을 어떻게 할 것인가에 대한 것이다.

먼저, Prometheus 를 위한 네임스페이스를 별도로 만든다. Kubernetes 는 네임스페이스 개념이 존재한다. 일종의 격리되는 그룹같은 것인데, Prometheus 를 위한 네임스페이스로 montoring 을 만들 것이다.

Prometheus 는 설정 파일과 데이터 저장 파일 크게 두가지로 나뉜다. 설정 파일은 그야말로 메트릭 수집과 운영에 대한 것으로 text 파일이며 데이터 저장 파일은 수집된 정보를 저장하는 TimeSeries 데이터 파일이다.

  • prometheus.yaml
  • tdb

Kubernetes 는 배포되는 프로그램의 각종 설정들을 pod 자체에 가지고 있게 하지 않는다. 이것은 pod 가 비상태 운영을 기본원칙으로 하기 때문이다. pod 는 언제든지 사라지고 만들어지고 해야 한다. pod 내에 배포되는 프로그램들의 설정파일을 pod 에 내장하게 되면 뭐하나 바꿀때마다 pod 를 손대야 한다.

ConfigMap 은 이렇게 Kubernetes 의 비상태 운영 원칙을 위한 것이다. 설정 맵은 그야말로 다양한 설정들의 내용을 Kubernetes 가 대신 가지고 있게 해준다. 예를들어 Prometheus 의 설정파일인 prometheus.yaml 은 text 파일인데, 이것을 ConfigMap 에 등록하고 Pod 생성시에 이것을 가지고와서 파일로 굽게 된다. 설정파일을 Kubernetest 가 가지고 있기 때문에 설정 편집을 위해서 pod 에 손을 댈 일은 없다.

데이터 저장 파일은 영구적인 저장 파일이다. Pod 에 내장되어 있다면 Pod 가 재시작될때마다 데이터 저장 파일은 삭제되었다 재 생성되는 과정을 반복할 것이다. 하지만 Pod 의 재시작과는 상관없이 데이터는 영구적으로 보존 되어야 하기 때문에 Pod 에 영구볼륨(Persistant Volume) 을 붙여서 데이터 저장 파일을 Pod 와 분리할 것이다.

추가로 Prometheus 나 exporter 들이 Kubernetes 의 API 에 접근할 수 있도록 계정과 권한도 부여할 것이다.

monitoring 네임스페이스 생성

Kubernetes 의 네임스페이스 생성은 아주 간단다. CLI 명령어로 간단하게 생성할 수 있다.

ClusterRole 생성

Kubernetes 의 자원에 대한 접근은 API 를 통해서 이루어 진다. API 접근은 Kubernetes 의 보안 부분으로 엄격하게 통제되고 있는데, Prometheus 가 이 API 에 접근해 자원에 대한 메트릭을 생성해야 하기 때문에 이에 대한 접근 권한이 필요하게 된다.

Kubernetes 의 API 에 대한 권한은 Role 개념으로 정립되어 있으며 이 Role 에 기반한 퍼미션을 부여하고 이것을 다시 특정한 계정과 바인딩 함으로써 접근제어는 마무리 된다.

위와같이 ClusterRole 을 작성한 후에 적용해 준다.

Prometheus 를 위한 영구볼륨 생성

Kubernetes 에서 영구 볼륨은 Persistant Volume 과 Claim 개념으로 다루어 진다. PV 는 영구저장소 미디어 특성을 고려한 일종의 드라이버 개념이고 Claim 은 영구저장소 미디어와는 상관없는 추상적 개층으로 PV 와 연결되어 작동된다.

Prometheus 는 데이터베이스 파일을 영구적으로 저장할 필요성이 있기 때문에 Kubernetes 의 PV, PVC 를 이용할 필요가 있다.

먼저 다음과 같이 PV 를 만든다.

중요한 것은 영구저장소를 이용할 Kubernetes 의 Node 를 지정해 주었고, 사용할 저장소는 디렉토리이며 없으면 생성하도록 했다. 거기다 ReclaimPolicy 를 Retain 으로 함으로써 PVC 와 연결이 해제되더라도 PV 는 그대로 데이터를 보존하도록 했다. 사용할 디렉토리 경로는 /opt/prometheus 로 지정 했다.

다음과 같이 생성해 준다.

이제 PV 를 가져다 쓸 PVC 를 생성해야 한다.

PVC 를 생성할 때에는 PV 에서 가져다 쓸 용량도 함께 기재한다. 당연한 이야기지만 PV 보다 많은 용량은 허용되지 않는다. 한가지 주의해야 할 것은 PV 의 Label 과 StorageClass 를 맞춰야 한다. 이게 어긋날 경우에는 PVC 가 제대로 연결되지 않는다.

다음과 같이 생성해 준다.

정상적으로 생성이 되면 위와같이 PVC 의 Status 가 Bound 로 표시 된다.

Prometheus 를 위한 ConfigMap 생성

앞에서도 이야기 했지만, Kubernetes 에서 Pod 는 비상태여야 한다. Pod 는 Replica 정책에 의해서 항상 특정한 수를 유지하도록 하는데, 간혹 Pod 가 알수 없는 이유로 재생성되는 경우가 발생하는데 이럴때에 Pod 가 상태를 가지는 파일을 가지고 있게 되면 데이터 손실이 발생하게 된다.

그래서 각종 서버에 대한 설정파일들을 Kubernetes 에 ConfigMap 으로 등록하고 Pod가 생성될때에 이를 가져다 설정파일로 만들도록 권장하고 있다.

ConfigMap 을 만드는 방법에는 크게 두가지로 나뉜다. 첫번째는 ConfigMap 메니페스트 파일에 설정 내용을 모두 함께 기술하는 것과 서버 설정파일을 특정한 디렉토리에 만든 다음에 kubectl 명령어로 ConfigMap 을 만드는 것이다. 어떤 방법을 쓰던지 결과는 동일하다.

여기선 설정 파일을 특정 디렉토리 별도로 만들어서 kubectl 명령어를 이용해 ConfigMap 을 작성하는 것으로 한다.

Prometheus 를 위한 설정 파일은 prometheus.yml 파일이다. 단 하나의 파일로 모두 가능하지만 rules 같은 경우에는 별도의 파일로 작성해 include 문을 작성해 연결 시킬 수 있다. 여기서는 두개의 파일로 제작했다.

prometheus.rules 파일에 rules 만 정의했다. 내용을 보면 Prometheus 에 알람을 보내는 Rule 을 적은 것이다. 이 파일은 prometheus.yml 파일에 include 문을 통해서 포함 된다.

prometheus.yml 파일의 내용을 보면 어떤 정보를 수집할지에 대해서 기술하고 있다. 전체적으로 10s 단위로 메트릭 정보를 수집하도록 하고 있으며 kube-state-metrics 에 대해서는 도메인 호출을해서 스크랩을 하도록 하고 있다. 그밖에 각종 Kubernetes 컴포넌트들에 대해서도 Kubernetes 의 API 서버를 통해서 메트릭을 수집하도록 설정하고 있다.

이렇게 설정내용을 파일로 작성하였다면 kubectl 명령어를 이용해 ConfigMap 을 다음과 같이 생성할 수 있다.

정상적으로 생성이 되었을 것이다.

이제 필요한 제반 사항들은 모두 만들어 졌다. 실제 Prometheus 배포로 Pod 를 생성해 보자.

Prometheus 를 위한 Deployment

Kubernetes 가 버전이 높아지면 Deployment 를 기반으로 여러개의 Pod 를 생성하도록 변경되었다. 여기서는 Prometheus 를 만들어야 하는데, 단순하게 Pod 만 생성하는게 아니라 Deployment 를 이용해서 Pod 를 생성 한다.

지금까지 만들었던 제반사항들이 모두 포함되어 있다. ServiceAccount 의 경우에는 Deployment.spec.serviceAccountName 에 prometheus 로 지정해 ClusterBinding 으로 묶인 메트릭 수집을 위한 API 접근을 부여하고 있다. Volume 마운트 에서는 ConfigMap 을 마운트해 파일을 작성과 PVC 를 마운트해 Prometheus 의 데이터 저장 디렉토리로 마운트 해주고 있다.

다음과 같이 생성해 준다.

처음 실행을 하면 위와 같이 에러가 발생 한다. 로그를 한번 보자.

“permission denied” 이 에러는 PV 에서 생성한 /opt/prometheus 디렉토리에 대한 권한이 없어서 나는 것이다. PV 를 생성한 Node 에 다음과 같이 퍼미션을 부여 한다.

위와같이 퍼미션을 조정해 주면 자동으로 Pod 가 재배포 되면서 정상화 된다.

접속을 위한 Service 배포

Kubernetes 는 기본적으로 Cluster 내에서의 접속만 허용 한다. 외부에서 접속이 되게 하기 위해서는 Service 배포를 통해서 NodPort 를 열거나 아니면 Port-Forward 를 설정을 해서 접속을 해야 한다.

여기선 Service 배포를 통해서 NodePort 를 배포해 준다.

Deployment 에서 Container 포트를 9090 으로 해줬다. Service 에서는 targetPort 로 Container 포트를 인식시켜주고 Service 에서 사용할 포트 8080 과 연결해준다. Cluster 내에서 8080 포트로 접속을 하면 Deployment 의 Container 에 9090 와 연결되어 응답이 오게 된다.

nodePort 를 지정해줘서 외부에서도 접속할 수 있도록 오픈해 준다.

다음과 같이 배포를 진행 한다.

Node Exportor

Node Exportor 는 Kubernetes 의 Node 에 대한 정보를 수집해 준다. Kubernetes 는 모든 것을 Pod 로 작동되는데, Node 에 하나씩만 작동되어야 하며 Kubernetes 클러스터와는 별도로 Node 자체에 데몬(Daemon) 처럼 동작해야 한다. 이를 위해서 DaemonSet 오브젝트로 만들어야 한다.

위 내용을 배포하게 되면 Node Exportor 가 DaemonSet 으로 동작한다. 그리고 Prometheus 는 정해진 시간마다 Node Exportor 에 접속해 메트릭을 수집하고 저장하게 된다.

마치며

Prometheus 는 Kubernetes 와 잘 작동 한다. Kubernetes 를 하면서 다양한 방법으로 설치를 진행할 수 있는데, 한번 쯤은 수동으로 모두 해보는 것을 권장하고 한번 공부해보길 권장한다. 그것만으로도 Kubernetes 에 대해서 상당히 많은 부분을 익힐 수가 있다.

그런 면에서 Prometheus 를 수동으로 모두 설치해보는 것은 가치가 있다.

Deployment, Unavailable 테스트

Kubernetes 의 Deployment 에서 pod 의 Unavailable 상태를 확인하기 위한 코드는 다음과 같다.

이것을 배포를 하면 Deployment 에 Pod가 Unavailable 상태를 보이게 된다.

Kubernetes 프로세스별 상태

Kubernetes 는 다양한 컴포넌트들로 인해서 작동된다. 이러한 컴포넌트들은 중요성에 있어서 약간의 차이가 있다. 예를들어 Worker Node 에서 docker 프로세스가 정지되거나 문제가 되었을때에 어떻게 될까? 혹은 Worker Node 에 kubelet 프로세스가 문제가 된다면?

이 문서는 Kubernetes 프로세스별 상태 에 대한 글이다.

환경

여기서 환경은 Kubernetes 의 객체를 말한다. 객체라함은 Pods, Deployments, Services, StatefulSet 으로 했다. 그밖에 다양한 객체가 있지만 이 정도 생성해서 진행해보기로 했다.

docker 정지

이것은 Work Node 에 docker 를 정지 시키는 것이다. 이렇게 되었을때에 Kubernetes 의 각종 컴포넌트들은 어떤 상태를 보일지 알아보자.

먼저, Nodes 상태는 ‘Notready’ 로 변경된다.

Node 의 자세한 상태를 describe 보면 다음과같이 몇가지 상태가 나온다.

  • Warning ContainerGCFailed 38s (x2 over 98s) kubelet, knode rpc error: code = Unknown desc = Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

Conditions 는 다음과 같이 된다.

두번째, Pods 상태.

상태가 STATUS 는 Completed 으로 나오고 READY 도 0/1 로 나온다. 정상으로 나오지 않는다. Pods 하나를 골라 describe 해보면 Ready 는 False 로 나온다.

세번째, Deployment 상태.

READY 가 0/3 으로 모두 문제가 있는 것으로 나온다.

네번째, Services 상태.

Service 에 상태는 없다.

다섯번째, StatefulSet 상태.

StatefulSet 상태로 READY 가 0/2 로 모두 문제가 있는 것으로 나온다. 하지만, Pods Status 에서는 “2 Running / 0 Waiting / 0 Succeeded / 0 Failed” 로 Pod 2개 Running 으로 나온다.

kubelet 정지

kubelet 은 Worker Node 에 명령을 수행하는 중요한 프로세스이다. 이를 정지했을때는 어떤 상태를 보일까..

Node 상태.

Node 상태는 NotReady 가 된다. 그리고 Conditions 상태는 다음과 같다.

Pods 상태

이상하게도 Pods 상태는 모두 정상으로 나온다. 하지만 Port-Foward 를 시도하면 되지 않는다.

Deployment 상태

비정상으로 나온다. READY 가 0/3 으로 표시된다.

StatefulSet 상태

비정상으로 나온다. READY 가 0/2 로 표시된다.

Worker Node 셧다운

이 상태는 kubelet 와 동일한 결과를 보여준다.

StatefulSet 에서 로컬 디스크 사용

이 문서는 StatefulSet 에서 로컬 디스크 사용 에 대한 글이다. Kubernetes 에서 디스크 사용은 어려운감이 있다. PersistentVolume 과 PersistentVolumeClaim 이라는 것을 알아야하고 이를 알고나서도 여러가지 속성들때문에 헷깔리는 경우가 많다.

PersistentVolume 관련해서 문서를 보면 대부분 클라우드가 제공하는 스토리지를 이용하는 예제가 많다. 그것이 아니라면 nfs 를 이용하는 경우가 많아서 나처럼 집에 컴퓨터를 이용하는 경우에 실습해 보기가 쉽지 않은게 사실이다.

StatefulSet 의 경우가 바로 이런 경우였다. StatefulSet 을 연구하기 위해서 여러가지 예제를 찾아봤고 다음과 같은 파일을 찾아냈다.

StatefulSet 은 비상태(stateless) 자원을 생성하는게 아니라 상태를 가지는 자원을 생성하게 해주는 Kubernetes 의 객체다. 대부분 Persistent Data 를 위한 것이기에 PersistentVolume 을 대부분 필요로 한다.

위 예제를 가지고 생성을 해보자.

정상적으로 생성이 됐다고 나온다. 확인을 해보자.

Pod 생성이 Pending 상태를 보이고 있다. 왜 이럴까? 앞에서 객체 생성을 정의한 yaml 파일을 자세히 보면 Persistent Volume 을 요청하고 있다. volumeClaimTemplates 이 바로 그것이다. 이것은 PersistentVolumeClaim 을 요청하는 것으로 나타난다. 확인해 보자.

persistentvolumeclaim 이 Pending 상태이다. 결국에는 이것으로 인해서 Pod 생성도 Pending 이 된 것이다.

해결방안

PersistentVolumeClaim 은 PersistentVolume 이 있어야 한다. 그리고 이것을 묶어줘야하는데 이것을 Bound 라고 한다. 문제는 web.yaml 을 실행했을때에 생성되는 PersistentVolumeClaim 과 PersistentVolume 을 어떻게 연결할 것인가?

좀더 정확하게 말하면 StatefulSet 이 자동으로 생성하는 PersistentVolumeClaim 과 PersistentVolume 을 어떻게 연결할 것인가?

StatefulSet 의 특징은 생성하는 객체의 이름이 임의대로 정해지지 않는다. 정확하게 사람이 인식하기 쉬운 이름으로 결정된다. 앞에서보면 Pod 의 이름이 web-0 이다. 이는 Pod 이름에 Replicas 의 첫번째인 0 을 붙여서 만든다.

StatefulSet 에서 PersistentVolumeClaim 이름은 예측 가능한 패턴을 따른다. volumeclaimtemplates-namestatefulset-namereplica-index. 그래서 생성된 PersistentVolumeClaim 의 이름이 www-web-0 가 된 것이다.

PersistentVolumeClaim 은 PersistentVolume 을 필요로 한다. PersistentVolume 을 생성할때에 claimRef.name 을 PersistentVolumeClaim 이름으로 지정한다. 이렇게 하면 PersistentVolumeClaim 이 생성될때에 PersistentVolume 이 이름과 연결되어 자동으로 Bound 되어진다. 다음과 같이 PersistentVolume 을 만든다.

이것은 Kubernetes Worker 호스트에 파일시스템에 특정 디렉토리를 PersistentVolume 으로 생성한다. 만일 디렉토리가 존재하지 않을 경우에는 생성하도록 한다. 그리고 PersistentVolumeClaim 이 삭제되면 이 볼륨도 함께 삭제되도록 했다.

여기서 중요한 것이 claimRef 필드이다. name 속성에 PersistentVolumeClaim 이름을 지정해준다.

또, nodeAffinity 필드를 이용해서 특정한 Worker 에서 생성되도록 했다.

StatefulSet 에서 replicas 를 2 로 했기 때문에 위 PersistentVolume 생성은 claimRef.name 이 www-web-0, www-web-1 로 두개가 필요하다.

두개의 PersistentVolume 을 생성하고 시간을 갖고 기다리면 다음과 같은 결과를 얻게 된다.

Worker 호스트에 PersistentVolume 에서 생성한 디렉토리가 있는지 확인해 보자.

이렇게 문제를 해결할 수 있다.

참고: StatefulSet 에서 기존 디스크 사용

Kubernetes 설치

Kubernetes 설치에 대해서 다룬다. 이번에는 Ubuntu 20.04 LTS, Centos 8.2 기반으로 진행했으며 이전에 설치에서 CNI 를 Calico 로 진행 했다. 더 나가 Helm, Metric Server 까지 진행 한다.

설치 환경은 다음과 같다.

  • Master
    • Distribution: Ubuntu 20.04
    • IP: 192.168.96.31
    • Hostname: kmaster
    • account: systemv
  • Worker Node
    • Distribution: CentOS 8.2
    • IP: 192.168.96.32
    • Hostname: knode
    • account: systemv
  • CNI: Calico
  • Helm 설치
  • Metric Server 설치

공통 설정 부분

Master, Node 두 서버 모두 Static IP 주소를 가지고 있어야 한다. 그리고 모두 일반 계정을 가지고 있어야 하며 이 일반 계정은 sudo 사용 권한을 가지고 있어야 한다.

sudo 권한 부여

CentOS 8.2 의 경우에 일반 계정을 생성한 후에 sudo 권한을 주고 싶다면 다음과 같이 하면 된다.

CentOS 8.2 에는 wheel 라고 하는 특수한 그룹이 존재하는데, sudo 설정에는 이 그룹에 한해 sudo 사용 권한을 부여하고 있어 일반 계정 systemv 에 sudo 를 사용하게하고 싶다면 wheel 그룹에 포함시키면 된다.

Ubuntu 20.04 에서는 다음과 같이 일반계정에 sudo 권한을 부여할 수 있다.

br_netfilter 모듈 로딩

br_netfilter 커널 모듈을 로딩해 줘야 한다. 기존에는 modprobe 설정으로 했지만 이제는 systemd 를 활용하면 되는데 ubuntu 20.04, CentOS 8.2 이 모두 이를 사용하고 있어서 적용 가능하다.

다음과 같이 모듈이름으로 conf 파일을 생성해 준다.

물론 이렇게 하면 시스템을 재부팅을 하더라도 자동으로 모듈이 로딩 된다.

커널 네트워크 파라메터

다음과 같이 커널 파라메터를 수정해 줘야 한다.

/etc/hosts 파일 편집

Master, Node 서버 양쪽 모두에 /etc/hosts 파일에 각 서버 정보를 다음과 같이 입력해준다.

swapoff 설정

kubernetes 는 swap 파티션이 존재할 경우에 동작하지 않을 수 있다. 예를들어, kubeadm 명령어로 뭔가를 할려고 할경우에 swap 파티션이 존재할 경우에 오류를 내면서 작동되지 않는다.

Master, Worke 양쪽 모두에 swap 을 off 로 해준다.

이렇게 하면 swap 이 비활성화 된다. 그리고 반드시 /etc/fstab 에서 swap 관련 마운트 설정을 주석처리 해준다.

CentOS 8.2 에서 설정

SELinux off

CentOS 8.2 에서 설정은 SELinux 설정이다. 다음과 같이 해준다.

firewalld 비활성화

이것은 systemctl 로 다음과 같이 가능하다.

패키지 설치

Ubuntu 에서 설정

패키지 설치

Docker 설치 및 설정

Kubernetes 는 Docker 를 기반으로하는 서비스다. 당연히 설치를 해줘야 하는데, 설치 관련 내용은 다음에 링크에서 각 배포판마다 잘 설명되어 있다.

한가지, Docker 설치를 위한 패키지 저장소는 명령어와 파일을 생성하는 방법 두가지가 있다.

Ubuntu 20.04

ubuntu 에서는 add-apt-repository 명령어로 저장소 URL 을 추가 가능하다. 예를 들면 다음과 같다.

저장소 추가가 되었다면 다음과 같이 Docker 를 설치해 준다.

CentOS 8.2

CentOS 8.2 에서는 yum-config-manager 명령어를 이용해서 추가할 수 있다. 이 명령어는 yum-utils 패키지에 포함되어 있어 설치하면 사용할 수 있다.

저장소 추가가 되었다면 다음과 같이 Docker 를 설치해 준다.

현시점에서 위와같은 오류가 발생한다. CentOS 8 에 대한 containerd 저장소가 존재하지 않기 때문에 필요한 정보만 출력하고 오류를 낸다. 수동으로 필요한 패키지를 다운받아서 해결한다.

수동으로 설치는 정상적으로 진행된다. 그리고 다음과 같이 Docker 를 설치해 준다.

CentOS 8.2 에서 Docker 를 설치하면 필요한 서비스가 자동으로 시작되지 않는다. 이를 위해서 다음과 같이 systemd 를 설정해주고 시작해준다.

CGroup Driver 설정

Ubuntu, CentOS 모두 공통으로 Docker 를 설정해 주는 부분이 존재한다. 바로 Driver 를 systemd 로 바꿔줘야 한다.

Kubernetes 를 설치할때에 Cgroup driver 를 systemd 로 추천하고 있다. 그래서 Kubernetes 만 systemd 로 드라이버를 교체하면 docker 와 통신이 되지 않는다. 이것을 위해서 Docker 에서도 드라이버를 systemd 로 교체해 준다.

다음과 같이 확인이 가능하다.

Kubernetes 설치

Ubuntu 20.04

Master 로 사용될 Ubuntu 20.04 에서 다음과 같이 Kubernetes 패키지 저장소를 추가 한다.

xenial 은 Ubuntu 16.04 를 말하는데 Ubuntu 20.04 에 설치하는데 아무런 문제가 없다.

다음과 같이 kubeadm, kubelet, kubectl 을 설치해 준다.

CentOS 8.2

CentOS 8.2 에서는 다음과 같이 Kubernetes 패키지 저장소를 추가 한다.

그리고 다음과 같이 Kubernetes 를 설치해 준다.

Master 설정

Master 를 다른 말로 Control Plaine 이라고도 한다. 이것을 만드는 것은 kubeadm 을 이용한다. 일반 계정으로 실행 한다.

Kubernetes Master 명령은 전부 일반계정으로 하도록 되어 있어 있다. 일반계정이 kube api 통신을 위한 설정을 위 출력에 나온데로 실행해주면 된다.

하지만 문제가 있다. 다음을 보자.

kmaster 가 ‘NotReady’ 나오고 coredns 상태가 ‘Pending’ 이다. kubelet 로그를 보자.

NetworkPlugin 이 없어 오류가 나오는 것으로 이는 CNI(Container Network Interface) 를 필요로 한다.

Calico 설치

Calico 는 Flannel 처럼 Kubernetes Cluster 에 네트워킹을 가능하도록 해준다. CNI 를 위한 컴포넌트중에 하나라고 보면 되는데, 한가지 주의해야 할 것은 반드시 메뉴얼을 읽어보고 해야 한다는 것이다.

Calico 는 Kubernetes 가 운영되는 환경에 따라 설치과정에 차이가 있으며 심지여 같은 운영환경이라고 할지라도 node 의 수에 따라서 설치해줘야하는 것도 다르다.

이 메뉴얼은 OnPremise 환경이며, 50 node 이하를 가지고 있음으로 아주 간단하게 다음과 같이 yaml 파일 하나만 다운로드 받아서 적용해주면 된다.

이제 시간을 조금 기달려서 모든 pods 가 정상으로 Running 인지를 확인해 본다.

그리고 nodes 의 상태를 확인해 본다.

“Ready” 상태가 되었음으로 이제 Worker Node 를 추가해 보자.

Worker Node 추가.

Worker Node 는 knode 서버에서 다음과 같이 Kubernetes Cluster 에 join 하겠다는 것으로 실현된다. join 을 위한 파라메터는 kmaster 에서 kubeadm 으로 cluster 를 생성할때 보여준 값을 입력하면 된다.

이렇게 한 다음에 kmaster 서버에서 다음과 같이 knode 가 추가되고 상태가 Ready 된다면 Worker Node 추가가 완료된 것이다.

Helm 3 설치하기

Helm 은 Kubernetes 에서 작동하는 많은 Application 들을 손쉽게 설치하도록 도와주는 프로그램이다. 마치 Ubuntu 의 APT 나 CentOS 의 Yum 이 프로그램 설치를 손쉽게 해주는것과 같다.

한가지 변화가 있다. Helm 2 와 Helm 3 은 완전히 다르다고 생각해야 한다. Helm 2 는 Tiller 라고 해서 Helm 서버가 필요했지만 Helm 3 에서는 이것이 없어졌다.

Helm 3 는 설치 스크립트를 제공함으로 이것을 이용하면 손쉽게 설치할 수 있다. 설치 Node는 kubectl 을 사용할 수 있는 곳이라면 어디선든 사용이 가능하다.

Helm 3 설치

Helm 3 설치는 스크립트로 제공한다.

설치는 그냥 바이너리를 다운로드 받아서 /usr/bin 에 helm 바이너리를 설치하는 것으로 끝난다.

정상적으로 설치됐는지 확인은 다음과 같이 한다.

한가지 문제는 기본 repository 주소가 없어서 뭐든 설치할려면 설치가 안된다. 이를 위해서 다음과 같이 저장소를 추가해 준다.

Helm 3 은 이것으로 끝이다. 이전 Helm 2 버전에 비해 해줘야 하는 것이 없다.

Metric Server 설치

Kubernetes 를 설치하게 되면 자원에 대한 모니터링이 필요하다. 과거에는 Heapster 를 이용했지만 이것은 이제 더 이상 개발이 되지 않고 있으며 이를 대체하는 것이 Metric Server 이다.

Kubernetes 에서 뭔가를 설치하는 것은 대부분 Pods 를 설치하는 것이며 이것에 대한 Rules, Datastore 등도 한꺼번에 설정을 해준다.

Metric Server 를 설치하게 되면 Kubernetes 의 컴포넌트들에 대한 자원 모니터링이 가능해지며 이것을 이용해 Autoscaling 에도 사용이 가능해진다.

Downloads

Metric Server 를 다음과 같이 다운로드를 한다.

TLS 수정

Metric Server 를 설치할때에 주의해야 할 것은 Kube API 서버와의 통신에서 사용할 TLS 를 수정하는 것이다. Metric Server 는 Public TLS 를 기본으로 하지만 Kube API 는 Kube 자체의 TLS 를 사용하기 때문에 그냥 설치하면 문제가 된다.

Deploy

이제 이것을 Deploy 해준다. Kubernetes 에서는 설치라는게 없다. 모두 다 pods 로 다 올라가기 때문에 Deploy 라고 한다.

위와같이 관련된 설정과 pods, deploy, service 등이 생성이 된다.

확인

Metric Server 의 확인은 pods, deploy 가 제대로 되었는지를 살펴보면 된다.

그리고 1~2분을 기다리면 후에 다음과 같이 자원이 출력이 되는지를 보면 된다.

CPU, Memory 등과 같은 자원 현황이 출력이 되면 정상적으로 작동하는 것이다.

Helm 설치하기

이 문서는 Kubernetes 의 Helm 설치에 대해 다룬다.

Helm 은 Kubernetes 에서 작동하는 많은 Application 들을 손쉽게 설치하도록 도와주는 프로그램이다. 마치 Ubuntu 의 APT 나 CentOS 의 Yum 이 프로그램 설치를 손쉽게 해주는것과 같다.

Helm

Helm 은 Client – Server 로 구성된다.

Client 는 CLI 명령어를 말하며 플랫폼마다 바이너리로 배포된다. 따라서 다운로드 받아서 압축을 풀면 바로 사용할 수 있다.

Server 는 Tiller 라고 불리운다. 이것은 Kubernetes 상에서 작동되는데 Deploy 해서 설치하면 된다.

Helm Client

Helm 클라이언트는 GitHub 에서 다운로드가 가능하다.

다음과 같이 설치가 잘되었는지 확인한다.

Helm Server – Tiller

Tiller 를 설치하기 위해서 서비스 계정을 생성하고 cluster-admin Role 을 생성해 준다. 이는 CLI 로 생성하거나 Yaml 을 이용해서 생성해도 된다.

파일을 작성해 다음과 같이 적용해 준다.

이제 Tiller 를 설치해 준다.

이제 다시 helm client 를 실행해보자.

이제 helm 의 저장소를 최신판으로 업데이트를 해보자.

Metric Server 설치하기

Kubernetes 를 설치하게 되면 자원에 대한 모니터링이 필요하다. 과거에는 Heapster 를 이용했지만 이것은 이제 더 이상 개발이 되지 않고 있으며 이를 대체하는 것이 Metric Server 이다.

Kubernetes 에서 뭔가를 설치하는 것은 대부분 Pods 를 설치하는 것이며 이것에 대한 Rules, Datastore 등도 한꺼번에 설정을 해준다.

Metric Server 를 설치하게 되면 Kubernetes 의 컴포넌트들에 대한 자원 모니터링이 가능해지며 이것을 이용해 Autoscaling 에도 사용이 가능해진다.

Downloads

Metric Server 를 다음과 같이 다운로드를 한다.

2020.04.19 현 시점에서 v0.3.7 이 있지만 ErrorImagePull 에러가 발생하면서 설치가 진행되지 않는다. 따라서 v0.3.6 으로 설치한다.

TLS 수정

Metric Server 를 설치할때에 주의해야 할 것은 Kube API 서버와의 통신에서 사용할 TLS 를 수정하는 것이다. Metric Server 는 Public TLS 를 기본으로 하지만 Kube API 는 Kube 자체의 TLS 를 사용하기 때문에 그냥 설치하면 문제가 된다.

Deploy

이제 이것을 Deploy 해준다. Kubernetes 에서는 설치라는게 없다. 모두 다 pods 로 다 올라가기 때문에 Deploy 라고 한다.

위와같이 관련된 설정과 pods, deploy, service 등이 생성이 된다.

확인

Metric Server 의 확인은 pods, deploy 가 제대로 되었는지를 살펴보면 된다.

그리고 1~2분을 기다리면 후에 다음과 같이 자원이 출력이 되는지를 보면 된다.

CPU, Memory 등과 같은 자원 현황이 출력이 되면 정상적으로 작동하는 것이다.

쿠버네티스(Kubernetes) 개념

쿠버네티스(Kubernetes) 처음 접하면 개념 잡기를 해야 한다. 쿠버네티스를 잘 사용하기 위한 사용법을 익히는것도 중요하지만 개념을 이해하고 나면 외워서 문제해결을 하는 것이 아닌 응용력이 생겨 예기치 않은 장애를 겪을때에 힘을 발휘한다.

개인적으로 쿠버네티스의 개념을 이해하는데 약간의 혼란이 있었다. 개념을 설명하는 용어와 실제 작업을 할때에 사용하는 단어, 명령어들이 다 틀리게 사용되고 있는데서 오는 것이였다.

Master/Worker

다들 알다시피 쿠버네티스는 Master Node와 Work Node 로 구성된다. 대부분 Work Node 가 Master Node 보다 훨씬 많고 대부분의 서비스들이 여기에 배포되어진다.

Node 라는 단어를 빼버리고 단순히 Master/Worker 라고도 하지만 그냥 Master/Node 라고 하기도 하는 모양이다. 하지만 정확하게는 Master Node, Worker Node 라고 불린다.

또, Master Node 를 Controller 라고도 한다. Master 의 역활이 Worker Node 를 모니터링, 감시를 하고 각종 명령어을 Master 가 받아서 처리한다. 이 Master Node 는 거대한 Controller 서버 역할이라고 보면 된다.

kubectl – ResTful API

Master 가 거대한 Controller 서버라면 클라이언트를 이용해서 이 서버에 명령을 보내면 될 것이다. 이 클라이언트가 바로 kubectl 이라는 커맨드가 수행한다. 서버-클라이언트 구조상 서버는 1대지만 클라이언트는 여러대 일 수 있다. 실제로 kubectl 은 단일한 명령어로서 도커(Docker), 컨테이너(Container) 등도 필요없이 동작한다. 그래서 클라이언트는 어느 머신이든지 다 설치/사용이 가능하다.

kubectl 은 클라이언트, Master Node 는 Controller 서버다. 이 둘이 명령어를 주고 받는 방법이 바로 RESTFul API 통신 방법이다.

ResTful API 는 HTTP 를 이요해 URI 에 자원(Resources) 을 명시하고 메소드(Method) 를 이용해 CRUD 연산을 수행한다.

쿠버네티스(Kubernetes) 에서 중요한 것이 바로 자원이다. ResTful API 를 이용해 어떤 작업을 명령할때에 반드시 대상이 필요한데, 이것이 바로 자원이다.

Object, Resource, Kind

쿠버네티스(Kubernetes) 에서 개념을 설명할때에 오브젝트(Object) 라는 말을 쓴다. 오브젝트라고하면 쿠버네티스를 구성요소쯤으로 이해하면 된다. 예를들어 Pods, Service, Volume, Namespace 등은 쿠버네티스의 기본 오브젝트라고 불린다.

문제는 이러한 오브젝트들이 때로는 자원(Resource), 때로는 종류(Kind) 로 불린다.

자원 ResTful API 관점에서 실체적인 존재로서 호출하는 오브젝트들이다. 실제로 kubectl 커맨드를 사용할때에는 ‘오브젝트를 명시한다’ 하지 않고 ‘자원을 명시한다’라고 한다. ResTful API 개념을 차용했기 때문에 ‘자원을 명시한다’라고 해야 맞다.

위 결과를 보면 자원(Resource) 목록에서 오브젝트들도 볼 수 있다. 물론 오브젝트는 개념화된 추상적 그야말로 개념이고 자원을 실체적인 대상으로서 차이를 보이지만 이들에 명명된 말이 모두 같다. 맨 오른쪽에 KIND 도 보인다.

종류(Kind) 는 보통 Pods 를 생성하거나 업데이트를 하기위한 매니페스트(Manifest) 파일 작성시에 사용된다. 종류(Kind)는 쿠버네티스 자원 종류를 말한다. 매니페스트 파일은 JSON, YAML 포맷형태인데 예를들면 다음과 같다.

kind: Pod 라는 것이 보인다. 매니페스트 파일에서 자원이라고 하면 그야말로 컨테이너가 사용할 컴퓨터 하드웨어 자원을 말한다. 그래서 Resource:Pod 라고 한다면 문제가 되니까 Kind 라는 것으로 바꾼거 짐작이 된다.

이 kind 가 궁금하다면 ‘kubectl api-resources’ 명령어를 호출하면 자원에 붙여진 kind 를 볼 수 있다.

어느 방향으로 이해하느냐가 관건

쿠버네티스가 다루는 자원의 방향으로 접근해 이해하는 것도 괜찮다. 아니면 추상화 개념으로서 개념을 이해하고 가는것도 괜찮다.

다만, 완전히 추상적인 개념과 실제적인 대상을 구분하고 연결짓는 것이 머리속에 체계적으로 저장하는 방법이 될 수 있다.