성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] Working with Rust Libraries from C#...
[정성태] Detecting blocking calls using asyn...
[정성태] 아쉽게도, 커뮤니티는 아니고 개인 블로그입니다. ^^
[정성태] 질문이 잘 이해가 안 됩니다. 우선, 해당 소스코드에서 ILis...
[양승조
] var대신 dinamic으로 선언해서 해결은 했습니다. 맞는 해...
[양승조
] 또 막혔습니다. ㅠㅠ var list = props[i].Ge...
[양승조
] 아. 감사합니다. 어제는 안됐던것 같은데....정신을 차려야겠네...
[정성태] "props[i].GetValue(props[i])" 코드에서 ...
[정성태] 저렇게 조각 코드 말고, 실제로 재현이 되는 예제 프로젝트를 압...
[정성태] Modules 창(Ctrl+Shift+U)을 띄워서, 해당 Op...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>기본 생성된 kubeconfig 파일의 내용을 새롭게 생성한 인증서로 구성하는 방법</h1> <p> 지난 글에서,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > kubectl 수행 시 다른 k8s 클러스터로 접속하는 방법 ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12583'>https://www.sysnet.pe.kr/2/0/12583</a> </pre> <br /> 결국 중요한 것은 config 파일만 있으면 해당 config과 연관된 k8s 클러스터를 자유롭게 접근하는 것이 가능하다는 것을 알았습니다. 그렇다는 것은, config 파일을 다른 곳으로 복사해야 한다는 것을 의미합니다.<br /> <br /> 혹시 새롭게 인증서를 생성해서 주는 방법은 없을까요? 아래의 글을 읽어봤다면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > openssl - CA로부터 인증받은 새로운 인증서를 생성하는 방법 ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12570'>https://www.sysnet.pe.kr/2/0/12570</a> </pre> <br /> 이것이 가능하다는 것을 알 수 있을 것입니다. 즉, 새롭게 client 측에서 사용할 개인키를 생성하고 인증서 요청 파일(csr)을 만든 다음 CA 서버의 개인키와 인증서로 서명을 하면 되는 것입니다.<br /> <br /> 실제로 한 번 해볼까요? ^^<br /> <br /> <hr style='width: 50%' /><br /> <br /> 자, 그럼 먼저 개인키를 하나 생성해 보겠습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\temp\pki\cluster2> <span style='color: blue; font-weight: bold'>openssl genrsa -out client-side.key 2048</span> Generating RSA private key, 2048 bit long modulus (2 primes) ............+++++ .+++++ e is 65537 (0x010001) </pre> <br /> k8s가 요구하는 인증서 규약에 따라,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > PKI certificates and requirements ; <a target='tab' href='https://kubernetes.io/docs/setup/best-practices/certificates/'>https://kubernetes.io/docs/setup/best-practices/certificates/</a> </pre> <br /> 다음의 cnf 파일을 만들고,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 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 </pre> <br /> CSR 파일을 생성합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\temp\pki\cluster2> <span style='color: blue; font-weight: bold'>openssl req -new -key client-side.key -out client.csr -config client.cnf</span> </pre> <br /> 이렇게 생성한 csr 파일을 이제 CA 인증서로 서명을 하면 되는데요, 이를 위해 필요한 파일이 CA 인증서와 개인키입니다. 이 파일들을 구하는 방법은 해당 k8s 클러스터와 관계된 pki 디렉터리를 찾아야 합니다. 이에 대해서는 이미 다음의 글에서 설명했는데요,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Docker Desktop for Windows 기반의 Kubernetes 구성 (2) - WSL 2 인스턴스에 kind가 구성한 k8s 서비스 위치 ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12578#cert_path'>https://www.sysnet.pe.kr/2/0/12578#cert_path</a> </pre> <br /> 여기서는 k8s를 kind로 구성한 경우를 예로 들겠습니다. 이를 위해 해당 k8s를 호스팅하는 컨테이너를 알아내고,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\temp\pki\cluster2> <span style='color: blue; font-weight: bold'>docker ps</span> 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 </pre> <br /> 그 컨테이너 내에 위치한 /etc/kubernetes/pki 디렉터리의 파일들을 로컬로 복사해 온 다음 (또는, 정확하게 ca.crt, ca.key 파일만 복사),<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\temp\test> <span style='color: blue; font-weight: bold'>docker cp 62cd9120f957:/etc/kubernetes/pki .</span> </pre> <br /> 로컬에 복사된 ca.crt, ca.key 파일을 사용해 다음과 같이 클라이언트 인증서의 요청 파일을 서명해 줍니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\temp\pki\cluster2> <span style='color: blue; font-weight: bold'>openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 10000 -extensions v3_ext -extfile client.cnf</span> Signature ok subject=CN = testusr, O = system:masters Getting CA Private Key </pre> <br /> 이렇게 해서 새로 생성된 client.crt 파일과 client-side.key, ca.crt 파일만 있으면 이제 다음과 같이 kubectl을 사용할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\temp\pki\cluster2> <span style='color: blue; font-weight: bold'>kubectl get nodes --server https://127.0.0.1:20971 --client-certificate client.crt --client-key client-side.key --certificate-authority ca.crt</span> NAME STATUS ROLES AGE VERSION cluster2-control-plane Ready control-plane,master 3d7h v1.20.2 </pre> <br /> <hr style='width: 50%' /><br /> <br /> 자, 그럼 절차가 정해졌군요. 만약 다른 사람이 여러분들의 k8s 클러스터에 접근하고 싶다면 간단하게는 여러분들이 사용하는 config 파일을 전달하면 됩니다. 혹은, 상대방에게 CSR 파일을 달라고 해 그것을 자신이 운영하고 있는 k8s 클러스터의 ca.crt, ca.key 파일로 csr 파일을 서명 후 생성된 crt 파일과 ca.crt 파일을 함께 전달해 주면 됩니다.<br /> <br /> 그럼 상대 측은 전달받은 client.crt, ca.crt 파일과 함께 자신이 가지고 있는 client-side.key 파일을 이용해 kubectl 명령어를 실행할 수 있게 됩니다. (사실, 이것은 SSL 인증서나 소프트웨어 인증서를 취득하는 과정과 정확히 일치합니다.)<br /> <br /> 물론, 명령행에 일일이 "--client-certificate client.crt --client-key client-side.key --certificate-authority ca.crt" 옵션을 넣는 것은 귀찮으므로 지난 글에서 설명한 방법을 이용해,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 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 </pre> <br /> kubeconfig 파일을 생성해 두는 것도 좋을 것입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > apiVersion: v1 clusters: - cluster: <span style='color: blue; font-weight: bold'>certificate-authority: ca.crt</span> 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: <span style='color: blue; font-weight: bold'>client-certificate: client.crt</span> <span style='color: blue; font-weight: bold'>client-key: client-side.key</span> </pre> <br /> 그런데 위와 같이 설정해 두면 ca.crt, client.crt, client-side.key 파일을 함께 들고 다녀야 하므로 불편하니, 각각의 파일 내용을 base64 인코딩 시켜 kubeconfig 파일 내에 합치는 것이 좋습니다.<br /> <br /> 이를 위해 ca.crt를 certificate-authority-data로, client.crt를 client-certificate-data로, client-side.key를 client-key-data로 각각 값을 설정하면 됩니다. (base64 명령어는 윈도우의 경우 없으므로 <a target='tab' href='https://github.com/stjeong/Utilities/releases/download/v1.1.1/Utilities.zip'>별도로 다운로드</a>해야 합니다.)<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\temp\pki\cluster2> <span style='color: blue; font-weight: bold'>base64 -w 0 ca.crt | clip</span> // clipboard에 복사되었으므로 config-demo 파일의 certificate-authority-data로 복사 C:\temp\pki\cluster2> <span style='color: blue; font-weight: bold'>base64 -w 0 client.crt | clip</span> // clipboard에 복사되었으므로 config-demo 파일의 client-certificate-data로 복사 C:\temp\pki\cluster2> <span style='color: blue; font-weight: bold'>base64 -w 0 client-side.key | clip</span> // clipboard에 복사되었으므로 config-demo 파일의 client-key-data로 복사 </pre> <br /> 그럼 config-demo의 최종 파일 구성이 다음과 같이 될 것이고,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > apiVersion: v1 clusters: - cluster: <span style='color: blue; font-weight: bold'>certificate-authority-data: LS0tLS...[생략]...LS0tCg==</span> 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: <span style='color: blue; font-weight: bold'>client-certificate-data: LS0tLS1CRU...[생략]...tCg== client-key-data: LS0tLS1CR...[생략]...S0tCg==</span> </pre> <br /> 이제 별다른 부가 파일 필요 없이 config-demo 파일 하나로 kubectl 명령어를 수행할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\temp\pki\cluster2> <span style='color: blue; font-weight: bold'>kubectl cluster-info --kubeconfig=config-demo</span> 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 </pre> <br /> <hr style='width: 50%' /><br /> <br /> 지난 글에서 configmaps에 CA 인증서를 담고 있는 것을 설명했는데요,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > kubeconfig 파일 없이 kubectl 옵션만으로 실행하는 방법 ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12584#configmaps'>https://www.sysnet.pe.kr/2/0/12584#configmaps</a> </pre> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\temp\wsl2> <span style='color: blue; font-weight: bold'>kubectl get configmaps</span> NAME DATA AGE kube-root-ca.crt 1 11h </pre> <br /> 그렇다면 혹시 또 다른 CA 인증서를 등록하는 것도 가능할까요? ^^ 일단 다음과 같은 식으로 명령을 내리면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\temp\wsl2> <span style='color: blue; font-weight: bold'>kubectl create configmap test-ca.crt --from-file=C:\temp\wsl2\ca.crt</span> configmap/test-ca.crt created C:\temp\wsl2> <span style='color: blue; font-weight: bold'>kubectl get configmaps</span> NAME DATA AGE kube-root-ca.crt 1 27h <span style='color: blue; font-weight: bold'>test-ca.crt</span> 1 6s </pre> <br /> test-ca.crt는 kube-root-ca.crt와 동일한 양식으로 등록은 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\temp\wsl2> <span style='color: blue; font-weight: bold'>kubectl describe configmaps test-ca.crt</span> Name: test-ca.crt Namespace: default Labels: <none> Annotations: <none> Data ==== ca.crt: ---- -----BEGIN CERTIFICATE----- MIIDCTCCAfGgAwIBAgIUc57N5ZHozrDio2hBQlOLB2iCfs4wDQYJKoZIhvcNAQEL ...[생략]... q1gObmghvUdhkdx1u8iNtKTua3czzwpzuOhsp7H0GFVh5jlK+RoD0rrlHEubIt4L Zij0Yk2SrgxO3GvA1Q== -----END CERTIFICATE----- Events: <none> </pre> <br /> 동작 여부는, 나중에 시간 나면 확인해 보겠습니다. ^^<br /> <br /> <hr style='width: 50%' /><br /> <br /> 참고로 openssl의 cnf 파일에 있는 FQDN은 임의의 값을 넣어도 되지만, 이 외의 값들(예를 들어, ORGNAME)은 가능한 규격을 지켜야 합니다. 만약 (ORGNAME으로 인한) O = system:masters 설정이 없으면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > FQDN = testusr [ req ] default_bits = 2048 prompt = no default_md = sha256 req_extensions = req_ext distinguished_name = dn ...[생략]... </pre> <br /> kubectl 실행 시 다음과 같은 오류가 발생합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\temp\pki\cluster2> <span style='color: blue; font-weight: bold'>kubectl get nodes --server https://127.0.0.1:20971 --client-certificate client.crt --client-key client-side.key --certificate-authority ca.crt</span> Error from server (Forbidden): nodes is forbidden: User "testusr" cannot list resource "nodes" in API group "" at the cluster scope </pre> <br /> <hr style='width: 50%' /><br /> <br /> "kubectl create configmap... " 명령어 수행 시 다음과 같은 오류가 발생한다면?<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\temp\wsl2> <span style='color: blue; font-weight: bold'>kubectl create configmap test_ca.crt --from-file=C:\temp\wsl2\ca.crt</span> 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])?)*') </pre> <br /> 오류 메시지에 볼 수 있는 것처럼, configmap의 이름으로 지정할 수 있는 값에 밑줄(underscore, _)은 유효하지 않은 문자이므로, '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*' 정규 표현식을 만족하는 범위 내의 문자로 이름을 지어야 합니다.<br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
2871
(왼쪽의 숫자를 입력해야 합니다.)