Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 

kubectl 수행 시 다른 k8s 클러스터로 접속하는 방법

docker의 경우 "-H" 옵션을 이용해,

Linux 운영체제의 docker를 위한 tcp 바인딩 추가
; https://www.sysnet.pe.kr/2/0/12178

Ubuntu 20.04 - docker를 위한 tcp 바인딩 추가
; https://www.sysnet.pe.kr/2/0/12349

또 다른 docker 인스턴스에 접근하는 것이 가능했는데요, kubectl은 이것을 어떻게 할 수 있을까요? 이에 대한 방법을 다음의 글에서 잘 설명하고 있습니다.

Mastering the KUBECONFIG file
; https://ahmet.im/blog/mastering-kubeconfig/

kubeconfig 파일을 사용하여 클러스터 접근 구성하기
; https://kubernetes.io/ko/docs/concepts/configuration/organize-cluster-access-kubeconfig/

간단하게 정리해 볼까요? ^^




지난 글에, docker desktop for windows 환경에서 "Use the WSL 2 based engine" 옵션을 켜고 kind를 이용해 WSL 2와,

$ kind create cluster --name cluster1

$ kubectl cluster-info
Kubernetes master is running at https://127.0.0.1:45381
KubeDNS is running at https://127.0.0.1:45381/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

윈도우 호스트 측에서 각각의 클러스터를 구성할 수 있다고 설명했습니다. (물론, --name의 값만 바꾸면 클러스터를 각각의 환경에서 원하는 대로 생성할 수 있습니다.)

c:\temp\knd> kind create cluster --name cluster2

c:\temp\knd> kubectl cluster-info
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

위와 같은 상황인 경우, WSL 2 측에서 kubectl을 이용해 (윈도우 측에서 생성한) cluster2를 대상으로 명령을 실행하고 싶다면 어떻게 해야 할까요?

간단한 방법이라면, cluster2에 대한 접근 정보를 가지고 있는 윈도우 측의 %USERPROFILE%\.kube\config 파일을 WSL 2 측에 (예를 들어 cluster2.config) 파일로 복사해,

/* 윈도우: type "%USERPROFILE%\.kube\config" */
/* $HOME/.kube 디렉터리에 원래 있던 config 파일 */
$ cat $HOME/.kube/config
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tL...[생략]...tCg==
    server: https://127.0.0.1:45381
  name: kind-cluster1
contexts:
- context:
    cluster: kind-cluster1
    user: kind-cluster1
  name: kind-cluster1
current-context: kind-cluster1
kind: Config
preferences: {}
users:
- name: kind-cluster1
  user:
    client-certificate-data: LS0t...[생략]...Qo=
    client-key-data: LS0tLS...[생략]...tCg==

/* 윈도우 측의 %USERPROFILE%\.kube\config을 WSL 2 측으로 복사해 온 파일 */
$ cat $HOME/.kube/cluster2.config
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0t...[생략]...Cg==
    server: https://127.0.0.1:20971
  name: kind-cluster2
contexts:
- context:
    cluster: kind-cluster2
    user: kind-cluster2
  name: kind-cluster2
current-context: kind-cluster2
kind: Config
preferences: {}
users:
- name: kind-cluster2
  user:
    client-certificate-data: LS0t...[생략]...Qo=
    client-key-data: LS0tL...[생략]...o=

그 경로를 kubectl의 --kubeconfig 인자로 넘겨주면 됩니다.

$ kubectl --kubeconfig=$HOME/.kube/cluster2.config cluster-info
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

편의상, 명령을 자주 실행해야 한다면 KUBECONFIG 환경 변수를 이용해 지정해 두는 것도 가능합니다.

// 기본 config 경로인 $HOME/.kube/config 정보로 k8s 클러스터 접근
$ kubectl cluster-info
Kubernetes master is running at https://127.0.0.1:45381
KubeDNS is running at https://127.0.0.1:45381/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

// $HOME/.kube/cluster2.config 정보로 k8s 클러스터 접근
$ export KUBECONFIG=$HOME/.kube/cluster2.config
$ kubectl cluster-info
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




또 다른 방법으로, 별도로 구성한 kubeconfig 파일을 마치 병합하는 듯한 효과를 줘서 kubectl 수행 시 --context 인자로 구분하는 것도 가능합니다. 이를 위해 KUBECONFIG 환경 변수를 다음과 같이 설정하고,

$ export KUBECONFIG=$HOME/.kube/config:$HOME/.kube/cluster2.config

각각의 config 파일 내에 클러스터의 "name: " 항목에 지정하고 있는 이름을 --context 인자에 넘겨 사용할 수 있습니다.

/* 어차피 기본 파일은 $HOME/.kube/config이 있으므로 아래의 명령어는 "kubectl cluster-info"로 대체 가능 */
$ kubectl --context=kind-cluster1 cluster-info
Kubernetes master is running at https://127.0.0.1:45381
KubeDNS is running at https://127.0.0.1:45381/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

$ kubectl --context=kind-cluster2 cluster-info
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

위와 같이 KUBECONFIG을 사용하면 매번 환경 변수를 지정해야 하는 불편함이 있는데, 이를 보완하기 위해 아예 하나의 config 파일로 합치는 방법도 있습니다. 수작업으로 kubeconfig yaml 문법에 맞게 병합할 수 있겠지만, 해당 기능을 kubectl 명령어의 옵션으로도 제공하므로 합쳐질 파일들의 목록을 KUBECONFIG 환경 변수로 전달해 다음과 같이 실행할 수 있습니다.

$ export KUBECONFIG=$HOME/.kube/config:$HOME/.kube/cluster2.config
$ kubectl config view --merge --flatten > out.txt
$ cat out.txt
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0t...[생략]...g==
    server: https://127.0.0.1:45381
  name: kind-cluster1
- cluster:
    certificate-authority-data: LS0...[생략]...==
    server: https://127.0.0.1:20971
  name: kind-cluster2
contexts:
- context:
    cluster: kind-cluster1
    user: kind-cluster1
  name: kind-cluster1
- context:
    cluster: kind-cluster2
    user: kind-cluster2
  name: kind-cluster2
current-context: kind-cluster1
kind: Config
preferences: {}
users:
- name: kind-cluster1
  user:
    client-certificate-data: LS...[생략]...Qo=
    client-key-data: LS0t...[생략]...g==
- name: kind-cluster2
  user:
    client-certificate-data: LS0...[생략]...tLQo=
    client-key-data: LS0t...[생략]...LQo=

이렇게 단일 kubeconfig 파일에 다수의 cluster 정보를 가진 경우 기본적으로는 "current-context"에 지정한 클러스터가 kubectl의 기본 명령어 대상이 됩니다. 실습을 위해 위와 같이 출력한 out.txt 파일을 $HOME/.kube/config 파일로 복사해 놓고 다음의 명령어를 실행해 볼 수 있습니다.

$ kubectl cluster-info
Kubernetes master is running at https://127.0.0.1:45381
KubeDNS is running at https://127.0.0.1:45381/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

$ kubectl cluster-info --context=kind-cluster2
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

/* 아울러 current-context를 명령어를 이용해 변경하는 것도 가능하고! */

// kubeconfig 파일에 등록된 context 목록
$ kubectl config get-contexts
CURRENT   NAME            CLUSTER         AUTHINFO        NAMESPACE
*         kind-cluster1   kind-cluster1   kind-cluster1
          kind-cluster2   kind-cluster2   kind-cluster2

// current-context의 값을 kind-clsuter2로 변경
$ kubectl config use-context kind-cluster2

$ kubectl config get-contexts
CURRENT   NAME            CLUSTER         AUTHINFO        NAMESPACE
          kind-cluster1   kind-cluster1   kind-cluster1
*         kind-cluster2   kind-cluster2   kind-cluster2

참고로 병합한 파일로부터 다시 특정 클러스터 설정만을 별도의 kubeconfig 파일로 뽑아내는 것도 가능합니다.

$ kubectl config view --minify --flatten --context=kind-cluster2 > cluster2.config

$ cat cluster2.config
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0t...[생략]...Cg==
    server: https://127.0.0.1:20971
  name: kind-cluster2
contexts:
- context:
    cluster: kind-cluster2
    user: kind-cluster2
  name: kind-cluster2
current-context: kind-cluster2
kind: Config
preferences: {}
users:
- name: kind-cluster2
  user:
    client-certificate-data: LS0t...[생략]...LQo=
    client-key-data: LS0t...[생략]...LQo=




원한다면, 자동 생성된 kubeconfig 파일을 kubectl 명령어를 이용해 직접 생성하는 것이 가능합니다.

c:\temp\knd> kubectl config --kubeconfig=config-demo set-cluster kind-cluster3 --server=https://127.0.0.1:20971 --certificate-authority="ca-cert-in.crt"
c:\temp\knd> kubectl config --kubeconfig=config-demo set-credentials kind-cluster3 --client-certificate="cert-in.crt" --client-key="cert-in.key"
c:\temp\knd> kubectl config --kubeconfig=config-demo set-context kind-cluster3 --cluster=kind-cluster3 --user=kind-cluster3
c:\temp\knd> kubectl config --kubeconfig=config-demo use-context kind-cluster3

그럼 다음과 같은 config-demo 파일이 생성됩니다.

apiVersion: v1
clusters:
- cluster:
    certificate-authority: ca-cert-in.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: cert-in.crt
    client-key: cert-in.key

인증서의 파일 경로는 kubectl을 실행한 경로에 대해 상대적으로 설정되는데요, 따라서 위의 경우에는 실행 시 해당 인증서를 현재의 디렉터리에서 찾을 수 있도록 인증서 및 키 파일을 복사하고 kubectl.exe를 실행해야 합니다.

// c:\temp\knd 디렉터리에 ca-cert-in.crt, cert-in.crt, cert-in.key 파일이 있다고 가정

c:\temp\knd> 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

위의 내용을 실습하려면, config-demo 파일 내에 지정한 certificate-authority, client-certificate, client-key 인증서를 어떻게 구할 수 있느냐라는 문제가 남는데요, 이에 대해서는 다른 글을 통해 다뤄보도록 하겠습니다. ^^




그럴 경우가 많지 않겠지만, 이런 식으로 kind를 이용해 Windows 10에 k8s 클러스터를 구성한 경우 다른 컴퓨터에서 접속하고 싶다면 부가적인 작업을 더 해야 합니다. 우선, kind가 생성하는 기본 클러스터는 TCP 바인딩을 "127.0.0.1"로 고정하기 때문에,

c:\temp> kubectl cluster-info
Kubernetes master is running at https://127.0.0.1:9272
KubeDNS is running at https://127.0.0.1:9272/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

c:\temp> netstat -ano | findstr 20971
  TCP    127.0.0.1:20971        0.0.0.0:0              LISTENING       34208

이것을 "0.0.0.0"으로 바인딩을 바꾸기 위해 yml에 명시하고,

# cluster-config.yml
kind: Cluster
name: cluster3
apiVersion: kind.x-k8s.io/v1alpha4
networking:
  apiServerAddress: "0.0.0.0"

클러스터를 생성하면,

c:\temp\wsl2> kind create cluster --config=cluster-config.yml

C:\temp\wsl2> docker ps
CONTAINER ID   IMAGE                  COMMAND                  CREATED          STATUS          PORTS                       NAMES
382ca15b6502   kindest/node:v1.20.2   "/usr/local/bin/entr…"   39 seconds ago   Up 36 seconds   0.0.0.0:16109->6443/tcp     cluster3-control-plane

c:\temp\wsl2> netstat -ano | findstr 16109
  TCP    0.0.0.0:16109          0.0.0.0:0              LISTENING       34208
  TCP    [::]:16109             [::]:0                 LISTENING       34208
  TCP    [::1]:16109            [::]:0                 LISTENING       25360

TCP 바인딩이 "0.0.0.0"으로 바뀌었습니다. 이제 %USERPROFILE\.kube\config 파일을 다른 컴퓨터에 복사하고, 아래의 "server" 주소만 "0.0.0.0"에서,

apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1...[생략]...Cg==
    server: https://0.0.0.0:16109
  name: kind-cluster3
...[생략]...

IP 주소(예를 들어, 이 글에서는 192.168.100.50이라고 가정)를 직접 기입한 후 kubectl.exe를 다음과 같이 실행해 볼 수 있습니다.

C:\temp> kubectl get pods
Unable to connect to the server: x509: certificate is valid for 10.96.0.1, 172.18.0.3, 0.0.0.0, not 192.168.100.50

보는 바와 같이 허용된 DNS/IP가 인증서에 포함되어 있지 않기 때문에 발생하는 오류입니다. 괜찮습니다, ^^ 이런 경우에도 "--insecure-skip-tls-verify" 옵션을 적용하면 되기 때문입니다.

C:\temp> kubectl cluster-info  --insecure-skip-tls-verify
Kubernetes master is running at https://192.168.100.50:16109
KubeDNS is running at https://192.168.100.50:16109/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

C:\temp> kubectl run nginx-app --image nginx --port=80 --insecure-skip-tls-verify
pod/nginx-app created




config 파일의 설정에서 특정 클러스터 정보를 삭제하려면 3번의 명령을 수행해야 합니다. 즉, 각 yaml 설정에서 users, contexts, clsuters에 추가된 항목의 이름을 알아내 개별 삭제합니다.
$ kubectl config unset users.[지우려는 users의 name]
$ kubectl config unset contexts.[지우려는 contexts의 name]
$ kubectl config unset clusters.[지우려는 clusters의 name]

이후 만약 삭제한 클러스터가 current-context에 해당한다면 다음의 명령어로 다른 클러스터로 스위칭을 합니다.
$ kubectl config use-context [...남아 있는 클러스터 이름...]




다음과 같이 kubeconfig 파일 변경 시 권한 오류가 발생한다면?

/* 사용자 명이 testusr인 경우 */

$ kubectl config set-context kindcluster2
error: open /home/testusr/.kube/config: permission denied

아마도 WSL 2의 config 파일을 윈도우 탐색기를 이용해 "\\wsl$\Ubuntu20.04\home\testusr\.kube" 디렉터리로 접근 후 직접 config 파일을 생성하는 등의 변경을 가해서 그런 경우일 수 있습니다. 실제로 권한을 확인해 보면,

$ ls -l /home/testusr/.kube
total 40
drwxr-x--- 4 testusr testusr  4096  Mar 21 16:25 cache
-rw-r--r-- 1 root    root     10970 Mar 24 11:38 config

라는 식으로 나올 텐데요, 다음과 같이 권한을 변경해 주면 됩니다.

$ sudo chown $USER:$USER /home/testusr/.kube/config




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

[연관 글]






[최초 등록일: ]
[최종 수정일: 1/26/2022]

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

비밀번호

댓글 작성자
 




[1]  2  3  4  5  6  7  8  9  10  11  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
13119정성태8/18/202231.NET Framework: 2044. .NET Core/5+ 프로젝트에서 참조 DLL이 보관된 공통 디렉터리를 지정하는 방법
13118정성태8/18/202235.NET Framework: 2043. WPF Color의 기본 색 영역은 (sRGB가 아닌) scRGB [1]
13117정성태8/17/202294.NET Framework: 2042. C# 11 - 파일 범위 내에서 유효한 타입 정의 (File-local types)파일 다운로드1
13116정성태8/4/2022189.NET Framework: 2041. C# - Socket.Close 시 Socket.Receive 메서드에서 예외가 발생하는 문제파일 다운로드1
13115정성태8/3/2022278.NET Framework: 2040. C# - ValueTask와 Task의 성능 비교파일 다운로드1
13114정성태8/2/2022261.NET Framework: 2039. C# - Task와 비교해 본 ValueTask 사용법파일 다운로드1
13113정성태7/31/2022253.NET Framework: 2038. C# 11 - Span 타입에 대한 패턴 매칭 (Pattern matching on ReadOnlySpan<char>)
13112정성태7/30/2022303.NET Framework: 2037. C# 11 - 목록 패턴(List patterns)파일 다운로드1
13111정성태7/29/2022256.NET Framework: 2036. C# 11 - IntPtr/UIntPtr과 nint/nuint의 통합파일 다운로드1
13110정성태7/27/2022296.NET Framework: 2035. C# 11 - 새로운 연산자 ">>>" (Unsigned Right Shift)파일 다운로드1
13109정성태7/27/2022232VS.NET IDE: 177. 비주얼 스튜디오 2022를 이용한 (소스 코드가 없는) 닷넷 모듈 디버깅 - "외부 원본(External Sources)"
13108정성태7/26/2022172Linux: 53. container에 실행 중인 Golang 프로세스를 디버깅하는 방법
13107정성태7/25/2022137Linux: 52. Debian/Ubuntu 계열의 docker container에서 자주 설치하게 되는 명령어
13106정성태7/24/2022113오류 유형: 819. 닷넷 6 프로젝트의 "Conditional compilation symbols" 기본값 오류
13105정성태7/23/2022242.NET Framework: 2034. .NET Core/5+ 환경에서 (프로젝트가 아닌) C# 코드 파일을 입력으로 컴파일하는 방법 - 두 번째 이야기 [1]
13104정성태7/23/2022214Linux: 51. WSL - init에서 systemd로 전환하는 방법
13103정성태7/22/2022115오류 유형: 818. WSL - systemd-genie와 관련한 2가지(systemd-remount-fs.service, multipathd.socket) 에러
13102정성태7/19/2022198.NET Framework: 2033. .NET Core/5+에서는 구할 수 없는 HttpRuntime.AppDomainAppId
13101정성태7/15/2022167[내용 예약] (비어 있는 글)
13100정성태7/15/2022286.NET Framework: 2032. C# 11 - shift 연산자 재정의에 대한 제약 완화 (Relaxing Shift Operator)
13099정성태7/14/2022682.NET Framework: 2031. C# 11 - 사용자 정의 checked 연산자파일 다운로드1
13098정성태7/13/2022212개발 환경 구성: 647. Azure - scale-out 상태의 App Service에서 특정 인스턴스에 요청을 보내는 방법 [1]
13097정성태7/12/2022158오류 유형: 817. Golang - binary.Read: invalid type int32
13096정성태7/8/2022461.NET Framework: 2030. C# 11 - UTF-8 문자열 리터럴
13095정성태7/7/2022243Windows: 208. AD 도메인에 참여하지 않은 컴퓨터에서 Kerberos 인증을 사용하는 방법
[1]  2  3  4  5  6  7  8  9  10  11  12  13  14  15  ...