Kubernetes 를 설치하면서 고생했던 것이 두 가지가 있습니다.

하나가 방화멱(Firewalld )문제였고, 다른 하나가 바로 DashBoard 입니다.



Kubernetes Dashboard 설치


Dashboard 에서는 모든 일을 할 수 있습니다.

Cluster 를 구성하고, 네임스페이스를 추가하고,, 뭐 다 되죠. kubernetes api 의 ui 버전이니까요.

그런만큼 보안면에서 상당히 까다롭습니다.(그 말은 개고생을 하게 된다는 이야깁니다.)


여러분은 복받으신 겁니다. 제가 깔끔하게 정리해 드립니다 :)




Kubernetes Dashboard 설치



공식 설치 매뉴얼 주소:

https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/



먼저 설치를 해 보겠습니다.

별거 없습니다.


$ kubectl create -f https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommended/kubernetes-dashboard.yaml



간단하게 설치가 되었습니다.

이제 pod 를 살펴보죠


$ kubectl get pods --all-namespaces

NAMESPACE     NAME                                          READY     STATUS    RESTARTS   AGE

kube-system   coredns-78fcdf6894-c6x7x                      1/1       Running   0          30m

kube-system   coredns-78fcdf6894-qf66q                      1/1       Running   0          30m

kube-system   etcd-test-k8s-master-ncl                      1/1       Running   0          19m

kube-system   kube-apiserver-test-k8s-master-ncl            1/1       Running   0          19m

kube-system   kube-controller-manager-test-k8s-master-ncl   1/1       Running   0          19m

kube-system   kube-flannel-ds-fblsn                         1/1       Running   0          20m

kube-system   kube-flannel-ds-z4pml                         1/1       Running   0          12m

kube-system   kube-proxy-258j8                              1/1       Running   0          12m

kube-system   kube-proxy-2grf9                              1/1       Running   0          25m

kube-system   kube-scheduler-test-k8s-master-ncl            1/1       Running   0          19m

kube-system   kubernetes-dashboard-767dc7d4d-hvfmc          1/1       Running   0          41s



마지막에 dashboard 가 정상적으로 설치되고, running 상태인 것을 볼 수 있습니다.

이제 실행하면 되는데,, 홈페이지에서도 볼 수 있듯이 접속 방법에는 크게 3가지가 있습니다.
참고:
https://github.com/kubernetes/dashboard/wiki/Accessing-Dashboard---1.7.X-and-above




첫째. Proxy 를 이용하기




Proxy 는 DashBoard 의 특별한 기능이 아니고 Kubernetes 에서 범용적으로 쓰이는 것입니다.

간략히 설명드리자면, Service API 에 접속하기 위해서는 각종 인증을 통해 가능한데 그 과정을 kubectl 이 proxy 를 제공함으로서 접속 가능하게 해 준다고 보시면 됩니다.


아래처럼 proxy 를 띄웁니다.


kubectl proxy

Starting to serve on 127.0.0.1:8001


오호~ 이제 아래 주소를 통해서 대시보드에 접속할 수 있습니다. :)

http://localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/.



이...씨...ㅂ...

저는 이 모든 작업을 윈도우에서 putty 를 이용해서 작업하고 있습니다.

당연히 localhost 로는 접속할 수 없습니다.


그럼 localhost 가 아니라, 외부에서 접근 가능하도록 proxy 를 다시 실행해 보죠.

10.105.105.11 은 kubelctl proxy 를 수행한 host 의 ip 주소입니다.

포트는 임의 포트


$ kubectl proxy --port=8001 --address=10.105.105.111 --accept-hosts='^*$'


이제 브라우저에서 접속할 수 있는 상태가 되었군요. :)

제 윈도우 PC에서 접속을 시도해 봅니다.


http://10.105.105.111:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/.

이런 형태가 되겠네요.



오~~ 뭔가 뜹니다



SKIP 을 눌러봅니다.




음..로그인을 하지 않아서, 사용을 할 수 없네요.

그럼 로그인하면 되나???


그런데 공식 페이지에 이렇게 되어 있네요?


NOTE: Dashboard should not be exposed publicly using kubectl proxy command as it only allows HTTP connection. For domains other than localhost and 127.0.0.1 it will not be possible to sign in. Nothing will happen after clicking Sign in button on login page.


localhost(127.0.0.1)에서 접속한게 아닌경우, 로그인 기능을 사용할 수 없다고 되어 있습니다. -_-+


어떻게든 사용할 수 있도록 해 봅시다.

무조건 난 이걸 사용하고 말거야!!!



아래 내용을 dashboard-admin 이라는 이름으로 저장합니다.

apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: kubernetes-dashboard
  labels:
    k8s-app: kubernetes-dashboard
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: kubernetes-dashboard
  namespace: kube-system

이제 아래처럼 실행합니다.


$ kubectl create -f dashboard-admin.yaml

clusterrolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created


자 Role 을 추가하였습니다.
이제 다시 Proxy 를 아래처럼 실행합니다.

$ kubectl proxy --port=8001 --address=10.105.105.111 --accept-hosts='^*$'


그리고 DashBoard 에 다시 접속을 하고, Skip 을 누르면,,

http://10.105.105.111:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/.





성공!!!

로그인 하지 않아도, 모든 권한을 갖게 되었습니다 :)


host 의 주소와 포트를 아는 사람이라면, 누구든지 저의 Cluster 를 삭제/변경할 수 있습니다. 

ㅅ..ㅂ.. 이게 뭐야;;



이건 아닌것 같습니다.

그렇다면 다른 방법을 찾아보죠.


롤백은 아래처럼 하시면 됩니다.


kubectl delete -f dashboard-admin.yaml

clusterrolebinding.rbac.authorization.k8s.io "kubernetes-dashboard" deleted








둘째. NodePort 이용하기



아래처럼 kubernetes-dashboard 서비스를 편집합니다.

서비스를 수정하여 Expose 하는 방식을 포트로 바꿔서 외부에서 접속 가능하게 하기 위함입니다.

여기서 말하는 "서비스"는 Kubernetes 에서 사용하는 용어입니다.


type: ClusterIP 라고 되어 있는 부분을 type: NodePort 로 바꿉니다.

$ kubectl -n kube-system edit service kubernetes-dashboar

# Please edit the object below. Lines beginning with a '#' will be ignored, # and an empty file will abort the edit. If an error occurs while saving this file will be # reopened with the relevant failures. # apiVersion: v1 ... name: kubernetes-dashboard namespace: kube-system resourceVersion: "343478" selfLink: /api/v1/namespaces/kube-system/services/kubernetes-dashboard-head uid: 8e48f478-993d-11e7-87e0-901b0e532516 spec: clusterIP: 10.100.124.90 externalTrafficPolicy: Cluster ports: - port: 443 protocol: TCP targetPort: 8443 selector: k8s-app: kubernetes-dashboard sessionAffinity: None type: ClusterIP    # 이 부분의 값(ClusterIP)을 NodePort 로 변경 후, 저장 status: loadBalancer: {}



그리고 아래 명령을 통해서 바인딩된 포트를 확인합니다.


$ kubectl -n kube-system get service kubernetes-dashboard

NAME                   CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE

kubernetes-dashboard   10.100.124.90   <nodes>       443:31707/TCP   21h


이제 https://<master-ip>:31707 로 접속하면 됩니다.

master-ip 는 아래처럼 하면 알 수 있습니다.


$ kubectl cluster-info

Kubernetes master is running at https://10.106.234.130:6443

KubeDNS is running at https://10.106.234.130:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy


To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.




31707 포트에 바인딩 되었으므로, 최종적인 DashBoard 주소는 아래와 같습니다.
https://10.106.234.130:31707/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy



크...접속할 수가 없다...;;
보면 인증서가 없습니다. 접속할 방법이 없습니다.

'고급' 을 눌러서 보면, 위험을 무릎쓰고 계속 진행하겠냐는 그런 선택도 못합니다.
그냥 답이 없습니다.

그럼 마지막...세번째 방법을 써 봅시다.


롤백은 아래처럼 하시면 됩니다.

$ kubectl -n kube-system edit service kubernetes-dashboard


편집모드로 들어간 뒤에, 처음에 수정했던 NodePort 를 ClusterIP 로 되돌려 놓습니다.

그리고 그 윗부분 Ports 부분에 nodePort: 31707 이라는 부분이 추가된 게 있습니다. 그것도 함께 지워줍니다.

그래야 정상적으로 파일이 저장됩니다.






셋째. API Server 이용하기



참고 주소:

https://github.com/kubernetes/dashboard/wiki/Accessing-Dashboard---1.7.X-and-above#api-server


간단하게 설명 되어 있습니다.


https://<master-ip>:<apiserver-port>/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/


를 하면 된다고 하네요?

apiserver-port 는 kubectl cluster-info 를 통해 알 수 있지요.

접속해 볼까요?


https://10.106.234.130:6443/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/


{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {
    
  },
  "status": "Failure",
  "message": "Unauthorized",
  "reason": "Unauthorized",
  "code": 401 

}


흠.. 영 좋지 안습니다.

인증서 문제인것 같습니다.


자! 인증서를 만들어 봅시다.

home 에 가서 .kube/config 가 잘 있는지 확인하고.


$ grep 'client-certificate-data' ~/.kube/config | head -n 1 | awk '{print $2}' | base64 -d >> kubecfg.crt

$ grep 'client-key-data' ~/.kube/config | head -n 1 | awk '{print $2}' | base64 -d >> kubecfg.key

$ openssl pkcs12 -export -clcerts -inkey kubecfg.key -in kubecfg.crt -out kubecfg.p12 -name "kubernetes-admin"


비밀번호를 입력하라고 나오면, 적당히 입력합니다. 단 기억해 둡니다.

이제 디렉토리를 보면, kubecfg.p21 이라는 파일이 만들어져 있을 것입니다.


그리고 아래 위치에 파일들을 보면, ca.crt 라고 CA 인증서가 있습니다.


$ ls -alF /etc/kubernetes/pki/

total 60

drwxr-xr-x 3 root root 4096 Sep  3 19:19 ./

drwxr-xr-x 4 root root  119 Sep  3 19:19 ../

-rw-r--r-- 1 root root 1237 Sep  3 19:19 apiserver.crt

-rw-r--r-- 1 root root 1094 Sep  3 19:19 apiserver-etcd-client.crt

-rw------- 1 root root 1679 Sep  3 19:19 apiserver-etcd-client.key

-rw------- 1 root root 1679 Sep  3 19:19 apiserver.key

-rw-r--r-- 1 root root 1099 Sep  3 19:19 apiserver-kubelet-client.crt

-rw------- 1 root root 1679 Sep  3 19:19 apiserver-kubelet-client.key

-rw-r--r-- 1 root root 1025 Sep  3 19:19 ca.crt

-rw------- 1 root root 1679 Sep  3 19:19 ca.key

drwxr-xr-x 2 root root  154 Sep  3 19:19 etcd/

-rw-r--r-- 1 root root 1025 Sep  3 19:19 front-proxy-ca.crt

-rw------- 1 root root 1675 Sep  3 19:19 front-proxy-ca.key

-rw-r--r-- 1 root root 1050 Sep  3 19:19 front-proxy-client.crt

-rw------- 1 root root 1679 Sep  3 19:19 front-proxy-client.key

-rw------- 1 root root 1675 Sep  3 19:19 sa.key

-rw------- 1 root root  451 Sep  3 19:19 sa.pub


이 ca.crt 와 앞에서 만든 kubecfg.p12 파일이 핵심입니다.

두개의 파일을 Dashboard 를 사용할 호스트로 복사해 옵니다.


여기서 호스트의 환경에서 따라서 방법이 다르니, 잘 따라오시기 바랍니다.






Windows


[인터넷 익스플로러, 크롬, 엣지 브라우저 등에서 사용하기 위한 설정]


D:\> certutil.exe -addstore "Root" path\to\ca.crt

Root

서명이 공개 키와 일치합니다.

"CN=kubernetes" 인증서가 저장소에 추가되었습니다.

CertUtil: -addstore 명령이 성공적으로 완료되었습니다.


위와 같이 ca.crt 를 찾아서 등록해 줍니다.

kubecfg.p12 도 추가해 줍니다.


D:\> certutil.exe -p {password} -user -importPFX path\to\kubecfg.p12


실행하면 아래처럼 인증서 등록을 위한 창이 뜹니다.


등록을 해 줍니다.


이제 모든 브라우저를 끕니다. 브라우저 전체를 재시작해야 적용이 되기 때문입니다.



[Firefox 를 위한 설정]


Firefox 는 윈도우의 인증서 저장소를 사용하지 않고, 자체적인 인증서 저장소를 사용합니다.

Firefox 의 "도구->옵션->고급->인증서->인증서 보기->인증서 추가" 에서 위의 ca.crt 와 kubecfg.p12 를 등록해 주시면 됩니다.







Linux


[크롬 브라우저 등에서 사용하기 위한 설정]


먼저 $HOME 에 .pki/nssdb 폴더가 있는지 확인합니다.

그리고 인증서 등록을 위해서 certutil 과 pk12util 이 설치되어 있는지도 확인합니다.

없다면, apt-get 이나 yum 을 통해 먼저 설치를 합니다.


이제 모든 브라우저를 닫습니다.

그리고 ca 파일을 설치합니다.


$ certutil -A \

  -n "Kubernetes" \

  -t "TC,," \

  -d sql:$HOME/.pki/nssdb \

  -i path/to/ca.crt


이제 kubecfg.12 파일도 추가해 줍니다.

$ pk12util -i path/to/kubecfg.p12 \

  -d sql:$HOME/.pki/nssdb \

  -W {password}


{password} 부분에는 p12 파일을 만들때, 입력했던 비밀번호를 넣어 줍니다.



[Firefox 를 위한 설정]


Firefox 는 윈도우의 인증서 저장소를 사용하지 않고, 자체적인 인증서 저장소를 사용합니다.

먼저 Firefox 의 실제 주소를 알아옵니다.


$ find ~/.mozilla/firefox -name "cert8.db"|xargs dirname


그리고 인증서 등록을 위해서 certutil 과 pk12util 이 설치되어 있는지도 확인합니다.

없다면, apt-get 이나 yum 을 통해 먼저 설치를 합니다.


이제 모든 브라우저를 닫습니다.

그리고 ca 파일을 설치합니다.

-d 에는 위에서 구한 firefox 의 실제 주소를 넣습니다.


$ certutil -A \

  -n "Kubernetes" \

  -t "TC,," \

  -d ~/.mozilla/firefox/8kazf4ob.default \

  -i path/to/ca.crt


kubecfg.p12 도 마저 등록해 줍니다.


$ pk12util -i path/to/kubecfg.p12 \

  -d ~/.mozilla/firefox/8kazf4ob.default \

  -W {password}







Mac OS


[크롬, 사파리 브라우저 등에서 사용하기 위한 설정]



다음과 같이 ca.crt 를 추가해 줍니다.


$ security add-trusted-cert \

  -r trustRoot \

  -k "$HOME/Library/Keychains/login.keychain" \

  path/to/ca.crt



kubecfg.p12 도 추가해 줍니다.

$ security import \

  path/to/kubecfg.p12 \

  -k "$HOME/Library/Keychains/login.keychain" \

  -P {password}



[Firefox 를 위한 설정]


Firefox 는 자체적인 인증서 저장소를 사용합니다.

Firefox 의 "도구->옵션->고급->인증서->인증서 보기->인증서 추가" 에서 위의 ca.crt 와 kubecfg.p12 를 등록해 주시면 됩니다.








이렇게 모든 인증서를 설치하고난 뒤, 브라우저를 모두 종료시킵니다.

그리고나서 DashBoard 주소에 접속해 봅니다.



https://10.106.234.123:6443/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/



크롬의 경우, 요렇게 인증서를 추가하겠냐는 창이 뜹니다. 추가합니다 :)

그러고나면,




이렇게 창이 뜹니다.

주소창을 보면, 인증서가 정상적으로 동작하고 있는 것을 알 수 있습니다 :)




이제 Token 을 이용해서 접속해 보죠.

먼저 service 계정을 만들고~


cat <<EOF | kubectl create -f -

apiVersion: v1

kind: ServiceAccount

metadata:

  name: admin-user

  namespace: kube-system

EOF



ClusterRoleBinding  만들어 줍니다

cat <<EOF | kubectl create -f -

apiVersion: rbac.authorization.k8s.io/v1

kind: ClusterRoleBinding

metadata:

  name: admin-user

roleRef:

  apiGroup: rbac.authorization.k8s.io

  kind: ClusterRole

  name: cluster-admin

subjects:

- kind: ServiceAccount

  name: admin-user

  namespace: kube-system

EOF



마지막으로 방금 추가한 사용자 계정의 토큰을 가져옵니다.

$ kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}')


그러고나면 주저리주저리 나오고, 마지막 부분에 token 이 나옵니다.

이 값을 복사합니다. 대략 아래와 같은 형태입니다.


token:      eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi11c2VyLXRva2VuLWRnazc4Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImFkbWluLXVzZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiIwOGMxNGE1YS1hZjZmLTExZTgtYmIwM15sfMmIxYWQ3YzNhZjYiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06YWRtaW4tdXNlciJ9.h8OZCBUjYlbyrvBSf91yq8abNn0D6lhRspzuBPOtpLJbqORWRpwAvvae9rSjYjnkg9ETWu4LE4InxBBp7Onx7CUYXQUMmnfC-5uk6GT6ZG9hr-KBsF8ggEfqsBQYQIHe40KDFW2j4BKjXSDYhBhNUUpkJ9sY0YBGRXL1vrgRKlO2rdj7dnmOsGSxiNeLVGYXvFJd6qJJAxVX1XfYxQvmO5suCK_O4vnkJehLMAVC2Ndj9oTAKveUrzwjyjiS54fqj2ZYoPrQ8mJZz2rQD4iAlr5iheKPUux6tnjRxtqRgb9-Oly_j30uxmKu0-X_eJBNa2YAzLbZxnbX6T1AcNV6NQ





짜잔~ 로그인 되었습니다 :)