API server에 요청을 하는 client를 authenticate, authorizate하는 기능을 하는 플러그인을 이용해 인증단계를 거칠 수 있다.
API server가 요청을 받으면, ㅇ니증 플러그인 목록의 각각에게 요청을 전달해서 신원을 확인한다.
Username, ID, Group 정보를 return 받은 후 승인 단계로 넘어간다. Client의 정보를 API server가 저장하지는 않음
Request를 받는 K8S API server 입장에서 client는 크게 2가지로 구분된다.
Pods는 ServiceAccount라는 방식을 이용해서 API server에 접근하며, 이는 cluster 내에 service account resource를 생성하고 저장해서 pod는 이를 통해 API server로 통신하는 방식이다.
User나 Service Account는 하나 이상의 group에 속할 수 있고, group마다 권한을 부여할 수 있다.
Note) Built-in groups
System built group은 조금 특별한 의미를 가지고 있는데
system:unauthenticated
: 여러개의 플러그인들 중 어떤 것도 이 request의 client를 식별할 수 없을 때 system:unauthenticated group으로 포함됨system:authenticated
: 성공적으로 client가 식별되었을 때 이 그룹으로 편성됨system:serviceaccounts
: system의 모든 service account 포함system:serviceaccounts:<namespace>
: specific namespace에 포함되는 service account가 이 그룹으로 편성됨Service account는 pod가 API server와 통신할 때 식별자 역할을 한다.
Token file은 service account의 인증 토큰을 갖고 있으며, pod 토큰을 이용한 인증과정은 아래! 👇
1. Pod가 토큰을 가지고 API server에 연결 요청
2. API server의 인증 플러그인이 service account를 인증
3. Service account의 사용자 이름을 API server core로 다시 전달
(Service acoount의 사용자 이름은 `System: serviceaccount::과 같이 구성된다)
4. API server는 이 사용자 이름을 승인 플러그인으로 전달하고, 해당 pod의 application이 수행하려고 하는 동작이 service-account에 의해 허가되는지 여부를 결정한다.
Resource
로 취급됨
$ kubectl create serviceaccount foo -n chapter12
serviceaccount "foo" created
$ kubectl get sa -n chapter12
NAME SECRETS AGE
default 1 26s
foo 1 8s
$ kubectl describe sa foo -n chapter12
Name:
Namespace:
Labels:
Annotations:
Image pull secrets: <none>
Mountable secrets: foo-token-72z4h
Tokens: foo-token-72z4h
events: <none>
Service account를 생성하면, custom token secret이 만드ㄹ어지고, 이게 service account와 연결되는 부분을 볼 수 있다.(foo-token-72z4h
) 참고로 service account에서 사용되는 인증 토큰은 JWT (JSON Web Token) 방식.
생성한 foo라는 service account를 사용해 pod를 배포해보면
apiVersion: v1
kind: Pod
metadata:
name: curl-custom-sa
namespace: chapter12
spec:
serviceAccountName: foo. ### 여기
containers:
- name: main
image: tutum/curl
command: ['sleep', '999999']
- name: ambassador
image: luksa/kubectl-proxy:1.6.2
이 service account를 가지고 API server로 통신해보면
$ kubectl exec -it curl-custom-sa -c main curl localhost:8001/api/v1
/pods -n chapter12
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {
},
"status": "Failure",
"message": "pods is forbidden: User \"system:serviceaccount:chapter12:
foo\" cannot list resource \"pods\" in API group \"\" at the cluster
scope",
"reason": "Forbidden",
"details": {
"kind": "pods"
},
"code": 403 }
403 권한 에러로 통신이 불가능하다😿
그럼 이 service account에 권한을 부여해주려면 어떻게 해야할까? ➡️ RBAC plugin을 이용함.
K8S는 RBAC 승인 플러그인을 통해 권한을 제어하고, 이 RBAC resource를 통해서 클러스터에 대한 접근을 관리하면서 API Server securing을 한다고 볼 수 있다.
API server는 REST interface를 노출하므로, 사용자는 HTTP 요청을 통해 server로 작업을 요청하는데, 이 때 사용자는 자격증명 (인증 토큰, 사용자 이름, 암호.. 등등) 을 통해 인증한다.
이 때 Authorization plugin을 통해 사용자의 요청이 수행 가능한지 여부를 확인한다.
Kubernetes에서 취할 수 있는 actions에는
이 RBAC Rule은 pod, service, secret과 같은 resource 유형에도 적용할 수 있고, resource의 특정 instance에도 적용 가능하다.
RBAC Authorization Rule은 4가지 resource로 구성되며, 크게 2가지로 그룹화된다.
-Roles
/ ClusterRoles
: 특정 resource에 대한 허가 여부를 지정
RoleBinding
/ ClusterRoleBinding
: Role에 정의된 내용을 User 나 User group에 지정 (bond해줌!)(==같은 namespace의 resource들에만 적용 가능)
‼️미션
- namespace `cloudswu` 에서 pod를 get / list 할 수 있도록 허용하는 service-reader라는 role을 만들어보자!
————-
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: cloudswu
name: service-reader
rules:
- apiGroups: [""]
verbs: ["get", "list"]
resources: ["pods"]
$ kubectl create -f service-reader.yaml -n cloudswu
YAML파일 생성이 귀찮다면 CLI로도 가능하다
$ kubectl create role <role_name> —verb=get —verb=list —resource=pod -n cloudswu
Role을 serviceAccount에 binding한다
$ kubectl create rolebinding <rb_name> —role=<role_name> —serviceaccount=<sa_name> -n foo
‼️미션
- persistvolume을 get / list 할 수 있도록 허용하는 pv-reader 라는 role을 만들어보자!
———
$ kubectl create clusterrole pv-reader --verb=get,list --
resource=persistentvolumes
clusterrole.rbac.authorization.k8s.io "pv-reader" created
여기에 clusterRoleBinding을 생성한다
$ kubectl create clusterrolebinding <pv-test-rolebinding> --clusterrole=pv-reader --
serviceaccount=<sa_name>:default
clusterrolebinding.rbac.authorization.k8s.io "pv-test" created
이 serviceAccount가 binding된 pod에 직접 접속해서 persistent volume을 조회하면 조회가능하다.
Cluster-role도 namespace마다 분리되는 role-binding이 가능하다.
Kubernetes API server가 시작될 때 제공되는 기본 ClusterRole과 ClusterRoleBinding이 있으며 이 중 view, edit, admin, cluster-admin이 중요하다
그밖의 Default Cluster Role은 system:
접두사 로 시작하는 룰이 있는데 이는 각 특성에 맞춰서 다양한 K8S 구성 요소를 제어하기 위해 사용된다.
Ex. Namespace “cloud” 안에 읽기권한만 필요한 Pod A가 있고, 수정 권한이 필요한 다른 pod B가 있다.
이럴 때 serviceAccount를 어떻게 지정해야할까?