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) 파일로 복사해,

/* $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




다음과 같이 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




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

[연관 글]


donaricano-btn



[최초 등록일: ]
[최종 수정일: 3/29/2021

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)
12440정성태12/4/2020991오류 유형: 689. SignTool Error: Invalid option: /as
12439정성태12/4/20201215디버깅 기술: 176. windbg - 특정 Win32 API에서 BP가 안 걸리는 경우 (2)
12438정성태12/2/20201178오류 유형: 688. .Visual C++ - Error C2011 'sockaddr': 'struct' type redefinition
12437정성태12/1/20201139VS.NET IDE: 155. pfx의 암호 키 파일을 Visual Studio 없이 등록하는 방법
12436정성태12/1/20201306오류 유형: 687. .NET Core 2.2 빌드 - error MSB4018: The "RazorTagHelper" task failed unexpectedly.
12435정성태12/1/20204145Windows: 181. 윈도우 환경에서 클라이언트 소켓의 최대 접속 수 (4) - ReuseUnicastPort를 이용한 포트 고갈 문제 해결파일 다운로드1
12434정성태11/30/20201323Windows: 180. C# - dynamicport 값의 범위를 알아내는 방법
12433정성태11/29/20201234Windows: 179. 윈도우 환경에서 클라이언트 소켓의 최대 접속 수 (3) - SO_PORT_SCALABILITY파일 다운로드1
12432정성태11/29/20201564Windows: 178. 윈도우 환경에서 클라이언트 소켓의 최대 접속 수 (2) - SO_REUSEADDR [1]파일 다운로드1
12431정성태11/27/20201152.NET Framework: 976. UnmanagedCallersOnly + C# 9.0 함수 포인터 사용 시 x86 빌드에서 오동작하는 문제파일 다운로드1
12430정성태11/27/20201221오류 유형: 686. Ubuntu - E: The repository 'cdrom://...' does not have a Release file.
12429정성태11/25/20201187디버깅 기술: 175. windbg - 특정 Win32 API에서 BP가 안 걸리는 경우
12428정성태11/25/20201068VS.NET IDE: 154. Visual Studio - .NET Core App 실행 시 dotnet.exe 실행 화면만 나오는 문제
12427정성태11/24/20201315.NET Framework: 975. .NET Core를 직접 호스팅해 (runtimeconfig.json 없이) EXE만 배포해 실행파일 다운로드1
12426정성태11/24/20201137오류 유형: 685. WinDbg Preview - error InitTypeRead
12425정성태11/24/20201228VC++: 141. Visual C++ - "Treat Warnings As Errors" 옵션이 꺼져 있는데도 일부 경고가 에러 처리되는 경우
12424정성태11/24/20201404VC++: 140. C++의 연산자 동의어(operator synonyms), 대체 토큰
12423정성태11/22/20201312.NET Framework: 974. C# 9.0 - (16) 제약 조건이 없는 형식 매개변수 주석(Unconstrained type parameter annotations)파일 다운로드1
12422정성태11/21/20201194.NET Framework: 973. .NET 5, .NET Framework에서만 허용하는 UnmanagedCallersOnly 사용예파일 다운로드1
12421정성태11/19/20201163.NET Framework: 972. DNNE가 출력한 NE DLL을 직접 생성하는 방법파일 다운로드1
12420정성태11/19/20201165오류 유형: 684. Visual C++ - MSIL .netmodule or module compiled with /GL found; restarting link with /LTCG; add /LTCG to the link command line to improve linker performance
12419정성태11/19/20201158VC++: 139. Visual C++ - .NET Core의 nethost.lib와 정적 링크파일 다운로드1
12418정성태11/19/20201147오류 유형: 683. Visual C++ - error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MT_StaticRelease' doesn't match value 'MDd_DynamicDebug'파일 다운로드1
12417정성태11/19/2020949오류 유형: 682. Visual C++ - warning LNK4099: PDB '...pdb' was not found with '...lib(pch.obj)' or at '...pdb'; linking object as if no debug info
12416정성태11/19/20201187오류 유형: 681. Visual C++ - error LNK2001: unresolved external symbol _CrtDbgReport
12415정성태11/18/20201045.NET Framework: 971. UnmanagedCallersOnly 특성과 DNNE 사용파일 다운로드1
1  2  3  4  5  6  7  8  9  10  11  12  [13]  14  15  ...