AWS ECS, Service 생성 오류 디버깅

AWS ECS 에서 Cluster 를 생성하고 난 후에 Service 를 생성해야 한다. AWS ECS 는 Cluster, Service 생성시에 CloudFormation 으로 생성하게 되는데, 문제는 오류가 발생했을때다.

“Circuit Breaker” 라고 되어 있어서 그냥 CloudFormation 이 실행하면서 예기치못한 오류가 발생한 것으로 착각할 수 있다. 하지만, 이것이 문제가 아닐 수도 있다.

Service 생성 Event 확인

CloudFormation 에서 “CREATE_FAILED” 라고 되어 있어도 AWS ECS 에 Service 에는 service 가 생성되어 있다. Service 를 클릭하고 들어가서 Events 탭을 클릭하면 생성이 진행되었던 과정을 볼 수 있다.

여기서 task 로 시작하는 해쉬값 링크를 볼 수 있다. 이것을 클릭하고 들어가본다.

이제 뭐가 문제인지를 확실하게 보인다. “pull image mainfest has bean retried 1 time(s)” 로 되어 있고 ECR 에서 이미지를 못가지고 오고 있음을 알 수 있다.

Harbor, Helm chart 사용하기

Harbor 도 Helm Chart Repository 를 제공한다. 한가지, Harbor 최신 버전에서는 chartmuseum 이 제거 되었다. 과거 버전에서는 chartmuseum 을 플러그인으로 설치해야 Helm Chart 저장소를 사용할 수 있었지만 최신 버전에서는 Helm Chart 저장소가 내장됐다.

변화는 또 있다. Helm Chart 저장소가 OCI 타입이라는 것이다. OCI 타입이면 helm 명령어를 이용하는 방법도 다르다. 먼저, helm repo add 와 같이 repo 관련 명령어는 사용할 수 없다. 또, helm pull 에서 oci:// 를 붙여줘야 한다.

대략 다음과 같이 사용해야 한다.

Gitlab, Helm 저장소 사용하기

Gitlab 은 아주 좋은 툴이다. 단순하게 git 저장소 뿐만 아니라 Container 저장소, Package 저장소를 제공한다. 여기서 Package 저장소가 Helm chart 저장소이다. 이 문서는 Gitlab 에서 Helm 저장소를 이용하는 방법에 대해서 다룬다.

Project

Gitlab 은 기본적으로 소스코드를 저장하기 위한 카테고리로 Project 를 만든다. 이렇게 하는 이유는 Gitlab 은 다양한 저장소 타입을 제공하기 때문에 딱히 Git 저장소 라고 불리기도 애매하기 때문이다. Gitlab 은 Git 명령어를 이용하지만 저장소는 Git, Container, Package, Terraform states, Terraform modules 등을 제공한다.

여기서 Helm 저장소를 Package Registry 로 부른다. 한가지 짚고 넘어가야하는 것은 Package Registry 는 소스코드를 저장하는 것이 아닌 Helm 의 Package 형태를 그대로 저장하는 것이다. Helm Package 라는 것이 Helm template 의 텍스트 파일을 압축한 형태의 결과물이고 이를 수정하기 위해서는 Helm chart 의 소스코드 형태로 가지고 있어야 한다.

Gitlab 은 텍스트 형태의 Git 저장소, Package Registry 를 하나의 프로젝트에서 관리할 수 있기 때문에 Helm Chart 를 위한 저장소 두개를 한꺼번에 운영할 수 있게 된다.

helm-employee-role 프로젝트

예를들어 설명하겠다. Gitlab 에서 helm-employee-role 이라는 프로젝트를 생성한다. 그리고 helm chart template 을 Git 코드 저장소에 저장을 한다. 이렇게 되면 다음과 같이 보인다.

Code Repository 에는 Helm Chart 의 텍스트를 저장하게 된다. 이것은 Helm Chart 의 소스코드라고 부르는 형태로 Package Registry 와는 다른 것이다.

이제 Package Registry 를 사용해 보자.

Personal Access Token

Gitlab 에는 Access Token 이 존재한다. 이는 Personal, Project, CI/CD Access Token 으로 세가지 형태가 있다. 각 Access Token 은 용도에 맞게 사용하게 되는데, 아무래도 Personal Access Token 이 권한 제약이 많다. 꼭 필요한 권한만을 가지고 있는 것이고, 보안상 최소한의 권한만을 부여한다는 방침을 따른다면 Personal Access Token 이 제일 적합하다.

Gitlab 에 로그인하고 ‘User settings -> Access Tokens’ 에서 토큰을 발행할 수 있다. 이때 스코프(Scope) 라고해서 Token 의 권한을 부여해야하는데, api 만 체크해주면 된다.

Publish a package

Gitlab 공식문서에는 Package Registry 에 Helm 을 올리는 것을 Publish 라고 표현하고 있다. 다음과 같은 방법으로 publish 한다.

결과가 성공적으로 생성이되었음을 알려주고 있다. 실제로 잘 되었는지를 Gitlab 웹 화면을 통해서 보면 다음과 같다.

위와 같이 나온다. 클릭해서 들어가면 다음과 같이 보인다.

아직 처음이라 별 내용은 보이지 않는다. 한가지, 저장되는 형태가 helm package 형태라는 것.

Gitlab 에 Helm 저장소 사용하기

Gitlab 의 Package Registry 에 Publish 가 되었으니 이제, 이것을 Helm 에서 사용해 봐야 한다.

위와같이 helm 을 사용할때에 Gitlab 저장소를 이용할 수 있다.

여기서 한가지 더, Gitlab 의 Package Registry 는 OCI 타입의 저장소가 아니다. 최근의 Harbor 의 경우, Helm Chart 저장소는 OCI 타입을 지원한다. OCI 타입을 Helm 에서 사용할 경우에 helm repo 명령어를 사용하지 않는다.

민트 리눅스에 KVM 가상환경 구성하기

민트 리눅스 21.03 에서 KVM 가상환경을 구성해 본다. 구성에 핵심은 KVM 의 네트워크 설정이다. 앞서 설정한 OpenvSwitch 를 이용하도록 설정 해야 한다.

네트워크 환경

KVM 가상화를 위해서는 네트워크 환경을 먼저 고려해야 한다. 필자의 경우에는 공유기를 이용하고 있다. 외부 광랜으로 들어온 라인을 모뎀에서 받아서 이더넷로 변환해준다. 여기서 랜선으로 공유기에 연결하고 각 컴퓨터에 연결해서 쓴다.

공유기는 다들 아는 IpTime 인데, IpTime 은 새로운 장비가 접속되면 자동으로 사설IP 를 할당해 준다. 이것을 외부로 내보낼때는 NAT 기능을 이용해서 하나의 인터넷 라인으로 공유기 안쪽에 많은 장비를 사용할 수 있게된다.

KVM 가상화를 하게되면 브릿지 네트워크가 생성된다. 이 브릿지 네트워크는 NAT 모드로 작동된다. 172.x.x.x 대역으로 게스트에게 자동으로 IP 를 할당해 준다. 마치 IpTime 공유기와 같은데, 문제는 이렇게 되면 다른 컴퓨터에서 게스트에 접속할 수가 없게 된다. NAT 는 단반향으로 게시트에서 바깥으로 접속은 할 수 있지만 바깥에서 게스트로 접속은 불가능하다. 가능한 방법은 Port 포워딩인데, 포트마다 설정을 해줘야 하는 번거로움이 있다.

KVM 네트워크 설정을 NAT 가 아닌 브릿지(Bridge) 모드로 설정하고 드라이버를 OpenvSwitch 로 설정하면 호스트 컴퓨터에 브릿지 네트워크인 OpenvSwitch 를 통해서 IpTime 에서 사설 IP를 받게 된다. IpTime 내에 네트워크 모두 접속이 가능해 진다.

KVM 을 위한 패키지 설치

다음과 같이 패키지를 설치해 준다.

KVM 를 위한 브릿지 네트워크 설정

주의해야 할 것은 OpenvSwitch 를 사용하도록 설정을 해야 한다. 민트 리눅스 21.03 은 특이하게도 KVM 설치해도 네트워크 설정이 없다. 다음과 같이 확인이 가능하다.

네트워크를 정의하기 위해서 다음과 같이 xml 파일을 작성해 준다.

forward 모드를 ‘bridge’ 이고 virtualport 의 타입이 openvswitch 여야 한다. 파일이 작성되었다면 이제 이것을 KVM 네트워크로 정의해 줘야 한다.

이로써 KVM 구성이 완료 됐다. 이제 virt-manager 를 이용해서 잘 게스트 OS 를 설치해 본다.

일반 계정으로 KVM 이용하기

KVM 설치하게 되면 root 계정으로만 사용할 수 있도록 되었다. 일반계정으로 사용하기 위해서는 다음과 같이 libvirt 그룹에 일반 계정을 추가해주면 된다.

이제 libvritd 의 설정 파일을 다음과 같이 변경한다.

설정을 변경했기 때문에 다음과 같이 재시작해 준다.

민트 리눅스에서 OpenvSwitch 설정하기

민트 리눅스(Mint Linux) 21.03 을 쓰고 있는데, 네트워킹이 NetworkManager 으로 되어 있다. Ubuntu 22.04 LTS 에서는 networkd 였지만 민트 리눅스는 같은 Ubuntu 라고 하더라도 네트워킹 운영을 NetworkManager 가 담당하고 있다.

이 문서는 민트 리눅스에서 OpenvSwitch 설정에 대한 것이다. Ubuntu 와 다른 네트워킹을 사용하기 때문에 nmcli 명령어를 이용한 방법을 소개 한다.

민트 리눅스 네트워킹 설정

이렇게 NetworkManager 일 경우에는 네트워크 인터페이스 관련 설정을 nmcli 로 하게된다. 물론 민트 리눅스 이기 때문에 GUI 를 통해서 손쉽게 할 수 있다.

GUI 툴을 이용해서 이렇게 설정을 하게 되면, nmcli 명령어를 사용해서 하는 것과 동일하게 nmcli 관련 설정파일이 변경 된다. 다음과 같은 경로에 파일이 존재한다.

GUI 툴을 이용해 설정한 내용이 위 파일에 적용된다.

OpenvSwitch 설치

OpenvSwitch 를 설치를 먼저 해야 한다. Ubuntu 를 사용하고 NetworkManager 일 경우에 OpenvSwitch 도 NetworkManager 와 연관된 패키지를 설치하는 경우가 많지만 민트 리눅스에는 다음과 같은 패키지를 설치 한다.

systemd 에 설정이 되었고 시작도 되었다. 다음과 같이 명령어가 문제없이 출력되는 확인한다.

위와같이 정상적으로 버전이 출력되어야 한다.

network-manager 패키지 문제

민트 리눅스 21.03 에서는 network-manager 패키지에 문제가 있다. OpenvSwitch 플러그인이 비활성화된 패키지라는 거다. 다음과 같다.

ovs 를 활성화하기 위해서는 network-manager 를 재패키징 해야 한다. 이를 위해서는 소스 deb 를 다운로드 받아야 한다.

이렇게하면 디렉토로에 network-manager 관련 패키징을 위한 파일과 디렉토리가 생성된다. 여기서 다름과 같이 deb 패키징을 위한 configure 파일이라 할 수 있는 rules 파일을 수정해 줘야 한다.

rules 파일을 열면 configure 설정을 볼 수 있다. 여기서 –disable-ovs 를 삭제한다. 이렇게 되면 ovs 를 위한 설정파일이 생성되고 이 파일에 대한 처리가 없으면 deb 패키징이 실패한다. 설치를 위한 파일 목록은 network-manager.install 파일이다. 여기서 다음을 추가해 준다.

lib/systemd/system/NetworkManager.service.d/NetworkManager-ovs.conf

이제 deb 패키지를 만들어야 하는데, network-manager 의 의존성 라이브러리를 설치해 줘야 한다.

그리고 debuild 명령어로 패키징을 제작해야 한다.

위와같이 하면 deb 패키지가 만들어진다. deb 패키지는 network-manager-1.36.6 디렉토리 밖에 만들어 진다.

이제 다음과 같이 재설치를 해준다.

nmcli 명령어를 이용한 openvswitch 설정

이제 nmcli 명령어를 이용해서 openvswitch 설정을 다음과 같이 한다. IP는 각자 자신의 네트워크 설정으로 바꾸면 된다. 먼저 명령어로 device 상태를 봐본다.

‘유선 연결 1’ 을 connection name 이라고 하는데, 한글이라 앞으로 설정하는데 문제가 될 수 있다. 이것을 DEVICE와 동일하게 설정해준다. 이것은 앞서 GUI 툴을 이용해서 변경해서 적용하면 간단하게 바꿀 수 있다. 변경이 되면 다음과 같다.

이제 nmcli 명령어를 다음과 같이 입력해준다.

IP 와 gateway 그리고 DNS 를 자신에 맞게 고쳐준다. 위와 같이하고 ovs-vsctl show 명령어로 제대로 되었는지 확인한다.

그리고 ip a 명령어로 제대로 ip가 세팅되었는지 확인한다.

잘되어 보인다. 이제 nmcli 명령어를 이용해 enp5s0 connection 을 삭제한다.

최종적인 모습은 다음과 같다.

이제 재부팅을 한 후에 네트워크가 잘된다면 끝난다.

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 값을 만들어 주면 된다.

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

AWS CloudFront 인증서는 ACM eu-east-1 에서 해야 한다

AWS CloudFront 인증서는 ACM eu-east-1 (N. Virginia) 에서 발급 받아야 한다. 왜냐하면 CloudFront 때문인데, CloudFront 의 메인 리즌이 eu-east-1 로 되어 있어서 다른 리즌에 발급받은 인증서는 CloudFront 에서 사용할 수 없게 된다.

Q: 어느 리전에서 ACM을 사용할 수 있나요?

AWS 서비스를 사용할 수 있는 현재 리전을 확인하려면 AWS 글로벌 인프라 페이지를 참조하세요. Amazon CloudFront에서 ACM 인증서를 사용하려면 미국 동부(버지니아 북부) 리전에서 ACM 인증서를 요청하거나 가져와야 합니다. CloudFront 배포와 연동되어 있는 이 리전의 ACM 인증서는 해당 배포에 대해 구성된 모든 지리적 위치에 배포됩니다.

Windows, x509: certificate signed by unknown authority 오류 해결

윈도우즈(Windows) 에서 개발을 할때에 사설 인증서를 사용한 서버에 접속하게 되면 제목과 같이 인증서 오류가 발생한다. 사설 인증서를 사용한 서버에 인증을 위해서는 Root CA 인증서를 내장하고 있어야 한다. Root CA 인증서는 공개키를 가지고 있고 이를 사용해서 서버에 사설 인증서에 내장된 해쉬값과 인증서명을 해독한다.

인증서 추가

윈도우즈(Windows) 도 이제는 인증서를 시스템에서 다룬다. 과거에는 브라우져에서 다루었지만 이제는 시스템에서 통합해 다루도록 변경되었다.

인증서를 추가하는 방법은 다양하지만, certutil.exe 커맨드 라인을 사용하는게 쉽다. certutils.exe 는 인증서 추가는 물론 파일의 해쉬값도 구할 수 있는 기능도 있다.

다양한 인증서 추가

certutil.exe 를 이용하면 다양한 인증서를 추가할 수 있다. 여기서 다양한 인증서는 Root CA 인증서, Intermediate 인증서, Server 인증서를 말한다. 이것을 구분해서 certutil.exe 를 사용해야 한다.

Root CA 인증서 추가

다음과 같이 Root CA 인증서를 추가 할 수 있다.

Root CA 인증서는 각 브라우져에 탑재되어 있는 것으로 공개키가 내장되어 있다. 모든 인증서는 Root 인증기관에서 암호화를 하는데, 인증기관에서 인증된 모든 인증서는 인증기관의 Root CA 인증서로 해독이 가능해 진다.

사설 인증서 관련해서 x509: certificate signed by unknown authority 오류가 발생하는 것은 사설 인증서를 받아서 해독을 할 수 없는 경우임으로 Root CA 인증서를 가지고 있으면 해독이 가능해진다. 따라서 제목의 문제 해결은 Root CA 인증서를 추가하면 된다.

혹은 클라이언트 인증서를 활용해도 문제는 해결되지만, 시스템에 설치되는 인증서는 Root CA 인증서임으로 클리이언트 인증서는 특정 애플리케이션에서 활용된다.

인터미데이트 인증서 추가

인터미데이트 인증서는 루트 인증기관에서 인증한 중간의 인증기관에 배포되어 인증이된 인증서를 말한다. 인증서는 3단계 인증서가 존재하는데, 루트 인증기관의 루트 인증서, 중간자 인증기관의 인터미데이트 인증서, 최종적으로 사용자 인증서다.

루트 인증기관의 인증서는 인터미데이트, 사용자 인증서 모두를 해독할 수 있다. 인터미데이터 인증서가 만들어진 이유는 중간에 카테고리를 하나 더 둠으로 인해서 인증서 유출에 따른 파급력을 줄이려는 의도다. 모든 사용자 인증서를 루트 인증기관으로부터 인증을 받은 상태에서 루트 인증서가 유출되면 그 파급력은 매우 크게 된다. 이를 쪼개기 위한 방안으로 인터미데이트 인증서가 필요해졌다.

재미있는 것은 인터미데이트 인증서는 보통 Root CA, Server 인증서를 모두 가지고 있다. 파일을 열어보면 인증서가 3개가 담겨 있는 경우가 대부분이다.

사용자 인증서 추가

윈도우즈 메뉴얼에는 사용자 인증서라고 되어 있는데, 이게 클라이언트 인증서인지 서버 인증서인지는 모르겠다. 추가하는 방법은 다음과 같다.

로컬 머신 인증서 관리 코솔(Certificate Local Machine)

로컬 머신 인증서 관리 콘솔이 있다. certlm.msc 명령어를 이용하면 되는데, 관리자 권한을 요구한다. 이는 시스템 와이드 적용이 되는 것으로 전체 사용자에게 영향을 준다.

Root CA 인증서를 추가된 것을 확인해 볼 수 있다.

사용자 인증서 콘솔(Certificate Manager)

사용자 인증서 관리 콘솔이 있다. 이는 아마도 개인 계정 범위내에서 사용되는 것을 보인다. certmgr.msc 로 실행해 확인해 볼 수 있다.

인증서 삭제

인증서 삭제는 관리 콘솔에서 가능하다.