ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 쿠버네티스 인증(Authentication)
    Kubernetes 2018. 8. 13. 09:00
    반응형
    사용자가 쿠버네티스의 API에 접근하기 위해서는 인증(Authentication)을 거쳐야 합니다. apiserver는 테스트 목적으로 로컬호스트의 8080포트에 http 포트를 띄웁니다. 외부에서 접근할 수 있는 기본포트는 6443인데 TLS인증이 적용되어 있습니다. 일반적인 https인증은 접근하는 클라이언트에서는 인증서가 필요없지만, 쿠버네티스의 apiserver에 열려 있는 이 포트에 접근하기위해서는 apiserver에서 가지고 있는 인증서에서 검증 가능한 유효한 인증서를 가지고 접근해야 통신이 가능합니다. 인증되지 않은 클라이언트가 외부에서 apiserver에 접근하는 것을 막기 위해서 입니다.
    쿠버네티스에서 인증을 요청하기 위한 사용자는 일반적인 사용자와 서비스어카운트(service account)  2가지 종류가 있습니다. 쿠버네티스에는 사용자에 대한 정보가 저장되지 않습니다. 외부의 별도 인증 시스템에 있는 사용자 정보들을 사용하도록 되어 있습니다. 구글 계정(Google Account)이나 오픈스택의 키스톤(keystone), LDAP 등의 인증 시스템과 연동이 가능하고 별도 인증 시스템이 없다면 단순하게 파일에 유저명과 비밀번호를 저장해두고 사용하는 것도 가능합니다.
    서비스어카운트는 쿠버네티스가 직접 관리하는 사용자 계정입니다. 서비스어카운트에는 시크릿(secret)이 할당되어서 해당 서비스어카운트에 대한 비밀번호 역할을 해줍니다. 


    인증 방법
    쿠버네티스에서 인증을 하는 방법은 여러가지가 있습니다. 여기서는 그 중에서 많이 사용하는 일반적인 방법들에 대해서 알아보도록 하겠습니다. 보다 자세한 방법은 https://kubernetes.io/docs/reference/access-authn-authz/authentication/ 에서 확인할 수 있습니다.

    인증서를 이용한 인증
    쿠버네티스는 apiserver와 통신하기 위해서 사용하는 기본 인증 방법으로 TLS(Transport Layer Security)인증을 사용합니다. TLS는 통신할때의 오고가는 패킷을 암호화하는 일반적인 방법입니다. 보통 HTTPS용 웹서버를 설정할때 보면 서버측에만 인증서를 설정하면 보안통신이 가능합니다. 하지만 TLS 인증은 서버 뿐만이 아니라 클라이언트가 유효한지를 검증하는 기능도 가지고 있습니다. 그러기 위해서 apiserver쪽에는 있는 인증서와 매치되는 클라이언트 인증서를 가지고 접속을 시도하면 됩니다. 그동안 kubectl을 설치한 후에 별다른 문제 없이 명령어들을 사용해 왔는데요. 이미 kubectl설정에 이 인증서가 들어 있기 때문에 가능한 거였습니다. 인증서가 들어 있는건 ~/.kube/config 파일을 내용을 확인해 보면 됩니다. kubectl config 명령으로 이 파일의 내용을 설정하거나 조회 가능하지만 여기서는 직접 파일을 열어서 확인해 보겠습니다.
    다음과 같은 내용을 확인해 볼 수 있습니다. 
    apiVersion: v1
    clusters:
    - cluster:
        insecure-skip-tls-verify: true
        server: https://localhost:6443
      name: docker-for-desktop-cluster
    contexts:
    - context:
        cluster: docker-for-desktop-cluster
        user: docker-for-desktop
      name: docker-for-desktop
    current-context: docker-for-desktop
    kind: Config
    preferences: {}
    users:
    - name: docker-for-desktop
      user:
        client-certificate-data: LS0tLS1CRUdJTiBDRVJUS….
        client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJ...
    다른 설정들과 마찬가지로 apiVersion이 제일 처음에 옵니다. 그 다음에 clusters가 오고 cluster관련 설정이 옵니다. cluster설정은 여기서는 1개만 있지만 여러개가 올 수도 있습니다. cluster설정에는 클러스터 이름을 나타내는 name과 접속 주소를 나타내는 server가 있습니다. 여기서는 로컬에 설치된 docker for desktop용 쿠버네티스에 접속하기 때문에 https://localhost:6443를 주소로 가지는걸 확인할 수 있습니다. 외부에 있는 쿠버네티스에 접근하려면 여기 있는 주소를 외부 쿠버네티스의 apiserver주소로 변경해 주면 됩니다. insecure-skip-tls-verify옵션은 인증서에 대한 내용입니다. 일반적으로 웹서버에 대한 TLS인증서를 설정할때는 공신력 있는 기관에서 발급한 인증서를 발급해서 사용합니다. 그러면 브라우저에서 접근할때 이 인증서가 공인기관에서 발급한 인증서인지를 확인해서 맞다면 정상적으로 접근가능하게 합니다. 하지만 인증서는 그런 공인기관이 아니더라도 openssl등의 오픈소스 라이브러리를 이용해서 직접 생성해서 사용할 수도 있습니다. 그런 인증서를 사설 인증서라고 하고 공인기관에서 검수받지 않았기 때문에 브라우저에서는 위험한 인증서라고 표시를 해줍니다. 쿠버네티스에서 apiserver과 kubectl이 통신할때는 외부에 공개하는 서버가 아니라 굳이 공인기관에서 인증받은 인증서가 필요하지 않기 때문에 사설 인증서를 만들어서 사용하는 일이 많습니다. 이 때, 인증서가 공인기관의 인증서인지 검증하는 과정을 건너뛰는 옵션이  insecure-skip-tls-verify 옵션입니다. 여기서는 true로 줬습니다.
    cluster 다음에는 하단의 Users를 보겠습니다. 여러명의 user를 명시해 두고 사용하는 것이 가능합니다. 여기서는 TLS인증을 사용하는 유저이기 때문에 client-certificate-data와 client-key-data를 사용합니다. 실제로는 더 긴 문자열이 오지만 여기서는 생략 시켰습니다.
    contexts 부분을 보면 context는 실제로 어떤 cluster에 접근하기위해 필요한 user가 누구인지를 연결해 주고 있습니다. 그리고 여기에는 생략되어 있지만 context에는 namespace까지 지정할 수 있어서 default 네임스페이스가 아닌 특정 네임스페이스에 대한 작업을 편하게 할 수도 있게 해줍니다.
    마지막으로 current-context를 보면 설정에 있는 여러가지의 컨텍스트 중에서 현재 어떤 컨텍스트를 사용해서 클러스터에 접근할지를 결정하게 됩니다. ~/.kube/config 파일의 내용을 직접 편집해도 되고 kubectl config set-context를 이용해서 컨텍스트를 변경하면서 다양한 클러스터에 다양한 유저로 접근해서 사용하는 것이 가능합니다.

    서비스 어카운트(serviceaccount) 토큰을 이용한 인증
    앞의 설정파일에서 유저 부분을 TLS인증서가 아니라 서비스어카운트를 이용하도록 변경해 보겠습니다. 먼저 현재 있는 서비스어카운트를 확인해 봅니다.
    kubectl get serviceaccount

    기본 서비스어카운트인 default를 볼 수 있습니다. default에 연결된 시크릿을 확인하기 위해서 default의 상세한 정보를 확인합니다.
    $ kubectl get serviceaccount default -o yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      creationTimestamp: 2018-07-31T01:17:04Z
      name: default
      namespace: default
      resourceVersion: "303"
      selfLink: /api/v1/namespaces/default/serviceaccounts/default
      uid: 6f166b10-945f-11e8-84cf-025000000001
    secrets:
    - name: default-token-qll9j

    default-token-qll9j 시크릿을 확인할 수 있습니다. 이 시크릿의 상세내용을 확인해 보겠습니다.
    $ kubectl describe secret default-token-qll9j
    Name:         default-token-qll9j
    Namespace:    default
    Labels:       <none>
    Annotations:  kubernetes.io/service-account.name=default
                  kubernetes.io/service-account.uid=6f166b10-945f-11e8-84cf-025000000001

    Type:  kubernetes.io/service-account-token

    Data
    ====
    token:      eyJhbGciOiJSUzI1NiI...
    ca.crt:     1025 bytes
    namespace:  7 bytes


    ca.crt 로 인증서 정보도 보이고 token으로 토큰 정보도 보입니다. 이번에는 token을 이용해보려고 합니다. 이 token정보를 이용해서 ~/.kube/config파일에 user정보를 추가해 보겠습니다.
    users하위에 default에 대한 내용을 추가해 줍니다. token에는 앞에서 확인한 토큰 정보를 넣습니다.
    - name: default
      user:
        token: eyJhbGciOiJSU...

    그리고 context에서 user를 docker-for-desktop에서 default으로 변경해 줍니다.
    이제 kubectl get pods 로 pod 내역을 확인해 보겠습니다. 
    $ kubectl get pods --v=7
    I0811 16:15:29.705455   93703 loader.go:357] Config loaded from file /Users/wonchon/.kube/config
    I0811 16:15:29.723357   93703 round_trippers.go:383] GET https://localhost:6443/api/v1/namespaces/default/pods?limit=500
    I0811 16:15:29.723384   93703 round_trippers.go:390] Request Headers:
    I0811 16:15:29.723394   93703 round_trippers.go:393]     Accept: application/json
    I0811 16:15:29.723403   93703 round_trippers.go:393]     User-Agent: kubectl/v1.10.3 (darwin/amd64) kubernetes/2bba012
    I0811 16:15:29.723429   93703 round_trippers.go:393]     Authorization: Bearer eyJhbGciOiJSUzI1...
    I0811 16:15:29.780180   93703 round_trippers.go:408] Response Status: 200 OK in 56 milliseconds
    I0811 16:15:29.781268   93703 round_trippers.go:383] GET https://localhost:6443/openapi/v2
    I0811 16:15:29.781286   93703 round_trippers.go:390] Request Headers:
    I0811 16:15:29.781296   93703 round_trippers.go:393]     Accept: application/com.github.proto-openapi.spec.v2@v1.0+protobuf
    I0811 16:15:29.781307   93703 round_trippers.go:393]     User-Agent: kubectl/v1.10.3 (darwin/amd64) kubernetes/2bba012
    I0811 16:15:29.781317   93703 round_trippers.go:393]     Authorization: Bearer eyJhbGciOiJSUzI1...
    I0811 16:15:29.793966   93703 round_trippers.go:408] Response Status: 200 OK in 12 milliseconds
    NAME                                    READY     STATUS    RESTARTS   AGE
    kubernetes-simple-app-649f755f6-xkbxs   1/1       Running   0          5d

    kubectl이 요청할때 방금 변경한 계정정보를 이용하는지 확인하기 위해서 --v=7이라는 옵션을 줘서 디버그용 내용을 출력하도록 했습니다. 보면 Authorization 부분에 앞에서 입력했던 토큰을 이용해서 요청한걸 확인할 수 있습니다. 마지막에는 포드내역이 정상적으로 조회되는걸 확인할 수 있습니다. 만약 정보를 잘못넣어서 인증이 실패했다면 다음처럼 인증이 실패했다는 메세지를 확인할 수 있습니다.
    I0811 16:19:00.712768   93752 helpers.go:201] server response object: [{
      "kind": "Status",
      "apiVersion": "v1",
      "metadata": {},
      "status": "Failure",
      "message": "Unauthorized",
      "reason": "Unauthorized",
      "code": 401
    }]
    F0811 16:19:00.712803   93752 helpers.go:119] error: You must be logged in to the server (Unauthorized)



    반응형

    댓글

Designed by Tistory.