최종 사용자 RBAC
Calico the hard way 시리즈의 RBAC 실습 문서예요. 클러스터를 프로덕션에서 운영하기에 적합한 역할 기반 접근 제어(RBAC)를 세팅해요. 네트워크 관리자와 서비스 소유자 두 역할을 만들고, 실제 사용자 인증서를 발급해서 권한이 올바르게 동작하는지 확인해 봐요. 프로덕션 Kubernetes 클러스터의 일반적인 RBAC는 이 실습의 범위를 벗어나요.
출처: 문서
본문
이 실습에서는 클러스터를 프로덕션에서 운영하기에 적합한 역할 기반 접근 제어(RBAC)를 세팅해요. Calico를 사용하기 위한 역할을 다뤄요. 프로덕션 Kubernetes 클러스터를 위한 일반적인 RBAC는 이 실습의 범위를 벗어나요.
calicoctl 사용하기
calicoctl 도구가 버전 불일치 검증(클러스터와 calicoctl의 버전이 같은지 확인)을 수행하려면, 그 도구를 사용하는 사람이 클러스터 수준, 즉 네임스페이스가 아닌 수준에서 clusterinformations에 대한 get 접근 권한이 필요해요. 아래의 network admin 역할은 이미 그런 권한을 갖고 있지만, 뒤에서 만들 service owner 사용자에게는 이 권한을 추가해야 한다는 걸 보게 될 거예요.
kubectl apply -f - <<EOF
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: calicoctl-user
rules:
- apiGroups: ["crd.projectcalico.org"]
resources:
- clusterinformations
verbs:
- get
EOF
네트워크 관리자 (Network admin)
네트워크 관리자는 Calico 네트워크 전체를 구성하고 운영하는 책임을 맡은 사람이에요. 따라서 모든 Calico 커스텀 리소스와, 일부 관련된 Kubernetes 리소스에 접근할 수 있어야 해요.
역할을 만들어요
kubectl apply -f - <<EOF
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: network-admin
rules:
- apiGroups: [""]
resources:
- pods
- nodes
verbs:
- get
- watch
- list
- update
- apiGroups: [""]
resources:
- namespaces
- serviceaccounts
verbs:
- get
- watch
- list
- apiGroups: ["networking.k8s.io"]
resources:
- networkpolicies
verbs: ["*"]
- apiGroups: ["crd.projectcalico.org"]
resources:
- felixconfigurations
- ipamblocks
- blockaffinities
- ipamhandles
- ipamconfigs
- bgppeers
- bgpconfigurations
- ippools
- hostendpoints
- clusterinformations
- globalnetworkpolicies
- globalnetworksets
- networkpolicies
- networksets
verbs: ["*"]
EOF
network admin 역할을 테스트해 보기 위해 Nik이라는 사용자를 만들고 역할을 부여할게요.
Kubernetes 컨트롤 플레인 노드에서 키와 인증서 서명 요청(CSR)을 만들어요. 여기서 subject에 /O=network-admins를 포함하는 점에 주목하세요. 이렇게 하면 Nik이 network-admins 그룹에 속하게 돼요.
openssl req -newkey rsa:4096 \
-keyout nik.key \
-nodes \
-out nik.csr \
-subj "/O=network-admins/CN=nik"
이 인증서를 메인 Kubernetes CA로 서명해요.
sudo openssl x509 -req -in nik.csr \
-CA /etc/kubernetes/pki/ca.crt \
-CAkey /etc/kubernetes/pki/ca.key \
-CAcreateserial \
-out nik.crt \
-days 365
sudo chown $(id -u):$(id -g) nik.crt
다음으로 Nik을 위한 kubeconfig 파일을 만들어요.
APISERVER=$(kubectl config view -o jsonpath='{.clusters[0].cluster.server}')
kubectl config set-cluster kubernetes \
--certificate-authority=/etc/kubernetes/pki/ca.crt \
--embed-certs=true \
--server=$APISERVER \
--kubeconfig=nik.kubeconfig
kubectl config set-credentials nik \
--client-certificate=nik.crt \
--client-key=nik.key \
--embed-certs=true \
--kubeconfig=nik.kubeconfig
kubectl config set-context default \
--cluster=kubernetes \
--user=nik \
--kubeconfig=nik.kubeconfig
kubectl config use-context default --kubeconfig=nik.kubeconfig
역할을 network-admins 그룹에 바인딩해요.
kubectl create clusterrolebinding network-admins --clusterrole=network-admin --group=network-admins
글로벌 네트워크 셋을 만들어서 Nik의 접근 권한을 테스트해요
KUBECONFIG=./nik.kubeconfig calicoctl apply -f - <<EOF
apiVersion: projectcalico.org/v3
kind: GlobalNetworkSet
metadata:
name: niks-set
spec:
nets:
- 110.120.130.0/24
- 210.220.230.0/24
EOF
글로벌 네트워크 셋이 존재하는지 확인해요
KUBECONFIG=./nik.kubeconfig calicoctl get globalnetworkset -o wide
결과
NAME NETS
niks-set 110.120.130.0/24,210.220.230.0/24
글로벌 네트워크 셋을 삭제해요
KUBECONFIG=./nik.kubeconfig calicoctl delete globalnetworkset niks-set
서비스 소유자 (Service owner)
서비스 소유자는 Kubernetes에서 하나 이상의 서비스를 운영하는 책임을 맡은 사람이에요. 자기 서비스를 위한 네트워크 정책을 정의할 수는 있어야 하지만, Calico와 관련된 글로벌 구성을 조회하거나 수정할 필요는 없어요.
역할을 정의해요
kubectl apply -f - <<EOF
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: network-service-owner
rules:
- apiGroups: ["networking.k8s.io"]
resources:
- networkpolicies
verbs: ["*"]
- apiGroups: ["crd.projectcalico.org"]
resources:
- networkpolicies
- networksets
verbs: ["*"]
EOF
service owner 역할을 테스트해 보기 위해 Sam이라는 사용자를 만들고 역할을 부여할게요.
Kubernetes 컨트롤 플레인 노드에서 키와 인증서 서명 요청(CSR)을 만들어요.
openssl req -newkey rsa:4096 \
-keyout sam.key \
-nodes \
-out sam.csr \
-subj "/CN=sam"
이 인증서를 메인 Kubernetes CA로 서명해요.
sudo openssl x509 -req -in sam.csr \
-CA /etc/kubernetes/pki/ca.crt \
-CAkey /etc/kubernetes/pki/ca.key \
-CAcreateserial \
-out sam.crt \
-days 365
sudo chown $(id -u):$(id -g) sam.crt
다음으로 Sam을 위한 kubeconfig 파일을 만들어요.
APISERVER=$(kubectl config view -o jsonpath='{.clusters[0].cluster.server}')
kubectl config set-cluster kubernetes \
--certificate-authority=/etc/kubernetes/pki/ca.crt \
--embed-certs=true \
--server=$APISERVER \
--kubeconfig=sam.kubeconfig
kubectl config set-credentials sam \
--client-certificate=sam.crt \
--client-key=sam.key \
--embed-certs=true \
--kubeconfig=sam.kubeconfig
kubectl config set-context default \
--cluster=kubernetes \
--user=sam \
--kubeconfig=sam.kubeconfig
kubectl config use-context default --kubeconfig=sam.kubeconfig
Sam의 접근을 단일 네임스페이스로 제한할 거예요. 네임스페이스를 만들어요
kubectl create namespace sam
네임스페이스에서 Sam에게 역할을 바인딩해요
kubectl create rolebinding -n sam network-service-owner-sam --clusterrole=network-service-owner --user=sam
그리고 calicoctl을 제대로 사용할 수 있도록 Sam에게 클러스터 수준에서 calicoctl-user 역할도 바인딩해요
kubectl create clusterrolebinding calicoctl-user-sam --clusterrole=calicoctl-user --user=sam
Sam은 글로벌 네트워크 셋 리소스를 만들 수 없어요(network admin인 Nik은 가능하죠)
KUBECONFIG=./sam.kubeconfig calicoctl get globalnetworkset -o wide
결과
connection is unauthorized: globalnetworksets.crd.projectcalico.org is forbidden: User "sam" cannot list resource "globalnetworksets" in API group "crd.projectcalico.org" at the cluster scope
하지만 Sam은 자기 네임스페이스 안에서는 리소스를 만들 수 있어요
KUBECONFIG=./sam.kubeconfig calicoctl apply -f - <<EOF
apiVersion: projectcalico.org/v3
kind: NetworkSet
metadata:
name: sams-set
namespace: sam
spec:
nets:
- 110.120.130.0/24
- 210.220.230.0/24
EOF
리소스가 존재하는지 확인해요
KUBECONFIG=./sam.kubeconfig calicoctl get networksets -n sam
결과
NAMESPACE NAME
sam sams-set
NetworkSet을 삭제해요
KUBECONFIG=./sam.kubeconfig calicoctl delete networkset sams-set -n sam
다음
더 알아보기 (Learn more)
Calico 운영 역할은 네트워크 관리자(클러스터 전역)와 서비스 소유자(네임스페이스 범위)로 나눠 설계해요. calicoctl 버전 검증을 위해 누구든 클러스터 수준 clusterinformations get 권한이 필요하다는 점을 잊지 마세요. 인증서 기반 사용자를 만들어 실제 권한 동작을 확인해 보세요.