Tagged: K8s

Ingress-Nginx 설치

Kubernetes 에서 인기있는 Ingress Controller 로 Nginx 가 있다. 설치는 Helm 을 이용하면 된다.

설치 명령어를 보면, 여러가지 파라메터가 보이는데 kube-prometheus-stack 으로 설치한 prometheus 까지 고려한 것이다.

관련 명령어나 파라메터는 다음의 주소에 매우 잘 설명되어 있어서 별도로 추가설명은 하지 않는다.

쿠버네티스 prometheus 설정

Helm 을 이용해 kube-prometheus-stack 을 설치하게 되면, Grafana 를 통해서 통계 그래프를 볼 수 있다. 그런데, 몇몇 대쉬보드는 나타나지 않는데 여기서는 이 문제를 해결하는 방법을 알아본다.

Prometheus

프로메테스에서 Status > Target health 에서 상태를 같이 보면서 해결하면 좋다. 어떻게 스크랩이 설정되어 있는데, 상태가 DOWN 인 부분을 잘 살펴보면 된다.

CoreDNS

CoreDNS 대쉬보드가 아무것도 나오지 않는다. Service 에 kube-dns 혹은 Helm 으로 설치할 경우에 coredns 로 나오는데, describe 를 한번 해본다.

위에 내용을 보면 k8s-app=coredns 가 보인다. 이제 Service 에 prometheus-coredns 를 한번 보자.

Selector 를 보면 k8s-app=kube-dns 로 보인다. 이것이 맞지 않아서 관련 내용을 가지고 오지 못하는 원인다. 이것을 k8s-app=coredns 로 바꿔 준다.

이렇게 하고 Prometheus 에 Status > Target health 에서 coredns 를 보면 스크랩이 잘되는 것으로 바뀐다.

Etcd

Prometheus 에서 Status > Target health 에서 ‘http://192.168.96.60:2381/metrics‘ 로 EndPoint 로 설정되어 있다. curl 로 긁어보면 다음과 같이 나온다.

Etcd 의 경우에는 상태 모니터링을 위한 파라메터 설정을 해줘야 한다. 하지만 kubeadm 으로 K8S 를 설치한 경우에 etcd 는 Master Controll Plane 으로 동작하기 때문에 파라메터 수정을 위해서는 manifest 파일을 수정으로 해야 한다.

2381 포트를 보면, 127.0.0.1 만 엔드포인트로 되어 있다. 192.168.96.60 을 추가해 준다. 그러면 정상화 된다.

Controller Manager

Prometheus 에서 Status > Target health 에서 ‘dial tcp 192.168.96.60:10257: connect: connection refused’ 에러 메시지가 나타난다.

Controller Manager 또한 Master Controller Plane 이기 때문에 manifest 파일을 수정해줘야 한다.

bind-address 주소가 localhost 로 되어 있기 때문에 refused 된 것으로 보인다. 0.0.0.0 으로 바꾼다.

kube-scheduler

kube-scheduler 도 위에 controller manager 처럼 bind-address 가 localhost 로 되어 있다. 0.0.0.0 으로 바꾼다.

kube-proxy

kube-proxy 는 DaemonSet 오브젝트다. 설정 파일이 있는 것처럼 나오지만 설정파일은 없고, 대신 ConfigMap 으로 존재한다. 이 ConfigMap 에 metricsBindAddress 값이 없다. 이 값을 0.0.0.0 으로 지정해 준다.

DaemonSet 은 자동으로 재시작되지 않는다. Rollout 업데이트를 해준다.

kube-prometheus-stack 설치

기존에 prometheus 설치를 했었는데, 버전을 올릴겸해서 다시 설치를 했다. 설치는 Helm 을 이용했고, 기존에 설치된 버전을 삭제 처리 했다.

환경

K8S 환경이 매우 중요하다. 필자의 환경은 Handy way 방법으로 설치를 진행한 상황이기 때문에 etcd, apiserver, scheduler 가 OS 데몬으로 운영되고 있다. 따라서 Master, Worker 노드의 IP 를 필요로 한다.

만일 kubeadm 으로 설치했다면 selector 를 이용해서 라벨을 선택해주면 된다.

삭제

Helm 을 이용해서 설치했기 때문에 Helm 으로 삭제를 해야 한다. 여기서 한가지 주의해야 하는 것이 있는데, Helm 으로 삭제를 하여도 CRD(Custom Resource Definition) 은 삭제되지 않기 때문에 수동으로 삭제를 해줘야 한다.

남아 있는 crd 가 다를 수가 있지만, 반드시 삭제를 해줘야 문제가 발생하지 않는다. crd 는 다른 프로그램에서도 삭제가 되지 않는 경우가 많다.

Helm repo update

Helm 저장소를 업데이트를 해야 한다.

Download a chart and untar

Helm Chart 를 다운로드하고 압축해제 한다. 이렇게 함으로써 values.yaml 파일을 수정할 수 있게된다.

다운로드와 함께 압축을 해제해 준다.

Values.yaml 파일 수정

어떤 내용들을 수정할지는 어떤 것을 모니터링 할지, 어떤 부분이 있는지에 따라서 달라진다. 변경된 내용은 대략 다음과 같다.

nodeSelector 에 system.rule: monitoring 이 보이는데, 이는 Worker 노드에 라벨을 말한다. 선택된 라벨을 가지고 있는 Worker 노드에 Prometheus 가 설치된다. 단, 이것도 상황에 따라서 달라지는데 Node exporter 의 경우에는 각 노드에 설치가 되어야 하기 때문에 라벨을 설정하지 않는다.

Node 라벨 생성

system.rule: monitoring 이라는 라벨을 생성해야 한다.

이렇게 하면 kworker3 에 prometheus 가 설치된다.

Dependency Update

Helm 을 이용해서 설치해야 한다. 그전에 kube-prometheus-stack 에 의존성이 있는 패키지를 업데이트 해줘야 한다.

설치

Helm 을 이용해 수정한 values.yaml 을 가지고 설치를 한다.

설치가 완료 되면 Pod, Service 에 Prometheus 가 올라오게 된다.

K8S dnstools 사용하기

K8S 를 사용하다보면 여러가지 검증을 위해 Pod 를 필요로 하는 경우가 있는데, dnstools 이 유용하다. 다음과 같이 사용할 수 있다.

Pod 가 생성되면서 dnstools 컨테이너에 진입하게 되고 exit 를 하게 되면 Pod 는 삭제된다.

혹은 curl 이미지를 이용하는 방법도 있다.

Metallb v0.14.9 설치

과거 Metallb 의 버전이 0.10 이였고 K8S 버전도 1.32 이여서 최신 버전으로 다시 설치를 해봤다.

환경

K8S 환경에서 설치를 하지만 CNI 등을 고려해 설치를 진행해야 한다. 내가 설치한 환경은 좀 더 특이한데, K8S 를 Hand Way 방법으로 설치한 상태다. Hand Way 로 설치를 하게 되면 Kube-apiserver, controller, kubelet, kube-scheduler, kube-proxy 같은 것을 컨테이너 방법이 아닌 OS 프로그램 방법으로 설치를 하게 된다. K8S 에서 사용하는 인증서도 수동으로 해줘야 한다.

요약하면 다음과 같다.

  • K8S 설치: Handy way
  • K8S Version: 1.32.2
  • Containerd: 1.7.26
  • CNI: Calico

다운로드

다운로드는 CURL 이나 WGET 명령어를 이용하면 된다.

설치 문서를 보면 이 manifest 파일로 설치가 가능하다고 하지만 여러가지 환경으로 인해서 추가로 파일을 작성해야할 필요도 있다.

metallb 설치

다운로드 받은 metallb-native.yaml 파일을 적용해 설치해 준다.

설치는 아무런 문제 없이 모두 잘 설치가 된다.

IPAddressPool 생성

Metallb 에서 사용할 고정IP 대역을 Pool 로 가지고 있어야 하는데, 이것을 생성해 줘야 한다.

위와 같은 addresses 를 할당해 준다. 필자는 집에서 K8S 를 구축했기 때문에 Private IP 대역을 할당해 줬다.

생성을 위해서 파일을 적용해 주면 위와같은 오류가 발생하게 된다.

이러한 오류는 validatingwebhookconfiguration 에 metallb-webhook-configuration 설정에서 문제가 된다. Webhook 이 필요한 것인데, 이에 대한 추가적인 설정을 해줘도 되지만 일단 삭제하는 것으로 처리 한다.

이렇게 한 후에 다시 metallb-ipaddress.yaml 파일을 적용하면 잘 된다.

L2 mode

필자의 경우에는 L2 mode 로 작동되도록 해야 한다. BGP 도 있기는 하지만, 필자의 경우에는 상관 없는 것이기 때문에 L2 mode 를 위해서 다음과 같이 manifest 파일을 작성한다.

metallb-L2Advertisement.yaml 파일을 적용한다.

LoadBalancer 타입 변경

이제 고정 IP 를 필요로 하는 Service 에 타입을 ClusterIP 에서 LoadBalancer 로 변경해 본다. Metallb 설치가 정상적이라면 다음과 같이 된다.

EXTERNAL-IP 에 Metallb 의 IPAddresses Pool 중에 하나의 IP가 할당된다.

그리고 describe 결과는 다음과 같다.

EndPoints 는 Nodes IP가 보이고 Port 도 할당된게 보인다. 이건 아마도 Hand Way 설치로 인한 것으로 보인다. 원래 kubeadm 으로 설치를 하게 될 경우에 Node IP 조차도 K8S IP 여야 하는데, 여기서는 Node IP 자체가 OS 자체에 할당된 IP로 나타난다.

kubeadm join 시 discovery-file 이용하기

새로운 Worker 노드를 추가하기 위한 문법은 대략 다음과 같다.

그런데, token 값은 시간이 지나면 만료되 사용할 수 없게 된다. 설사 token 을 알아도 ca-cert-hash 값을 알아야 한다. 이를 위해서 K8S 의 루트 CA 인증서를 이용해 hash 값을 알아내는 명령어를 사용한다.

Discovery-file 만들기

하지만 이 방법외에도 discovery-file 을 이용하는 방법도 있다. 이는 kube-public 네임스페이스에 ConfigMap 에서 cluster-info 의 정보를 가지고 오면 된다. 다음과 같다.

위 파일을 추가하고자 하는 새로운 Worker 노드에 복사해준다.

Discovery-file 을 이용한 새로운 Worker 노드 추가

이제 discovery-file 를 이용해 새로운 Worker 노드를 추가할 수 있다. 다음과 같다.

CSR Approved

이렇게 한 후에 csr 을 보면 pending 상태의 인증서들이 보인다. 이를 Approved 해주면 된다.

쿠버네티스, 새로운 Worker 노드 Join 시 토큰 값 확인하기

쿠버네티스(Kubernetes) 를 운영하다가 새로운 Worker 노드를 추가할때에 kubeadm 명령어와 함께 join 옵션을 함께 쓴다. 이때 token 값과 hash 값을 줘야 하는데, 최초 설치할때에 값을 출력해주지만 시간이 지나서 잃어버리면 어떻게 해야 할까..

Token 확인

불행하게도 Token 값은 영구적이지 않다. 어디다 잘 적어놨어도 시간이 지나면 자동으로 폐기되도록 되어 있다.

아무것도 안나온다. 이는 자동 폐기 됐기 때문이다.

Token 생성

Token 값을 확인할 수 없다면 새로운 worker 노드를 추가할 수 없다. 아니, 정확하게는 Token 값을 이용해 추가할 수 없다. Token 값을 이용하기 위해서는 새로운 Token 값을 만들어 주면 된다.

위와같이 새로운 토큰이 생성되었다. 만료일이 기재되어 있어 이 기간동안만 유효하다.

Kubernetes 관련 기술 스택..

쿠버네티스 관련된 기술들이 워낙 많다보니 뭘 어디서부터 손대야할지 모를때도 있고 하다보면 어디에 서 있는지도 모를때가 있다. 더 나가 쿠버네티스를 시작하려고할때에 이게 어디에 있는건지를 알고 싶을때가 종종 있는데, 웹 서핑을 하다가 주운걸 기록해본다.

딱봐도 채용공고에 내용인데, 굵직하게 정리가 되어서 긁어왔다. 여기서 한가지 추가해야 한다면 IaC 부분인데, 요새는 쿠버네티스에 뭔가를 설치할때는 다음과 같은 걸 많이 사용한다.

  • Helm
  • Operator

ArgoCD 도 있지만 이것은 사실 애플리케이션 배포에 쓰인다고 보면 된다.

요새 하도 공부를 하지 않아서 잃어버리는 기억도 많고 이제는 쓰지 않는 기술들도 많은데, 슬슬 다시 공부를해야 겠다고 다짐한다. 해야할게 얼마나 많은지… 덕분에 잘 심심하지 않게 살수 있다는 것에 위안을 받는다.

컨테이너에서 Java 힙 덤프 뜨기

Kubernetes 에서 Java 애플리케이션을 운영할때에, Java 힙 덤프를 떠야하는 경우가 있다. 하지만 다음과 같이 덤프를 떠지지 않는다.

“Unable to get pid of LinuxThread manager thread” 오류가 발생한다.

이 오류가 나오는 이유는 Java 애플리케이션의 Pid 값이 1이기 때문이다. 이를 해결하는 방법을 소개한다.

Container 이미지에 tini 설치, 배포

먼저 Openjdk 의 컨테이너 이미지에 tini 프로그램을 설치해야 한다. 이 tini 라는 프로그램은 인자값을 받은 프로그램을 실행 시켜 준다. 이렇게 하면 tini 는 Pid 1을 가지지만 tini 가 실행시킨 프로그램은 1보다 큰 Pid 값을 가지게 된다.

문제는 Openjdk 에 tini 라는 프로그램이 없다. 더군다나 아무 컨테이너 이미지에 이것을 설치할 수 있는게 아니라 Alpine 기반 이미지에서 쉽게 설치가 가능하다. Alpine 에서는 패키지로 제공하기 때문에 명령어로 간단하게 설치할 수 있다.

Dockerfile 을 다음과 같이 수정한다.

apk 명령어를 이용해 tini 를 설치해주고 ENTRYPOINT 에 실행 명령어에 tini 를 넣고 인자값으로 java 애플리케이션 명령어를 넣는다.

이렇게 컨테이너 이미지를 제작하고 배포를 한다.

tini 프로그램 이 후 Pid

tini 프로그램으로 Java 애플리케이션이 어떻게 실행되는 다음과 같이 확인 할 수 있다.

jcmd 뿐만 아니라 jstat, jmap 등 모든 명령어를 사용할 수 있다.