Kubernetes API 서버 인증서에 도메인 추가하기

Kubernetes API 서버는 http 를 통해서 쿠버네티스에 대한 연산을 제공해 준다. kubectl 명령어로 실행되는 것들은 모두 API 서버를 거쳐서 이루어진다. 하지만 API 서버는 인증서를 기반으로 통신이 이루어지는데, 이 인증서에 기재된 도메인이나 IP가 아니면 통신이 이루어지지 않는다.

API 서버의 인증서는 SAN 인증서여야 한다. 도메인 리스트를 가지고 있는 SAN 인증서. 현재 API 서버의 인증서 상태는 다음과 같다.

위 apiserver.crt 파일 상태를 보면 SAN 에 이미 도메인과 IP 들이 들어가 있다. 내용을 보면 haproxy2.systemv.local 도메인, 192.168.96.7 IP 가 들어가 있는데 이 서버에서 API 서버와 통신이 가능하다.

만일 추가적으로 도메인, IP 를 추가하고 싶다면 어떻게 해야할까? 이에 대해서 알아본다.

kubeadm-config 업데이트

kubeadm-config 라고 불리는 ConfigMap 을 업데이트 해줘야 한다. 이를 위해서 먼저 기존이 설정을 뽑아내야 하는데 다음과 같이 하면 된다.

파일 내용을 보면 SAN 리스트가 없다. 도메인이나 IP 를 SAN 으로 추가하기 위해서 apiServer 아래에 certSANs 를 추가해 준다. 이미 다른 도메인이 있다면 제거하나 추가할 수도 있다.

위와같이 SAN 에 추가할 도메인, IP를 적어준다.

apiserver.crt 파일 업데이트

기존의 존재하는 apiserver.crt 파일을 백업한다.

kubeadm 을 이용해 새로운 인증서를 생성해 준다.

새로운 인증서가 생성되면서 certSANs 에 설정된 도메인, IP 주소들이 모두 인증서에 업데이트 된다. 이제 새로운 인증서를 가지고 구동되도록 api 서버를 재시작 시켜줘야 한다.

Docker 기반의 경우에는 다음과 같이 하면 된다.

  • docker ps | grep kube-apiserver 명령어로 kube-apiserver 의 컨테이너 ID 를 파악한다.
  • docker kill <containerID> 로 컨테이너를 킬(kill) 한다. 이렇게 하면 api 서버가 재시작 된다.

만약 containerd 를 이용하는 경우에는 다음과 같이 하면 된다.

  • crictl pods | grep kube-apiserver 로 kube-apiserver 의 Pod ID 를 파악한다.
  • crictl stopp <pod-id> 로 pod 를 정지
  • crictl rmp <pod-id> 로 pod 를 제거 합니다. 이렇게하면 다시 Pod 가 재시작 된다.

위와같이 Api 서버가 재시작되면서 새롭게 만들어진 API 서버 인증서를 인식하게 된다.

클러스터 설정 업데이트

마지막으로 클러스터 설정을 업데이트 해줘야 한다.

이렇게 하면 최종적으로 Api 서버에 인증서가 업데이트 된다.

Kubernetes 의 Role Based Access Control(RBAC)

쿠버네티스는 RBAC 기반으로 허가권(Permission) 을 조정하도록 설계 되었다. 그런데, 쿠버네티스는 다음과 같이 네가지의 Role 관련 리소스를 가지고 있다. 그 차이는 다음과 같다.

  1. ClusterRole – 전체 클러스터에 적용하기 위한 역할(Role) 에 할당된 허가권(Permission)
  2. ClusterRoleBinding – 특정 계정(Account) 에 ClusterRole 을 바인딩
  3. Role – 특정 네임스페이스에 적용하기 위한 역할(Role) 에 할당된 허가권(Permission)
  4. RoleBinding – 특정 계정(Account) 에 Role 을 바인딩

RBAC 을 적용하기 위해서는 계정이 필요하다. 이 계정은 쿠버네티스의 사용자를 말하는것이 아닌 쿠버네티스에서 운영되는 자원에 대한 계정을 말한다.

예를들어 ingress-nginx 라는 계정을 생성했다면 이제 이 계정에 ClusterRole 과 Role 을 Binding 을 통해서 ingress-nginx 계정과 연결하는 형식이다.

참고: Role Based Access Control (RBAC)

Istio, Pod CrashLoopBackOff 해결하기

Istio 를 설치하고 Pod 를 생성했는데, 다음과 같이 오류가 발생했다.

istio-init 컨테이너가 오류가 발생한 것을 알 수 있다. Pod 안에 컨테이너가 여러개일 경우에 컨테이너 로그를 봐야하는데 다음과 같이 Pod 에 속한 컨테이너 로그를 볼수 있다.

이 문제는 istio cni 컴포넌트를 함께 설치해주면 된다. 보통 Istio 를 설치할때에 Profile 만 지정하는데, demo 프로파일에 경우에 CNI 를 설치하지 않는다. 다음과 같이 재설치를 해준다.

이렇게 CNI 를 활성화해서 재설치를 하면 문제없이 작동 된다.

문제점

여기서 한가지 문제가 있다. CNI 는 보통 Flannel, Calico 등을 이용하는데, 이것과 별도로 Istio-cni 를 설치하게 되는 것이다. 이왕이면 기존에 있는 것을 활용하는 방안을 고려해야 한다.

Calico 의 경우에 이에 대해서 기술하고 있는 문서가 있으니 참고해서 한번 해볼만 하다.

Istio 설치

Istio 는 쿠버네티스의 Network 레벨의 Mesh 서비스다. 비교하자면 Netflix OSS 에 Ribbon 과 비슷하다고 볼 수 있다.

Istio 설치 방법

Istio 설치 방법은 다양하다. 처음에 Istio 를 시작할때에 가장 헷깔리는 것이 바로 설치 방법이다. 구글에서 검색을 하면 설치방법이 나오지만 읽어보면 제각각인 이유가 다양한 설치 방법 때문이다.

그래서인지 Istio 홈페이지에서 다양한 설치 방법을 적어놨는데 대략 3가지 방법이 많이 쓰인다.

  1. Install with Istioctl
  2. Install with Helm
  3. Install Istio Operator

여기서는 Istoctl 을 이용해 설치하는 법을 다룬다. 이 방법은 다음 문서에 잘 나와 있다.

Download Istioctl

다음과 같이 Istio 를 다운로드 한다.

istio profile

istioctl 은 말그대로 istio 관련 작업을 위한 툴이다. 설치를 할때도 이를 활용할 수 있다.

istio 설치는 미리 정의되어 있는 프로파일을 정의하면 그 프로파일에 맞는 컴포넌트들을 같이 설치해 준다. 미리정의된 프로파일은 다음과 같이 조회가 가능하다.

프로파일의 내용은 대략 다음과 같다.

  • default: 프로덕트 환경에 적합하도록 기본세팅되어 있다.
  • demo: 쇼케이스를 위해서 세팅된 값을 쓴다.
  • minimal: 오진 컨트롤 플레인만 설치된다.
  • empty: 아무것도 디폴로이 되지 않는다. 이것은 커스텀 설정을 위한 베이스 프로파일처럼 사용할 수 있다.

각 프로파일의 내용은 다음과 같이 dump 옵션을 사용해 가능하다.

위 내용을 보면, cni, egressGateway 와 istiodRemote 가 비활성화 되어 있다.

전체설정의 서브셋만 보고 싶다면 –config-path 를 사용하면 가능하다.

프로파일에 차이를 알고 싶다면 다음과 같이 확인할 수 있다.

demo profile 설치

demo 프로파일을 이용해 설치를 진행 한다. istio 문서대로 한번 해보는 것이다.

자동으로 Envoy 사이드카 프록시를 자동으로 주입시키기 위한 네임스페이스에 라벨을 추가해준다.

default 네임스페이스에 라벨링을 해줬다. default 네임스페이스에 드플로이를 해주면 Envoy 사이드카가 자동으로 주입된다.

istio 설치 확인

먼저 네임스페이스를 확인해 보자. 네임스페이스는 istio-system 이 생성된다.

그리고 이제 어떤것이 설치되었는지를 살펴보자.

CRD 도 함께 생성된다. 다음과 같이 확인 가능하다.

문제

이벤트(Events) 를 보면 다음과 같이 오류가 난것을 확인할 수 있다.

쿠버네티스 curl 사용하기

쿠버네티스에서 클러스터내에서 Pod 에 데이터가 잘 나오는지를 확인하는 방법은 CURL 일 것이다. ClusterIP 로 IP 가 할당되면 클러스터내에서 접근이 가능한데 이때에 다음과 같이 사용하면 된다.

curl 을 비롯한 ping, nslookup 도 가능하다.

Calico Metrics 모니터링 하기

Calico 는 쿠버네티스(Kubernetes) 의 CNI 다. 쉽게 말해서 쿠버네티스의 네트워킹을 가능하게 해준다. 설치도 쉽게 할수 있는데, 프로메테우스에서 Calico 모니터링을 하기 위해서는 추가적인 작업이 필요한데 여기에 대해서 알아본다.

calicoctl

calicoctl 을 설치해야 한다. 이 파일은 바이너리이며 wget, curl 명령어를 이용해서 설치가 가능하다. 설치를 한 후에 이것을 사용하기 위해서는 다음과 같이 환경변수를 설정해 준다.

calicoctl 명령어는 다양한 질의를 할 수 있다.

Calico CRD

Calico 설치를 메니페스트로 설치를 하게 되면 CRD 가 생성되면서 CRD 에 정의된 오브젝트가 함께 생성된다.

이것을 언급하는 이유는 Calico 홈페이지에 보면 이에 대한 언급이 많이 되어 있지 않은채, API 를 언급하고 있다. 만일 API 조회를 해봤는데 없다면 CRD 를 살펴보고 찾으면 된다.

Monitor Calico component metrics

Felix configuration

이제 Calico 의 컴포넌트 메트릭을 활성화 해보자. 이를 위해서는 felixconfigurations 의 설정을 먼저 바꿔야 한다. 이를 위해서 calicoctl 명령어를 활용한다.

Creating a service to expose Felix metrics

이제 프로메테우스에서 메트릭 수집을 위한 서비스를 다음과 같이 만든다.

Felix 는 쿠버네티스 WorkerNode 에서 실행되는 CNI 를 말한다. 셀렉터를 보면 k8s-app: calico-node 를 설정하고 있는데, Calico Node 의 Pods 를 지정한 것이다.

또, 나중에 ServiceMonitor 설정을 위해서 Labels 를 잘 설정해줘야 한다.

Typha 설정은 하지 않는다. 50개 노드 이하로 설치를 했기 때문에 Typha 가 없다.

Confirm prometheus metrics port

쿠버네티스는 컨트롤 설정을 하나로 모아 놨다. 이 설정을 보면 여러가지 오브젝트에 대한 내용도 나오는데, 이 오브젝트에 대한 프로메테우스 엔드포인트는 9094로 정의 되어 있다. 이 포트를 이용하면 모든 메트릭의 엔드포이트를 가지고 올 수 있다.

Creating a service to expose kube-controllers metrics

앞에 Felix 는 Node 의 CNI 라고 한다면 이를 제어하는 것이 컨트롤러이다. 이를 위한 서비스를 다음과 같이 생성해 준다.

Calico-kube-controllers 의 Pods 를 찾기 위해서 셀렉터 k8s-app: calico-kube-controllers 지정해 준다. 그리고 ServiceMonitor 에서 찾을 수 있도록 Labels 를 설정해 줬다.

Prometheus ServiceMonitor 생성

나는 프로메테우스를 Operator 로 설치했다. Prometheus-Operator 설치를 할 경우에 메트릭 수집은 ServiceMonitor 를 통해서 이루어진다. 이 ServiceMonitor 는 Prometheus 의 설정을 함께 적용하면서 동작한다. Prometheus 의 Scape 을 ServiceMonitor 가 대신하는 것이라고 생각하면 쉽다.

Felix 를 위한 ServiceMonitor

Felix 를 위한 ServiceMonitor 는 다음과 같다.

셀렉터를 이용해서 Service 의 Felix 를 지정해줬고, 스크랩에서도 Felix 를 인식하도록 서비스 이름을 지정해 줬다.

Calico Kube Controller ServiceMonitor

Calico kube controller 를 위한 ServiceMonitor 는 다음과 같다.

위와같이 한 후에 프로메테우스를 살펴보면 다음과 같이 나온다.

쿠버네티스 secret 파일 저장하기

쿠버네티스의 Secret 은 암호화해서 데이터를 저장하는데, 파일도 저장할 수 있다. 바이너리 파일이던 텍스트 파일이던 모두 base64 인코딩 스트링으로 저장이된다. 이것을 파일로 저장하는 방법에 대해서 간단하게 알아본다.

Prometheus 설정 Secret

Pormetheus 를 오퍼레이터(Operator) 로 설치를 했을 경우에 다음과 같은 Secret 을 볼 수 있다.

data 필드를 보면 prometheus.yaml.gz 파일이름이 보이고 내용이 base64 스트링이 보인다. 이 prometheus.yaml.gz 파일을 받기 위해서는 간단히 bas64 스트링을 디코딩하고 나오는 스트링을 그냥 파일명으로 저장하면 된다.

간단하게 echo “<encoded-value>” | base64 -d prometheus.yaml.gz 으로 보면 된다.

압축을 해제하고 파일을 수정한 후에 다시 압축을 한다. 그리고 이것을 base64 로 인코딩 스트링을 만들면 되는데 다음과 같이 만들 수 있다.

이렇게 하게 되면 Base64 인코딩 스트링 나오는데, Secret 에 데이터부분에 이 스트링을 넣고 편집하면 된다.

curl 사용법

curl 사용법을 정리해 본다. curl 사용법을 정리하는 이유는 쿠버네티스(Kubernetes) 를 사용하면서 테스트를 위해서 많이 사용할 명령어이기 때문이다. 쿠버네티스에서 주로 사용하는 방법은 인증서를 지정해 인증을 받아 실행시키는 API 호출이다.

–cacert

TLS 연결을 위해 인증서 파일을 지정하는데 사용 한다. 이 파일은 다중 CA 인증서를 포함할 수 있다. 여기서 ‘다중 CA 인증서’ 는 인증서 체인(Certification Chain) 을 말한다. 인증서는 반드시 PEM 포맷이여야 한다.

–cert

TLS 연결을 위한 클라이언트 인증서 파일을 지정하는데 사용 한다. 인증서는 보안 전송(Secure Transport) 를 위해서는 PKCS#12 포맷을 다른 엔진을 위해서는 PEM 포맷을 사용이여야 한다. 이 옵션은 개인 키와 클라이언트 인증서가 연결된 인증서 파일로 가정 한다.

–key

개인 키 파일 이름

쿠버네티스 테스트

현재 쿠버네티스를 KVM 에 Hardway 로 설치를 했다. controller-manager, etcd, apiserver 등을 OS 프로세스등으로 작동한다. 이러다보니 이 서버에 연결을 위해서는 인증을 해야 하는데, 인증서가 필요한데 테스트를 다음과 같이 할 수 있다.

쿠버네티스의 경우에 인증을 위해서 대부분 인증서를 사용하는데, 위 명령어가 도움을 줄 수 있다.

대칭키, 비대칭키 개념

컴퓨터를 다룬다는 건 쉬운게 아니다. 컴퓨터 자체는 공학 개념이지만 그 컴퓨터에서 작동하는 수 많은 일들은 과학에 속한다. 이러한 컴퓨터 과학분야는 매우 다양해서 대충이라도 알고 있는 것과 모르는 것의 차이는 시간이 갈 수록 커질 수 밖에 없다.

그 대충이라도 알아야하는 것중에 하나가 암호화다. 컴퓨터 네트워크를 위해서 필요한 보안을 가능하게 해주는 암호화. 개인 정보의 중요성을 가져오지 않아도 과거부터 컴퓨터 네트워크에서 암호화는 필요 이상이였다.

암호화 방법에서 데이터를 암호화 하는 키가 어떤건지를 말하는 것으로 대칭키, 비대칭키라는 말이 있다. 오늘은 암호화의 기초, 용어에 대해서 알아본다.

대칭키(Symmetric Key)

대칭키는 영어로 Symmetric Key 라고 하는데, 직역 그 자체로 ‘대칭’ 이다. ‘대칭’ 이라는 용어의 사용은 동일한 형상이 상반된 위상에 존재하는 것을 말한다. 대칭은 자연상태에서 가장 많이 발견된다. 식물의 꽃의 경우 반으로 접었을때에 포개지는 것이 대표적이다. 자연이 가장 안전적인 상태가 대칭이라는 말이 있을 정도로 자연에서의 대칭은 흔하다.

암호화는 복호화도 포함한다. 어떤 평문을 암호화 했다면 반드시 해독이 가능하도록 평문으로 되돌릴 수 있어야 한다. 이를 복호화라고 하는데, 암호화 할때 사용하는 암호화 키와 복호화 할때 사용하는 복호화 키가 모두 동일한 경우를 대칭키 암호화라고 한다.

암호화 과정과 복호화 과정을 포개면 동일한 키가 딱 들어맞고 찾을 수 있다해서 대칭키라고 이름을 붙인 것으로 보인다. (이건 추정이다. 하지만 이름 하나는 딱 맞게 잘 지은 거 같다)

대칭키 암호화는 암호화, 복호화에 모두 동일한 키를 사용하기 때문에 복호화를 하는 사람도 결국 같은 키를 가지고 있어야 한다. 암호전문을 전송, 수신하는 양측 모두 같은 암호키를 가지고 있어야지만 암호화전문을 보내고 복호화해서 평문으로 내용을 확인할 수 있으니까..

암호화의 발전은 전쟁으로 인한 것이 였다. 1,2차 대전때에 전문통신을 암호화 해야할 필요가 있었는데, 이때 암호화를 위한 키 스트링을 사용했었다. 다시 복호화를 하기 위해서는 암호화 과정에서 사용했던 동일한 키 스트링을 이용해야만 했다. 대칭키 암호화를 활용한 것이다.

이러다보니 적군에게 스파이를 파견해 하는 일중에 최우선은 이 암호화 하는데 이용하는 키 스트링을 훔쳐오는 것이다. 그 키 스트링만 알면 적군의 암호전문통신을 중간에서 가로채서 해독할 수 있고 작전을 모두 알 수 있었기 때문이다.

이것은 결과적으로 대칭키 암호화에서 암호화 한 전문 보다는 암호화를 하는데 사용한 대칭키를 어떻게 보관하고 상대방에게 전달해야 하느냐 하는 문제로 이어진다.

컴퓨터 분야에서도 대칭키 암호화를 활용한적있다. 대표적으로 DES 암호화 알고리즘이 그것이다. DES 암호화 알고리즘은 IBM 이 만들어서 미국 NIST 에 제안해 채택되었다. 하지만 1998년에 대칭키를 몰라도 수학적으로 해독이 가능하다는 것이 증명됨에 따라 사용하지 않고 있다.

비대칭키(Asymmetric Key)

비대칭키 암호화는 암호화 하는데 사용하는 암호화 키와 복호화 하는데 사용하는 복호화 키가 다르다. 어떻게 암호화 키와 복호화 키가 다른데, 평문을 암호화도 되고 더군다나 그 암호화된 문장이 평문으로 복호화가 되나? 하겠지만, 매우 잘 된다.

비대칭키 암호화의 핵심은 복호화와 전달에 있다. 정확하게 말하면 암호화, 복호화 전체과정에서 가장 중요하게 보는 부분이 복호화일 뿐이다.

암호화를 하는 이유는 보안을 위한 것이다. 그 보안이라는 것은 타인이 내가 봐야하는 뭔가 은밀한 기밀을 들키지 않고 유지 하는 것을 말한다. 결국 그 은밀한 기밀은 나만 보아야 한다는 전제가 깔린 것이다.

비대칭키 암호화에서 가장 중요하게 보는 것은 복호화다. 암호화는 아무나 다 해도 된다. 하지만 그것을 볼 수 있는 사람은 오직 나 혼자여야 한다. 따라서 복호화를 위한 키는 나만 가지고 있으면 된다.

암호화를 하는 이유는 타인에게 정보를 전달하기 위한 것이다. 타인에게 정보를 전달도 하지 않을 거라면 나 혼자 아는 암호화 키로 암호화하고 보관하면 된다. 나만 알고 있는 키이기 때문에 다른 사람에게 유출될 일도 없다. 하지만 타인에게 정보를 전달하는 거라면 대칭키 암호화에서처럼 상대방도 내 암호화 키를 알고 있어야 하고 이 키를 전달하는데 많은 보안을 유지해야 한다.

하지만 암호화 된 전문을 나만 아는 키로 해독이 가능하면 대칭키 암호화 키 전달을 위한 추가적인 보안이 필요 없다.

비대칭키 암호화는 그 누구나 암호화를 할 수 있는 키가 존재하고 나만 복호화 할 수 있는 복호화 키, 이렇게 두가지로 존재한다. 이를 공개 키(Public Key), 개인 키(Private Key) 라고 부른다.

비대칭키 암호화를 사용하기 위해서 나는 공개 키와 개인 키 두개를 만든다. 그리고 공개 키를 세상에 그냥 뿌린다. 인터넷에 그냥 올려놔도 된다. 지구상에 모든 사람이 공개 키를 알아도 된다. 왜냐하면 공개 키로 암호화 한 전문은 오로지 나 혼자 가지고 있는 개인 키로만 평문으로 복호화가 가능하니까.

비대칭키 암호화에 대표는 RSA 이다. 론 리베스트(Ron Rivest), 아디 샤미르(Adi Shamir), 레오나르드 애들만(Leonard Adleman) 3명의 수학자의 앞 글자를 따서 지은 것이다.

이 3명의 수학자는 MIT 컴퓨터 사이언스 실험실 8층에서 함께 암호화 알고리즘 연구를 진행하던 중에 디피와 헬만이 발표한 비대칭키 암호화 알고리즘을 듣게 된다. 그리고 그들도 이 암호화 알고리즘 개발에 착수하는데, 1977년 4월에 론 리베스트가 수학 교과서를 읽다가 갑자기 아이디어가 떠올랐다고 한다. 그는 전광석화처럼 그날 밤에 논문을 작성하고 마쳤는데, 논문에 마지막에 자신을 포함한 연구실 사람 이름을 올렸다고 한다. 그래서 RSA 라고 부르게 되었다는 것.

SSH 키 접속

어느날 한번쯤은 ‘SSH 키 접속’ 이라는 것을 들어보거나 검색을 해봤을 것이다. SSH 는 서버에 접속을 위한 프로그램으로 SSH 서버에 접속을 위해서는 ID/Password 입력해 접속을 한다. 하지만 SSH 는 Key 방식으로 접속을 지원한다. 이때 SSH가 사용하는 Key 방식이 RSA 키 방식이다.

SSH 키 접속을 위해서는 암호화 키를 생성해야 하는데, 대충 다음과 같은 명령어로 생성이 된다.

두개의 파일이 생성되는데, id_rsa 는 개인키(Private Key) 이며 id_rsa.pub 는 공개키(Public Key) 다.

공개키를 접속하려고 하는 서버에 사용자 ID 홈디렉토리에 .ssh 디렉토리에 authorized_keys 파일로 전송한다. 그리고 접속할때에는 개인키를 이용해서 SSH 접속을 하면 된다.

도메인 인증서

RSA 암호화를 알아야 하는 이유는 SSH 뿐만 아니라 전자서명에도 사용하기 때문이다. 전자서명으로 대표적인 것이 도메인 인증서다.

HTTPS 를 위해서 반드시 필요한 인증서가 도메인 인증서인데, 이것이 RSA 암호화를 기반으로 한다. HTTPS 는 정확하게는 RSA 암호화와 대칭키 암호화를 혼합해 작동된다.