멀티 클러스터와 많은 서버가 구축되어 있을수록 사용자 접근에 대한 관리가 더욱 어려워집니다. 이에 대하여 효율적인 관리를 위해 Access Management로 Teleport를 사용하기 위해 테스트한 내용을 기록합니다. Teleport는 안정적으로 Infrastructure에 접근하도록 관리해 주는 설루션입니다. Teleport를 이용하여 SSO 인증이나 Two factor 인증을 통해 SSH로 접속하기 위한 Node(서버), Kubernetes Cluster, Database, Web application 등을 관리하며 해당 리소스에 접근할 수 있습니다.
1.Teleport Component
- Teleport Auth Service: 클러스터 인증기관, 리소스에 접근하기 위해 클라이언트에게 인증서 발급 및 인증절차 수행, 인증 과정에 대한 audit log 수집 및 저장합니다.
- Teleport Proxy Service: Auth Service의 인증을 전달받은 유저의 요청 처리, 인프라스터럭쳐의 특정 자원에 접근이 가능한 Teleport 인스턴스와 통신하는 역할을 지원합니다. Publice Network에서 Teleport 클러스터에 접근하기 위해 Proxy Service를 저장해야 합니다.
- Teleport Application Service: 인증된 유저를 쿠버네티스 대시보드에 접근 허용
Teleport는 일반적으로 많이 사용하는 X.509 인증방식을 사용하는데 자체적으로 CA(Auth service)를 구축해 인증서를 클라이언트에 발급합니다. 일반적인 인증서보다 짧은 기한의 Short-Lived Certifiacte를 사용하여 resource에 대한 인증 절차를 진행합니다(SSH 인증의 경우 OpenSSH 사용)
인가 절차의 경우 User와 Role 통해 관리하는데 Teleport에서는 다음과 같이 User 구분합니다.
- Local User: Teleport를 통해 생성된 유저로 ID/PW, MFA를 통해 인증
- External user : Teleport가 아닌 SSO 프로토콜을 사용해 3rd-party로 통합된 User, Github만 기본적으로 제공되고 OIDC, SAML은 Enterprise 형태로 제공
Teleport를 사용하기 위한 세 가지 CLI 종류가 있습니다.
- teleport : Teleport Serivce 데몬에 과 통신하는 CLI ( status, configure 등)
- tsh: teleport를 사용하는 end user가 사용하는 CLI (kube ls, kube login 등)
- tctl: 관리자가 클러스터를 관리하기 위해 필요한 리소스를 관리할 때 사용 ( node, user, token 등)
2. Teleport Cluster 설치
작업환경은 EKS로 Worker 1개의 소규모 클러스터를 구성해 텔레포트 클러스터로 사용합니다. 이후 해당 클러스터에 접근하기 위한 Ubuntu 20.04 서버에서 작업하였습니다 Prerequest로 Helm과 kubectl을 설치하였습니다.
2-1. Teleport Cluster를 생성하기 위한 Kubernetes cluster 생성
teleport-cluster용 쿠버네티스를 따로 설치해서 텔레포트를 배포합니다. 일반적으로 서버에서 Agent로 설치하여 데몬으로 사용할 수 있으나 텔레포트 클러스터를 구성하여 사용하는 방법을 권장합니다. 기존에 사용하는 클러스로 사용해도 문제가 없을 거라 생각되지만 권장 방식을 따라 하며 클러스터를 따로 분리하였습니다. 주의할 점은 쿠버네티스 서비스 타입인 Loadbalancer를 사용하기 때문에 쿠버네티스 Cloud Provider를 사용하거나 Bear metal에서 구성한 경우 Metal LB 등의 설치가 필요할 거 같습니다.
eksctl create cluster --name=eks-cluster-teleport-demo --nodes=1 --region=ap-northeast-2
2-2. Teleport Install
eks를 통해 쿠버네티스를 구성하게 되면 helm을 통해 teleport를 배포합니다. helm install 명령어에서 clusterName은 향후 텔레포트 대시보드의 DNS로 매핑돼야 하기 때문에 유요한 이름을 작성합니다. Email 또한 유효한 메일 주소를 작성합니다.
helm repo add teleport https://charts.releases.teleport.dev
helm install teleport-cluster teleport/teleport-cluster --create-namespace --namespace=teleport-cluster \
--set clusterName=k8s-teleport-demo.matilda-mzc.com --set acme=true --set acmeEmail=seokbin@mz.co.kr
정상적으로 배포가 완료되면 teleport-cluster 네임스페이스에 파드가 정상적으로 설치되고 서비스에 Loadbalancer가 올라온 것을 확인할 수 있습니다.
kubectl config set-context --current --namespace=teleport-cluster
2-3. Teleport DNS 연결
생성된 로드밸런서를 DNS에 연결합니다. 사용하고 있는 DNS의 레코드를 다음과 같이 CNAME으로 LoadBalancer의 External IP를 추가합니다. 최종적으로 접속하는 DNS가 이전 teleport-cluster 설치 시 파라미터로 설정한 clusterName과 일치하게 됩니다.
)
nslookup으로 조회 시 DNS 가 정상적으로 등록된 것을 확인할 수 있습니다.
이후 webapi를 통해 ping을 전송해 정상적으로 동작하는지 확인합니다.
정상적으로 동작되면 Teleport가 정상적으로 설치되었습니다. 등록한 도메인으로 접속 시 Telport UI를 확인할 수 있습니다. 이후 텔레포트를 통해 관리할 Kubernetes와 서버를 등록하고 접속을 위한 User를 생성합니다.
3. Kubernetes 등록 및 User 생성
3-1. Teleport Role, User 생성
role 생성을 위한 yaml 작성 후 teleport pod에서 적용합니다. teleport를 클러스터를 통해 생성하였기 때문에 파드에 접속하여 role과 User를 생성해야 합니다.
#member.yaml
kind: role
version: v5
metadata:
name: member
spec:
allow:
#kubernetes에 default로 존재하는 group / Linux의 sudo 권한의 역할
kubernetes_groups: ["system:masters"]
kubernetes_labels:
'*': '*'
POD=$(kubectl get pod -l app=teleport-cluster -o jsonpath='{.items[0].metadata.name}')
#role 생성
kubectl exec -i ${POD?} -- tctl create -f < member.yaml
#User 생성
kubectl exec -ti ${POD?} -- tctl users add seokbin2 --roles=member
User 생성 시 아래와 같이 생성된 user를 설정하는 링크(1시간 동안 유효)가 생성됩니다. 해당 링크로 들어가서 패스워드와 OTP를 설정합니다.
)
비밀번호 설정 후 OTP를 설정하는 QR코드가 제공됩니다. Mobile Googlue Auth 앱에 등록한 후 코드를 입력해 설정합니다.
현재 teleport에 등록된 k8s-teleport-demo.matilda-mzc.com
이름의 teleport 클러스터입니다. role 파일에서 kubernetes_label
을 전체로 설정하여 모든 클러스터에 대한 접근 권한을 부여했습니다. 이후 Teleport 대시보드에 접속해 Kubernetes 항목에서 설정된 클러스터를 확인할 수 있습니다.
3-2. Kubernetes 접근하기
생성된 계정을 통해 Kubernetes에 접속할 수 있는지 확인하기 위해 Kubernetes가 설치되어있지 않은 서버에서 테스트를 진행합니다. 쿠버네티스에 접근하기 위해 Kubectl와 tsh 설치를 먼저 설치합니다.
#tsh 설치
curl -L -O https://get.gravitational.com/teleport-v10.0.2-linux-amd64-bin.tar.gz
tar -xzf teleport-v10.0.2-linux-amd64-bin.tar.gz
sudo mv teleport/tsh /usr/local/bin/tsh
sudo mv teleport/tctl /usr/local/bin/tctl
대시보드의 Kubernetes 탭에서 클러스터의 Connect
버튼을 선택 시 다음과 같이 명령어가 출력됩니다.
위의 방법으로 로그인이 안될 시 다음과 같이 Kubeconfig 설정을 통해 로그인합니다. 패스워드와 OTP를 입력하면 정상적으로 로그인됩니다.
이후 cluster를 선택 후 파드를 조회하면 쿠버네티스가 설치되어있지 않는 서버에서도 쿠버네티스에 정상적으로 접근하는 것을 확인할 수 있습니다.
3-3. Multiple kubernetes clusters
여러 클러스터를 관리할 경우 클러스터를 추가할 수 있습니다. 이를 위해 Teleport Pod에서 토큰을 발급받습니다.
POD=$(kubectl get pod -l app=teleport-cluster -o jsonpath='{.items[0].metadata.name}')
TOKEN=$(kubectl exec -ti "${POD?}" -- tctl nodes add --roles=kube --ttl=10000h --format=json | jq -r '.[0]')
echo $TOKEN
발급받은 토큰을 이용해 teleport와 연결할 클러스터에 접속하여 helm을 통해 클러스터에 teleport-agent를 설치합니다.
helm repo add teleport https://charts.releases.teleport.dev
CLUSTER='temp1-cluster'
PROXY='k8s-teleport-demo.matilda-mzc.com:443'
helm install teleport-agent teleport/teleport-kube-agent --set kubeClusterName=${CLUSTER?} \
--set proxyAddr=${PROXY?} --set authToken=${TOKEN?} --create-namespace --namespace=teleport-agent
정상적으로 배포가 완료되면 teleport-agent 네임스페이스에 파드가 생성된 것을 확인할 수 있습니다.
이후 teleport 로그인이 되어있는 환경에서 클러스터 조회 시 다음과 같이 클러스터가 추가된 것을 확인할 수 있습니다. 이후 tsh kube login 클러스터 명을
통해 클러스터를 활성화해 사용합니다.
3-4 Kubernetes Cluster Label 설정
쿠버네티스 클러스터에 레이블을 설정하기 위해서 Helm으로 클러스터를 배포할 때 파라미터를 설정해야 합니다.
helm install teleport-agent teleport/teleport-kube-agent --set kubeClusterName=${CLUSTER?} \
--set proxyAddr=${PROXY?} --set authToken=${TOKEN?} --create-namespace --namespace=teleport-agent --set labels.env=dev
이미 설치된 경우 Configmap을 수정해 레이블을 추가할 수 있습니다.
#teleport-cluster configmap
kubernetes_service:
enabled: true
listen_addr: 0.0.0.0:3027
kube_cluster_name: k8s-teleport-demo.matilda-mzc.com
labels:
app: teleport-cluster
이후 클러스터 리스트를 조회하면 Label이 정상적으로 추가된 것을 확인할 수 있습니다.
4. Node(ssh 접속 서버) 추가하기
Kubernetes 클러스터가 아닌 SSH 서버의 Access를 관리하기 위해 노드를 추가합니다. 이를 위해 Teleport UI에 접속해 Server 항목에서 추가를 선택합니다. 다음과 같이 추가할 수 있는 스크립트 커맨드가 제공됩니다. 해당 커맨드를 복사해 추가할 서버에서 실행합니다.
실행 시 Teleport Agent와 함께 tsh, tctl, teleport CLI가 함께 설치되며 Node가 추가됩니다.
이후 Web UI에서 서버를 확인할 수 있고 접속할 수 있습니다.
서버의 개수가 많아질수록 효율적인 관리를 위해 Label을 설정할 수 있습니다. 추가한 노드에 접속해 설정파일을 수정합니다. /etc/teleport.yaml
에서 Label을 추가합니다.
#/etc/teleport.yaml
ssh_service:
enabled: "yes"
commands:
- name: hostname
command: [hostname]
period: 1m0s
labels:
environment: dev
이우 데몬 재시작 시 서버에 레이블이 적용된 것을 확인할 수 있습니다.
5. Role & User 관리
Teleport 기본적으로 RBAC를 사용하며 인증과 인가의 절차를 가지고 리소스를 관리합니다. 따라서 Role과 User를 관리하는 방법을 이해할 필요가 있습니다. User의 경우 Name을 지정하고 생성하는 내용밖에 없기 때문에 Role을 생성하는 방법을 알아보겠습니다. 우선 User와 Role에 대한 관리 권한을 가지고 있는 관리자 계정을 생성합니다.
tctl users add teleport-admin2 --roles=editor,access
생성한 editor, access 역할의 경우 Teleport에서 미리 생성해 놓은 역할로 각각의 내용은 다음과 같습니다.
- editor : teleport 설정에 대한 수정 권한(role, user, session, cluster networking 등)
- access: teleport 리소스에 대한 접근 권한(kubernetes, db, server 등)
- auditor: teleport cluster에서 발생한 audit logs, session record를 읽을 수 있는 권한
생성된 계정으로 Web UI에 접속 시 Team 항목에서 User와, Role에 대한 정보를 확인할 수 있습니다.
일반적으로 Role은 yaml 파일 형식으로 관리되는데 allow
, deny
두 가지의 rule을 통해 설정합니다. 일반적으로 모든 자원(resource)에 대한 행위(verbs)는 deny
형태로 지정됩니다. 또한 deny
항목의 경우 allow
의 규칙을 override 합니다. 예를 들어 개발 환경에만 접근 가능한 devs
Role을 생성하기 위해 다음과 같은 요구사항을 정의합니다.
- 서버는 Dev 환경만 접근 가능하다.
- Kubernetes Cluster의 경우 teleport cluster를 제외한 모든 클러스터에 접근이 가능하다.
- 사용자는 Kubernetes에서 Pod, Deployment, service, configmap에 대해서만 조회, 삭제, 생성, 수정을 할 수 있다.
- session 녹화 기능을 조회할 수 있다.
현재 연결된 쿠버네티스 클러스터와 서버 각 3개씩 다음과 같습니다
)
기존에 생성한 teleport-admin 계정으로 role 항목에서 create role을 선택해 다음과 같이 작성합니다. spec.allow
부분을 작성하여 node_labels
를 통해 env:dev
인 서버만 접근 가능하도록 하고, kubernetes_labels
는 전체 접근이 가능하도록 하였지만 deny
섹션에서 teleport-cluster를 설정하여 해당 클러스터에 접근을 하지 못하도록 설정합니다.
kind: role
metadata:
name: dev2
spec:
allow:
kubernetes_groups:
- '{{internal.kubernetes_groups}}'
- developer
kubernetes_labels:
'*': '*'
kubernetes_users:
- '{{internal.kubernetes_users}}'
- dev
# ssh 접속을 허용하는 서버 계정
logins:
- '{{internal.logins}}'
- ec2-user
node_labels:
environment: dev
rules:
- resources:
- session
verbs:
- read
- list
where: contains(session.participants, user.metadata.name)
deny:
kubernetes_labels:
app: teleport-cluster
logins:
- guest
options:
cert_format: standard
create_host_user: false
desktop_clipboard: true
desktop_directory_sharing: true
enhanced_recording:
- command
- network
forward_agent: false
max_session_ttl: 8h0m0s
pin_source_ip: false
port_forwarding: true
record_session:
default: best_effort
desktop: true
version: v5
yaml 파일에서 변수 형태로 value값을 설정 한 항목은 User를 생성할 때 값을 대입할 수 있습니다. 변수를 지정하지 않고 고정적으로만 값을 입력하게 되면 확장성이 낮아 많은 role을 생성해야 됩니다. Role의 경우 공통적인 부분이 많아 변수를 통해 Role을 정의한 후 아래와 같이 User를 생성할 때 값을 지정합니다.
# User 예시
kind: user
version: v2
metadata:
name: alice
spec:
roles: ['dev2']
traits:
logins: ['admin']
kubernetes_groups: ['edit']
다음과 같이 생성 Role을 생성 후 Kubernets 접근 시 권한 에러가 발생합니다. 이는 kubernetes_groups
을 developer
로 설정하였으나 해당 group이 존재하지 않아 그렇습니다. 이를 위해 Kubernetes에 접근해 ClusterRole을 생성합니다.
#Group:developer 에 부여할 cluster role spec
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: developer-cluster-role
rules:
- apiGroups: [""]
resources: ["configmaps","services","pods","deployments"]
verbs: ["get", "watch", "list","create","delete","patch"]
developer 그룹에 해당 롤이 연결되도록 clusterrolebinding을 생성합니다.
kind: ClusterRoleBinding
metadata:
name: developer-crb
subjects:
- kind: Group
name: developer
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: developer-cluster-role
apiGroup: rbac.authorization.k8s.io
이후 tsh
를 통해 재접속 시 Cluster Role에 부여된 Pods는
정상적으로 조회되지만 endpoint
의 경우 접근이 되며 developer group의 권한이 정상적으로 부여된 것을 확인할 수 있습니다..
또한 kubernetes_users를
통해 권한을 부여하려면 clusterroebinding
의 subjects
항목을 User
로 변경해 해당 User를 추가합니다. 이와 같이 Kubernetes, Application, DB, Desktop 등의 리소스의 경우 spec.allow
섹션에 내용을 추가하지만 teleport configure(session, role, rules 등)에 대한 접근을 제어하기 위해서는 spec.allow.rules
에 resources
와 verbs
를 추가해 제어합니다. 그 외의 ssh port-forwarding과 같은 option은 spec.options 에서 설정 합니다.(설정이 가능한 options list)
'Kubernetes' 카테고리의 다른 글
ArgoCD,Jenkins를 이용한 쿠버네티스 배포 (0) | 2023.10.12 |
---|---|
Kubernetes HA 구성을 위한 Pod Scheduling (0) | 2023.10.12 |
Kubernetes에서 학습용 Job 생성하기 (0) | 2023.10.12 |
Kubeflow JupyterNoteBook (0) | 2023.10.12 |
Kubernetes Offline 환경 설치하기 (0) | 2023.10.12 |