Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 
(연관된 글이 1개 있습니다.)
(시리즈 글이 3개 있습니다.)
개발 환경 구성: 561. kubectl 수행 시 다른 k8s 클러스터로 접속하는 방법
; https://www.sysnet.pe.kr/2/0/12583

개발 환경 구성: 562. kubeconfig 파일 없이 kubectl 옵션만으로 실행하는 방법
; https://www.sysnet.pe.kr/2/0/12584

개발 환경 구성: 563. 기본 생성된 kubeconfig 파일의 내용을 새롭게 생성한 인증서로 구성하는 방법
; https://www.sysnet.pe.kr/2/0/12585




기본 생성된 kubeconfig 파일의 내용을 새롭게 생성한 인증서로 구성하는 방법

지난 글에서,

kubectl 수행 시 다른 k8s 클러스터로 접속하는 방법
; https://www.sysnet.pe.kr/2/0/12583

결국 중요한 것은 config 파일만 있으면 해당 config과 연관된 k8s 클러스터를 자유롭게 접근하는 것이 가능하다는 것을 알았습니다. 그렇다는 것은, config 파일을 다른 곳으로 복사해야 한다는 것을 의미합니다.

혹시 새롭게 인증서를 생성해서 주는 방법은 없을까요? 아래의 글을 읽어봤다면,

openssl - CA로부터 인증받은 새로운 인증서를 생성하는 방법
; https://www.sysnet.pe.kr/2/0/12570

이것이 가능하다는 것을 알 수 있을 것입니다. 즉, 새롭게 client 측에서 사용할 개인키를 생성하고 인증서 요청 파일(csr)을 만든 다음 CA 서버의 개인키와 인증서로 서명을 하면 되는 것입니다.

실제로 한 번 해볼까요? ^^




자, 그럼 먼저 개인키를 하나 생성해 보겠습니다.

C:\temp\pki\cluster2> openssl genrsa -out client-side.key 2048
Generating RSA private key, 2048 bit long modulus (2 primes)
............+++++
.+++++
e is 65537 (0x010001)

k8s가 요구하는 인증서 규약에 따라,

PKI certificates and requirements
; https://kubernetes.io/docs/setup/best-practices/certificates/

다음의 cnf 파일을 만들고,

FQDN = testusr
ORGNAME = system:masters

[ req ]
default_bits = 2048
prompt = no
default_md = sha256
req_extensions = req_ext
distinguished_name = dn

[ dn ]
CN = $FQDN
O = $ORGNAME

[ req_ext ]
subjectAltName = @alt_names

[ alt_names ]
DNS.1 = kubernetes
DNS.2 = kubernetes.default
DNS.3 = kubernetes.default.svc
DNS.4 = kubernetes.default.svc.cluster
DNS.5 = kubernetes.default.svc.cluster.local
IP.1 = 127.0.0.1

[ v3_ext ]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=keyEncipherment,dataEncipherment
extendedKeyUsage=serverAuth,clientAuth
subjectAltName=@alt_names

CSR 파일을 생성합니다.

C:\temp\pki\cluster2> openssl req -new -key client-side.key -out client.csr -config client.cnf

이렇게 생성한 csr 파일을 이제 CA 인증서로 서명을 하면 되는데요, 이를 위해 필요한 파일이 CA 인증서와 개인키입니다. 이 파일들을 구하는 방법은 해당 k8s 클러스터와 관계된 pki 디렉터리를 찾아야 합니다. 이에 대해서는 이미 다음의 글에서 설명했는데요,

Docker Desktop for Windows 기반의 Kubernetes 구성 (2) - WSL 2 인스턴스에 kind가 구성한 k8s 서비스 위치
; https://www.sysnet.pe.kr/2/0/12578#cert_path

여기서는 k8s를 kind로 구성한 경우를 예로 들겠습니다. 이를 위해 해당 k8s를 호스팅하는 컨테이너를 알아내고,

C:\temp\pki\cluster2> docker ps
CONTAINER ID   IMAGE                  COMMAND                  CREATED        STATUS        PORTS                       NAMES
62cd9120f957   kindest/node:v1.20.2   "/usr/local/bin/entr…"   3 days ago     Up 3 days     127.0.0.1:20971->6443/tcp   cluster2-control-plane

그 컨테이너 내에 위치한 /etc/kubernetes/pki 디렉터리의 파일들을 로컬로 복사해 온 다음 (또는, 정확하게 ca.crt, ca.key 파일만 복사),

C:\temp\test> docker cp 62cd9120f957:/etc/kubernetes/pki .

로컬에 복사된 ca.crt, ca.key 파일을 사용해 다음과 같이 클라이언트 인증서의 요청 파일을 서명해 줍니다.

C:\temp\pki\cluster2> openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 10000 -extensions v3_ext -extfile client.cnf
Signature ok
subject=CN = testusr, O = system:masters
Getting CA Private Key

이렇게 해서 새로 생성된 client.crt 파일과 client-side.key, ca.crt 파일만 있으면 이제 다음과 같이 kubectl을 사용할 수 있습니다.

C:\temp\pki\cluster2> kubectl get nodes --server https://127.0.0.1:20971 --client-certificate client.crt --client-key client-side.key --certificate-authority ca.crt
NAME                     STATUS   ROLES                  AGE    VERSION
cluster2-control-plane   Ready    control-plane,master   3d7h   v1.20.2




자, 그럼 절차가 정해졌군요. 만약 다른 사람이 여러분들의 k8s 클러스터에 접근하고 싶다면 간단하게는 여러분들이 사용하는 config 파일을 전달하면 됩니다. 혹은, 상대방에게 CSR 파일을 달라고 해 그것을 자신이 운영하고 있는 k8s 클러스터의 ca.crt, ca.key 파일로 csr 파일을 서명 후 생성된 crt 파일과 ca.crt 파일을 함께 전달해 주면 됩니다.

그럼 상대 측은 전달받은 client.crt, ca.crt 파일과 함께 자신이 가지고 있는 client-side.key 파일을 이용해 kubectl 명령어를 실행할 수 있게 됩니다. (사실, 이것은 SSL 인증서나 소프트웨어 인증서를 취득하는 과정과 정확히 일치합니다.)

물론, 명령행에 일일이 "--client-certificate client.crt --client-key client-side.key --certificate-authority ca.crt" 옵션을 넣는 것은 귀찮으므로 지난 글에서 설명한 방법을 이용해,

kubectl config --kubeconfig=config-demo set-cluster kind-cluster3 --server=https://127.0.0.1:20971 --certificate-authority="ca.crt"
kubectl config --kubeconfig=config-demo set-credentials kind-cluster3 --client-certificate="client.crt" --client-key="client-side.key"
kubectl config --kubeconfig=config-demo set-context kind-cluster3 --cluster=kind-cluster3 --user=kind-cluster3
kubectl config --kubeconfig=config-demo use-context kind-cluster3

kubeconfig 파일을 생성해 두는 것도 좋을 것입니다.

apiVersion: v1
clusters:
- cluster:
    certificate-authority: ca.crt
    server: https://127.0.0.1:20971
  name: kind-cluster3
contexts:
- context:
    cluster: kind-cluster3
    user: kind-cluster3
  name: kind-cluster3
current-context: kind-cluster3
kind: Config
preferences: {}
users:
- name: kind-cluster3
  user:
    client-certificate: client.crt
    client-key: client-side.key

그런데 위와 같이 설정해 두면 ca.crt, client.crt, client-side.key 파일을 함께 들고 다녀야 하므로 불편하니, 각각의 파일 내용을 base64 인코딩 시켜 kubeconfig 파일 내에 합치는 것이 좋습니다.

이를 위해 ca.crt를 certificate-authority-data로, client.crt를 client-certificate-data로, client-side.key를 client-key-data로 각각 값을 설정하면 됩니다. (base64 명령어는 윈도우의 경우 없으므로 별도로 다운로드해야 합니다.)

C:\temp\pki\cluster2> base64 -w 0 ca.crt | clip
// clipboard에 복사되었으므로 config-demo 파일의 certificate-authority-data로 복사

C:\temp\pki\cluster2> base64 -w 0 client.crt | clip
// clipboard에 복사되었으므로 config-demo 파일의 client-certificate-data로 복사

C:\temp\pki\cluster2> base64 -w 0 client-side.key | clip
// clipboard에 복사되었으므로 config-demo 파일의 client-key-data로 복사

그럼 config-demo의 최종 파일 구성이 다음과 같이 될 것이고,

apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS...[생략]...LS0tCg==
    server: https://127.0.0.1:20971
  name: kind-cluster3
contexts:
- context:
    cluster: kind-cluster3
    user: kind-cluster3
  name: kind-cluster3
current-context: kind-cluster3
kind: Config
preferences: {}
users:
- name: kind-cluster3
  user:
    client-certificate-data: LS0tLS1CRU...[생략]...tCg==
    client-key-data: LS0tLS1CR...[생략]...S0tCg==

이제 별다른 부가 파일 필요 없이 config-demo 파일 하나로 kubectl 명령어를 수행할 수 있습니다.

C:\temp\pki\cluster2> kubectl cluster-info --kubeconfig=config-demo
Kubernetes master is running at https://127.0.0.1:20971
KubeDNS is running at https://127.0.0.1:20971/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy





지난 글에서 configmaps에 CA 인증서를 담고 있는 것을 설명했는데요,

kubeconfig 파일 없이 kubectl 옵션만으로 실행하는 방법
; https://www.sysnet.pe.kr/2/0/12584#configmaps

C:\temp\wsl2> kubectl get configmaps
NAME               DATA   AGE
kube-root-ca.crt   1      11h

그렇다면 혹시 또 다른 CA 인증서를 등록하는 것도 가능할까요? ^^ 일단 다음과 같은 식으로 명령을 내리면,

C:\temp\wsl2> kubectl create configmap test-ca.crt --from-file=C:\temp\wsl2\ca.crt
configmap/test-ca.crt created

C:\temp\wsl2> kubectl get configmaps
NAME               DATA   AGE
kube-root-ca.crt   1      27h
test-ca.crt        1      6s

test-ca.crt는 kube-root-ca.crt와 동일한 양식으로 등록은 됩니다.

C:\temp\wsl2> kubectl describe configmaps test-ca.crt
Name:         test-ca.crt
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
ca.crt:
----
-----BEGIN CERTIFICATE-----
MIIDCTCCAfGgAwIBAgIUc57N5ZHozrDio2hBQlOLB2iCfs4wDQYJKoZIhvcNAQEL
...[생략]...
q1gObmghvUdhkdx1u8iNtKTua3czzwpzuOhsp7H0GFVh5jlK+RoD0rrlHEubIt4L
Zij0Yk2SrgxO3GvA1Q==
-----END CERTIFICATE-----

Events:  <none>

동작 여부는, 나중에 시간 나면 확인해 보겠습니다. ^^




참고로 openssl의 cnf 파일에 있는 FQDN은 임의의 값을 넣어도 되지만, 이 외의 값들(예를 들어, ORGNAME)은 가능한 규격을 지켜야 합니다. 만약 (ORGNAME으로 인한) O = system:masters 설정이 없으면,

FQDN = testusr

[ req ]
default_bits = 2048
prompt = no
default_md = sha256
req_extensions = req_ext
distinguished_name = dn
...[생략]...

kubectl 실행 시 다음과 같은 오류가 발생합니다.

C:\temp\pki\cluster2> kubectl get nodes --server https://127.0.0.1:20971 --client-certificate client.crt --client-key client-side.key --certificate-authority ca.crt
Error from server (Forbidden): nodes is forbidden: User "testusr" cannot list resource "nodes" in API group "" at the cluster scope




"kubectl create configmap... " 명령어 수행 시 다음과 같은 오류가 발생한다면?

C:\temp\wsl2> kubectl create configmap test_ca.crt --from-file=C:\temp\wsl2\ca.crt
The ConfigMap "test_ca.crt" is invalid: metadata.name: Invalid value: "test_ca.crt": a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')

오류 메시지에 볼 수 있는 것처럼, configmap의 이름으로 지정할 수 있는 값에 밑줄(underscore, _)은 유효하지 않은 문자이므로, '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*' 정규 표현식을 만족하는 범위 내의 문자로 이름을 지어야 합니다.




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 4/5/2021]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




... 76  77  78  79  80  81  82  83  84  85  86  87  88  89  [90]  ...
NoWriterDateCnt.TitleFile(s)
11684정성태9/6/201821100개발 환경 구성: 396. pagefile.sys를 비활성화시켰는데도 working set 메모리가 줄어드는 이유파일 다운로드1
11683정성태9/5/201818720개발 환경 구성: 395. Azure Web App의 이벤트 로그를 확인하는 방법
11682정성태9/5/201817666오류 유형: 484. Fakes를 포함한 단위 테스트 프로젝트를 빌드 시 CS1729 관련 오류 발생
11681정성태9/5/201820372Windows: 149. 다른 컴퓨터의 윈도우 이벤트 로그를 구독하는 방법 [2]
11680정성태9/2/201822542Graphics: 21. shader - _Time 내장 변수를 이용한 UV 변동 효과파일 다운로드1
11679정성태8/30/201820534.NET Framework: 792. C# COM 서버가 제공하는 COM 이벤트를 C++에서 받는 방법 [1]파일 다운로드1
11678정성태8/29/201818969오류 유형: 483. 닷넷 - System.InvalidProgramException [1]
11677정성태8/29/201816726오류 유형: 482. TFS - Could not find a part of the path '...\packages\Microsoft.AspNet.WebApi.5.2.5\.signature.p7s'.
11676정성태8/29/201827570.NET Framework: 791. C# - ElasticSearch를 위한 Client 라이브러리 제작 [1]파일 다운로드1
11675정성태8/29/201817750오류 유형: 481. The located assembly's manifest definition does not match the assembly reference.
11674정성태8/29/201819722Phone: 12. Xamarin - 기존 리모컨 기능을 핸드폰의 적외선 송신으로 구현파일 다운로드1
11673정성태8/28/201816990오류 유형: 480. Fritzing 실행 시 Ordinal Not Found 오류
11672정성태8/28/201817425오류 유형: 479. 윈도우 - 시스템 설정에서 도메인 참가를 위한 "Change" 버튼이 비활성화된 경우
11671정성태8/28/201823815사물인터넷: 39. 아두이노에서 적외선 송신기 기본 사용법파일 다운로드1
11670정성태8/28/201822048사물인터넷: 38. 아두이노에서 적외선 수신기 기본 사용법 [1]파일 다운로드1
11669정성태8/24/201820826개발 환경 구성: 394. 윈도우 환경에서 elasticsearch의 한글 블로그 검색 인덱스 구성
11668정성태8/24/201831847오류 유형: 478. 윈도우 업데이트(KB4458842) 이후 SQL Server 서비스 시작 오류
11667정성태8/24/201818633오류 유형: 477. "Use Unicode UTF-8 for worldwide language support" 옵션 설정 시 SQL Server 2016 설치 오류 [1]
11666정성태8/22/201818541사물인터넷: 37. 아두이노 - 코딩으로 대신하는 오실레이터 회로의 소리 출력파일 다운로드1
11665정성태8/22/201821230사물인터넷: 36. 오실레이터 회로 동작을 아두이노의 코딩으로 구현하는 방법파일 다운로드1
11664정성태8/22/201820858개발 환경 구성: 393. 윈도우 환경에서 elasticsearch의 한글 형태소 분석기 설치 [1]
11663정성태8/22/201823571개발 환경 구성: 392. 윈도우 환경에서 curl.exe를 이용한 elasticsearch 6.x 기본 사용법
11662정성태8/21/201817245사물인터넷: 35. 병렬 회로에서의 커패시터파일 다운로드1
11661정성태8/21/201819555사물인터넷: 34. 트랜지스터 동작 - 컬렉터-이미터 간의 저항 측정파일 다운로드1
11660정성태8/19/201818633사물인터넷: 33. 세라믹 커패시터의 동작 방식파일 다운로드1
11659정성태8/19/201818461사물인터넷: 32. 9V 전압에서 테스트하는 PN2222A 트랜지스터파일 다운로드1
... 76  77  78  79  80  81  82  83  84  85  86  87  88  89  [90]  ...