Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 
(연관된 글이 3개 있습니다.)

WSL 2 기반으로 "Enable Kubernetes" 활성화 시 초기화 실패

Docker Desktop for Windows에서 "Use the WSL 2 based engine" 옵션을 켠 경우, "Enable Kubernetes"를 적용하면 다음과 같이 "Starting ..."에서 멈추지를 않습니다.

k8s_config_hang_1.png

이때의 docker 로그(%LOCALAPPDATA%\Docker\log.txt)를 보면 이런 메시지가 반복되기도 하고,

"cannot get lease for master node: an error on the server (\"\") has prevented the request from succeeding (get leases.coordination.k8s.io docker-desktop)"
"external: POST /events 200 \"DockerDesktopGo\" \"\""

또는, k8s 관련 서비스들이 시작될 때까지 대기하는 듯한 메시지가 반복됩니다.

"1/3 system pods running, found labels component=kube-apiserver but still waiting for labels k8s-app=kube-dns, component=kube-controller-manager..."

관련해서 검색해 보면,

Docker for Windows stuck at “Kubernetes is Starting” after updating to version 2.1.1.0 Edge (or Stable)
; https://stackoverflow.com/questions/57711639/docker-for-windows-stuck-at-kubernetes-is-starting-after-updating-to-version-2

"%LOCALAPPDATA%\Docker\pki" 디렉터리를 삭제하고 다시 docker desktop을 재시작하면 됐다는 글들이 나옵니다.




그런데, 제 경우에는 그게 통하지 않았습니다. ^^; 게다가 k8s 구성이 정상적이지 않아 kubectl의 실행도 잘 되지 않는데요, 와중에 간혹 실행이 되면 출력에서 다음과 같은 문제를 볼 수 있습니다.

C:\temp> kubectl get pods --all-namespaces
NAMESPACE     NAME                                     READY   STATUS             RESTARTS   AGE
kube-system   etcd-docker-desktop                      1/1     Running            0          18m
kube-system   kube-apiserver-docker-desktop            1/1     Running            4          18m
kube-system   kube-controller-manager-docker-desktop   0/1     CrashLoopBackOff   8          19m
kube-system   kube-scheduler-docker-desktop            1/1     Running            0          18m

kube-controller-manager의 로그를 (운 좋게) 살펴보면,

C:\temp> kubectl -n kube-system logs -p  kube-controller-manager-docker-desktop
Error from server (InternalError): an error on the server ("") has prevented the request from succeeding (get pods kube-controller-manager-docker-desktop)

C:\temp> kubectl -n kube-system logs -p  kube-controller-manager-docker-desktop
Flag --port has been deprecated, see --secure-port instead.
I0318 07:06:16.127978       1 serving.go:331] Generated self-signed cert in-memory
I0318 07:06:16.331572       1 controllermanager.go:175] Version: v1.19.7
I0318 07:06:16.332216       1 dynamic_cafile_content.go:167] Starting request-header::/run/config/pki/front-proxy-ca.crt
I0318 07:06:16.332300       1 dynamic_cafile_content.go:167] Starting client-ca-bundle::/run/config/pki/ca.crt
I0318 07:06:16.332492       1 secure_serving.go:197] Serving securely on 127.0.0.1:10257
I0318 07:06:16.332585       1 tlsconfig.go:240] Starting DynamicServingCertificateController
W0318 07:06:27.194500       1 controllermanager.go:628] fetch api resource lists failed, use legacy client builder: Get "https://192.168.65.4:6443/api/v1?timeout=32s": x509: certificate is valid for 10.96.0.1, 0.0.0.0, 192.168.65.3, 127.0.0.1, not 192.168.65.4
F0318 07:06:37.201977       1 controllermanager.go:244] error building controller context: failed to wait for apiserver being healthy: timed out waiting for the condition: failed to get apiserver /healthz status: Get "https://192.168.65.4:6443/healthz?timeout=32s": x509: certificate is valid for 10.96.0.1, 0.0.0.0, 192.168.65.3, 127.0.0.1, not 192.168.65.4

goroutine 1 [running]:
k8s.io/kubernetes/vendor/k8s.io/klog/v2.stacks(0xc000130001, 0xc00037a280, 0x167, 0x276)
        /workspace/src/k8s.io/kubernetes/_output/dockerized/go/src/k8s.io/kubernetes/vendor/k8s.io/klog/v2/klog.go:996 +0xb9
k8s.io/kubernetes/vendor/k8s.io/klog/v2.(*loggingT).output(0x6a47fa0, 0xc000000003, 0x0, 0x0, 0xc000a0a150, 0x68bfef4, 0x14, 0xf4, 0x0)
        /workspace/src/k8s.io/kubernetes/_output/dockerized/go/src/k8s.io/kubernetes/vendor/k8s.io/klog/v2/klog.go:945 +0x191
k8s.io/kubernetes/vendor/k8s.io/klog/v2.(*loggingT).printf(0x6a47fa0, 0x3, 0x0, 0x0, 0x449dd15, 0x25, 0xc001125348, 0x1, 0x1)
        /workspace/src/k8s.io/kubernetes/_output/dockerized/go/src/k8s.io/kubernetes/vendor/k8s.io/klog/v2/klog.go:733 +0x17a
k8s.io/kubernetes/vendor/k8s.io/klog/v2.Fatalf(...)
        /workspace/src/k8s.io/kubernetes/_output/dockerized/go/src/k8s.io/kubernetes/vendor/k8s.io/klog/v2/klog.go:1456
k8s.io/kubernetes/cmd/kube-controller-manager/app.Run.func1(0x4a691a0, 0xc00012e018)
        /workspace/src/k8s.io/kubernetes/_output/dockerized/go/src/k8s.io/kubernetes/cmd/kube-controller-manager/app/controllermanager.go:244 +0x54e
k8s.io/kubernetes/cmd/kube-controller-manager/app.Run(0xc000b7eea0, 0xc0001140c0, 0xc000d0c950, 0xc000b7e458)
        /workspace/src/k8s.io/kubernetes/_output/dockerized/go/src/k8s.io/kubernetes/cmd/kube-controller-manager/app/controllermanager.go:260 +0x9b1
k8s.io/kubernetes/cmd/kube-controller-manager/app.NewControllerManagerCommand.func2(0xc0006c8dc0, 0xc000d08b40, 0x0, 0x13)
        /workspace/src/k8s.io/kubernetes/_output/dockerized/go/src/k8s.io/kubernetes/cmd/kube-controller-manager/app/controllermanager.go:124 +0x2b7
k8s.io/kubernetes/vendor/github.com/spf13/cobra.(*Command).execute(0xc0006c8dc0, 0xc000136010, 0x13, 0x13, 0xc0006c8dc0, 0xc000136010)
        /workspace/src/k8s.io/kubernetes/_output/dockerized/go/src/k8s.io/kubernetes/vendor/github.com/spf13/cobra/command.go:846 +0x2c2
k8s.io/kubernetes/vendor/github.com/spf13/cobra.(*Command).ExecuteC(0xc0006c8dc0, 0x166d5dfe0031f738, 0x6a47c00, 0x406525)
        /workspace/src/k8s.io/kubernetes/_output/dockerized/go/src/k8s.io/kubernetes/vendor/github.com/spf13/cobra/command.go:950 +0x375
k8s.io/kubernetes/vendor/github.com/spf13/cobra.(*Command).Execute(...)
        /workspace/src/k8s.io/kubernetes/_output/dockerized/go/src/k8s.io/kubernetes/vendor/github.com/spf13/cobra/command.go:887
main.main()
        _output/dockerized/go/src/k8s.io/kubernetes/cmd/kube-controller-manager/controller-manager.go:46 +0xe5

아래의 메시지가 눈에 띕니다.

// Kubelet - x509: certificate is valid for 10.233.0.1 not for <IP>
// https://stackoverflow.com/questions/54303469/kubelet-x509-certificate-is-valid-for-10-233-0-1-not-for-ip

certificate is valid for 10.96.0.1, 0.0.0.0, 192.168.65.3, 127.0.0.1, not 192.168.65.4

누락된 192.168.65.4가 실제로 사용되고 있는 듯하고,

// 우선 kubectl proxy 실행

c:\temp> curl http://127.0.0.1:8001/api/
{
  "kind": "APIVersions",
  "versions": [
    "v1"
  ],
  "serverAddressByClientCIDRs": [
    {
      "clientCIDR": "0.0.0.0/0",
      "serverAddress": "192.168.65.4:6443"
    }
  ]
}

또한, 해당 인증서("%LOCALAPPDATA%\Docker\pki\apiserver.crt")를 보면,

k8s_config_hang_2.png

SAN에 "192.168.65.4" 항목이 없습니다. 아마도 "Docker for Windows stuck at “Kubernetes is Starting” after updating to version 2.1.1.0 Edge (or Stable)" 등의 Q&A에서 " pki 폴더를 삭제하고 재시작해 동작했다는 것이 저런 이유 때문으로 보입니다.




그런데, WSL 2 + k8s 초기화의 실패 원인이 저것만이 전부는 아닌 듯합니다. 왜냐하면, 위의 인증서는 192.168.65.4를 포함해 다시 생성하는 것이 가능하기 때문입니다. "%LOCALAPPDATA%\Docker\pki" 디렉터리를 보면, CA의 인증서 및 개인키 파일과 함께 apiserver에 대한 키파일도 있고,

  • ca.crt
  • ca.key
  • apiserver.key

k8s에서 요구하는 인증서의 요구 사항도 공개돼 있으므로,

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

Certificate Management with kubeadm
; https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-certs/

kube-apiserver
    Parent: kubernetes-ca   
    O (in Subject): (empty)
    kind: server
    hosts (SAN): <hostname>, <host_ip>, <advertise_ip>, [1]
    recommended key path: apiserver.key
    recommended cert path: apiserver.crt
    command: kube-apiserver
    key argument: --tls-private-key-file
    cert argument: --tls-cert-file

server == digital signature, key encipherment, server auth

[1] == any other IP or DNS name you contact your cluster on (as used by kubeadm the load balancer stable IP and/or DNS name, kubernetes, kubernetes.default, kubernetes.default.svc, kubernetes.default.svc.cluster, kubernetes.default.svc.cluster.local)

다음과 같은 식으로 cnf 파일을 만들어,

FQDN = kube-apiserver

# ALTNAMES는 기존 apiserver.crt의 Subject 목록을 포함한 후, "certificate is valid for ..., not 192.168.65.4"로 있는 IP를 추가해 구성
ALTNAMES = DNS:docker-for-desktop,DNS:kubernetes,DNS:kubernetes.default,DNS:kubernetes.default.svc,DNS:kubernetes.default.svc.cluster.local,DNS:kubernetes.docker.internal,DNS:vm.docker.internal,DNS:localhost,IP:10.96.0.1,IP:0.0.0.0,IP:192.168.65.3,IP:127.0.0.1,IP:192.168.65.4

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

[ dn ]
CN = $FQDN

[ req_ext ]
extendedKeyUsage = serverAuth
subjectAltName = $ALTNAMES
keyUsage = digitalSignature,keyEncipherment

[ x509_ext ]
extendedKeyUsage = serverAuth
authorityKeyIdentifier = keyid,issuer
subjectAltName = $ALTNAMES
keyUsage = digitalSignature,keyEncipherment

openssl 명령어를 실행해 (누락된 IP를 포함한) apiserver.crt를 새로 만들 수 있습니다.

C:\temp\wsl> openssl req -key apiserver.key -new -out apiserver.csr -config apiserver.cnf

C:\temp\wsl> openssl x509 -extfile apiserver.cnf -extensions x509_ext -req -days 365 -in apiserver.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out apiserver.crt
Signature ok
subject=CN = kube-apiserver
Getting CA Private Key

위의 명령어로 crt 파일을 생성했으면 그 파일을 %LOCALAPPDATA%\Docker\pki\apiserver.crt 파일로 덮어쓰면 됩니다.

하지만, 이렇게까지 한 후 docker를 재시작해도 여전히 docker 로그 파일(%LOCALAPPDATA%\Docker\log.txt)의 오류 메시지는 반복되고 k8s 구성에 실패합니다.

c:\temp> tail -f %LOCALAPPDATA%\Docker\log.txt
[21:44:23.572][ApiProxy          ][Info   ] msg="cannot get lease for master node: an error on the server (\"\") has prevented the request from succeeding (get leases.coordination.k8s.io docker-desktop)"
[21:44:23.572][GoBackendProcess  ][Info   ] msg="external: POST /events 200 \"DockerDesktopGo\" \"\""




결론을 보면, 현재(2021-03-20 기준) "Docker desktop for Windows"에서는 "Enable Kubernetes"를 설정하려면 "Use the WSL 2 based engine" 옵션을 해제해야 합니다. (혹시, WSL 2 상에서 k8s 구성에 성공하신 분은 덧글 부탁드립니다. ^^)

마지막으로, 아래는 docker desktop for windows와 k8s 구성 관련 디렉터리 목록입니다.

  • %ProgramFiles%\Docker
  • %USERPROFILE%\.docker
  • %USERPROFILE%\.kube
  • %APPDATA%\Docker
  • %APPDATA%\Docker\Docker Desktop
  • %LOCALAPPDATA%\Docker
  • %LOCALAPPDATA%\Docker Desktop Installer




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

[연관 글]






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

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

비밀번호

댓글 작성자
 



2021-04-05 02시35분
특정 Windows 10에서는 WSL 2 + k8s 활성화가 잘 되는데... 그 차이를 모르겠군요. ^^; 아무래도 이런 환경 상의 요인 때문에라도 Docker Desktop for Windows 측의 대응이 빠르지는 않을 듯합니다.
정성태

... 16  17  18  19  20  21  22  23  24  25  26  27  28  29  [30]  ...
NoWriterDateCnt.TitleFile(s)
12884정성태12/20/20216869개발 환경 구성: 620. Windows 10+에서 WMI root/Microsoft/Windows/WindowsUpdate 네임스페이스 제거
12883정성태12/19/20217725오류 유형: 775. uwsgi-plugin-python3 환경에서 "ModuleNotFoundError: No module named 'django'" 오류 발생
12882정성태12/18/20216836개발 환경 구성: 619. Windows Server에서 WSL을 위한 리눅스 배포본을 설치하는 방법
12881정성태12/17/20217336개발 환경 구성: 618. WSL Ubuntu 20.04에서 파이썬을 위한 uwsgi 설치 방법 (2)
12880정성태12/16/20217147VS.NET IDE: 170. Visual Studio에서 .NET Core/5+ 역어셈블 소스코드 확인하는 방법
12879정성태12/16/202113398오류 유형: 774. Windows Server 2022 + docker desktop 설치 시 WSL 2로 선택한 경우 "Failed to deploy distro docker-desktop to ..." 오류 발생
12878정성태12/15/20218469개발 환경 구성: 617. 윈도우 WSL 환경에서 같은 종류의 리눅스를 다중으로 설치하는 방법
12877정성태12/15/20217109스크립트: 36. 파이썬 - pymysql 기본 예제 코드
12876정성태12/14/20216952개발 환경 구성: 616. Custom Sources를 이용한 Azure Monitor Metric 만들기
12875정성태12/13/20216625스크립트: 35. python - time.sleep(...) 호출 시 hang이 걸리는 듯한 문제
12874정성태12/13/20216616오류 유형: 773. shell script 실행 시 "$'\r': command not found" 오류
12873정성태12/12/20217771오류 유형: 772. 리눅스 - PATH에 등록했는데도 "command not found"가 나온다면?
12872정성태12/12/20217581개발 환경 구성: 615. GoLang과 Python 빌드가 모두 가능한 docker 이미지 만들기
12871정성태12/12/20217665오류 유형: 771. docker: Error response from daemon: OCI runtime create failed
12870정성태12/9/20216223개발 환경 구성: 614. 파이썬 - PyPI 패키지 만들기 (4) package_data 옵션
12869정성태12/8/20218513개발 환경 구성: 613. git clone 실행 시 fingerprint 묻는 단계를 생략하는 방법
12868정성태12/7/20217088오류 유형: 770. twine 업로드 시 "HTTPError: 400 Bad Request ..." 오류 [1]
12867정성태12/7/20216755개발 환경 구성: 612. 파이썬 - PyPI 패키지 만들기 (3) entry_points 옵션
12866정성태12/7/202114140오류 유형: 769. "docker build ..." 시 "failed to solve with frontend dockerfile.v0: failed to read dockerfile ..." 오류
12865정성태12/6/20216838개발 환경 구성: 611. 파이썬 - PyPI 패키지 만들기 (2) long_description, cmdclass 옵션
12864정성태12/6/20215288Linux: 46. WSL 환경에서 find 명령을 사용해 파일을 찾는 방법
12863정성태12/4/20217220개발 환경 구성: 610. 파이썬 - PyPI 패키지 만들기
12862정성태12/3/20215933오류 유형: 768. Golang - 빌드 시 "cmd/go: unsupported GOOS/GOARCH pair linux /amd64" 오류
12861정성태12/3/20218154개발 환경 구성: 609. 파이썬 - "Windows embeddable package"로 개발 환경 구성하는 방법
12860정성태12/1/20216275오류 유형: 767. SQL Server - 127.0.0.1로 접속하는 경우 "Access is denied"가 발생한다면?
12859정성태12/1/202112438개발 환경 구성: 608. Hyper-V 가상 머신에 Console 모드로 로그인하는 방법
... 16  17  18  19  20  21  22  23  24  25  26  27  28  29  [30]  ...