Kubernetes ngày càng trở thành nền tảng cốt lõi trong hạ tầng của nhiều doanh nghiệp - nhưng càng mở rộng quy mô, bài toán quản lý quyền truy cập càng trở nên đau đầu hơn.

Trong môi trường doanh nghiệp, quản lý quyền truy cập vào Kubernetes cluster thường rất phức tạp: tạo user thủ công, phân phối kubeconfig, thu hồi quyền khi nhân sự nghỉ việc... Tất cả đều tốn thời gian và dễ gây ra lỗ hổng bảo mật nếu không được quản lý chặt chẽ.

Giải pháp cho sự bất cập này chính là OIDC (OpenID Connect) - một chuẩn xác thực cho phép Kubernetes ủy thác việc quản lý danh tính cho một Identity Provider bên ngoài. Thay vì tự quản lý user trên cluster, bạn chỉ cần quản lý trên hệ thống identity quen thuộc - ai vào group nào, người đó có quyền tương ứng trên K8S, tự động và nhất quán.

hướng dẫn tích hợp OIDC cho Kubernetes

Trong series này, mình sẽ hướng dẫn tích hợp OIDC cho Kubernetes với hai lựa chọn phổ biến, phù hợp với các môi trường khác nhau:

Phần 1 - Microsoft Azure AD (Microsoft Entra ID): Dành cho các tổ chức đang dùng hệ sinh thái Microsoft 365, tận dụng luôn hạ tầng identity có sẵn.

Phần 2 - Authentik: Dành cho những ai muốn tự chủ hoàn toàn - một Identity Provider open-source, self-hosted, không phụ thuộc cloud vendor và hoàn toàn miễn phí.

Bây giờ, hãy cùng mình đi vào nội dung phần 1: Xác thực người dùng Kubernetes với OIDC sử dụng Microsoft Azure AD (Entra ID)

Chuẩn bị

  • Một cluster Kubernetes mà bạn có quyền chỉnh sửa cấu hình kube-apiserver (bài viết sử dụng RKE2 để init Kubernetes).
  • Một Azure AD (Entra ID) tenant mà bạn có quyền Application Administrator hoặc Global Administrator.
  • Máy client để test có thể connect tới kube-apiserver và đã được cài đặt kubectl.

Cấu hình Microsoft Azure AD

1. Tạo App registrations trên Microsoft Azure

Truy cập https://portal.azure.com/

Tạo App registrations trên Microsoft Azure

2. Điền thông tin app

Ở phần Supported account types, chọn Accounts in this organizational directory only (single tenant) để giới hạn chỉ tài khoản nội bộ của tổ chức mới đăng nhập được.

Supported account types, chọn Accounts in this organizational directory only

Sau khi tạo xong sẽ có giao diện như sau, hãy chú ý Application (client) IDDirectory (tenant) ID

Application (client) ID và Directory (tenant) ID

3. Cấu hình application

Tiếp tục qua phần Token configuration cấu hình Group claim

Bước này rất quan trọng: nếu không cấu hình Group Claim, JWT token trả về sẽ không chứa danh sách group của user, và Kubernetes sẽ không thể phân quyền theo group. Chọn All groups và đảm bảo chọn Group ID (Object ID) để token trả về đúng giá trị mà K8S RBAC cần.

All groups và đảm bảo chọn Group ID (Object ID) để token trả về đúng giá trị mà K8S RBAC cần.

Cấu hình tiếp phần API Permissions, thêm quyền GroupMember.Read.All

GroupMember.Read.All

Chọn Grant admin consent để cấp quyền cho API

Lưu ý: Bước này yêu cầu quyền Global Administrator hoặc Privileged Role Administrator (hoặc bạn có thể nhờ Global Admin consent cho application). Nếu quên grant consent, token sẽ không chứa thông tin group và K8S sẽ không phân quyền đúng. Hãy đảm bảo cột Status hiển thị dấu tích xanh sau khi grant.

yêu cầu quyền Global Administrator hoặc Privileged Role Administrator

Vậy là đã cấu hình xong phần application trên Azure, tiếp tục đến cấu hình kube-api server của k8s.

Cấu hình kube-apiserver trên Kubernetes

Ở đây mình init cluster k8s bằng RKE2 nên sẽ sửa config tại /etc/rancher/rke2/config.yaml (đối với những cách init cluster khác sẽ có các file config đặt ở những vị trí khác nhau, hãy tìm hiểu thêm nhé)

Thêm config sau vào file config.yaml

kube-apiserver-arg:
- "oidc-issuer-url=https://login.microsoftonline.com/<tenant_id>/v2.0"
- "oidc-client-id=<Application (client) ID>"
- "oidc-username-claim=email"
- "oidc-groups-claim=groups"

Ý nghĩa từng flag:

  • oidc-issuer-url: URL của Azure AD tenant - kube-apiserver dùng đây để fetch public key xác minh token.
  • oidc-client-id: Client ID của App Registration vừa tạo ở bước trước.
  • oidc-username-claim: Trường trong JWT được dùng làm username trong K8S (dùng email cho dễ nhận diện).
  • oidc-groups-claim: Trường chứa danh sách group của user (phải khớp với Group Claim đã cấu hình trên Azure AD).

Đây là 1 ví dụ của file config.yaml

ví dụ của file config.yaml

Restart rke2-server bằng lệnh systemctl restart rke2-server.service

Tiếp theo chúng ta sẽ cấu hình tại máy client muốn sử dụng kubectl để quản trị cluster kubernetes.

Cấu hình máy client

Đầu tiên cài đặt gói kubelogin theo hướng dẫn tại https://github.com/int128/kubelogin

Tạo file kubeconfig theo mẫu sau (mặc định file sẽ nằm ở ~/.kube/config):

apiVersion: v1

clusters:
- cluster:
    certificate-authority-data: xxx
    server: https://IP:6443
  name: default

contexts:
- context:
    cluster: default
    user: oidc-user
  name: oidc-context

current-context: oidc-context
kind: Config
preferences: {}

users:
- name: oidc-user
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1
      command: kubectl
      interactiveMode: IfAvailable
      args:
      - oidc-login
      - get-token
      - --oidc-issuer-url=https://login.microsoftonline.com/<tenant_id>/v2.0
      - --oidc-client-id=<Application (client) ID>
      - --oidc-extra-scope=profile,email,openid

Thử chạy lệnh kubectl để kiểm tra

chạy lệnh kubectl để kiểm tra

Khi chạy lệnh trình duyệt sẽ popup 1 trang http://localhost:8000 để login bằng account O365.

image019.png

Sau khi login xong kubectl đã lấy được username, group nhưng vì chúng ta chưa phân quyền cho user/group nên sẽ báo Forbidden.

Đây là dấu hiệu tốt! Lỗi Forbidden có nghĩa xác thực OIDC đã thành công - Kubernetes đã lấy được username và group từ token Azure AD. Chúng ta chỉ cần tạo ClusterRoleBinding ở bước tiếp theo là xong.

Có thể dùng cmd này để lấy token và sử dụng jwt.io để xem những giá trị gì được trả về:

kubectl oidc-login get-token --oidc-issuer-url=https://login.microsoftonline.com/<tenant_id>/v2.0 --oidc-client-id=<Application (client) ID>

Tiếp tục sử dụng RBAC trên K8S để phân quyền cho user/group có thể có những thao tác gì trên cluster K8S.

Phân quyền với Kubernetes RBAC

Thay vì gán quyền cho từng user, best practice là gán quyền theo group. Khi có nhân sự mới, chỉ cần thêm họ vào group Azure AD - quyền truy cập K8S tự động có ngay, không cần tạo user thủ công. Ngược lại khi nhân sự nghỉ việc hoặc thay đổi vị trí công việc, chỉ cần disable hoặc thay đổi group của tài khoản Azure là mất quyền toàn bộ.

Trong bài demo này mình sẽ phân quyền cho Group tên là OIDC-K8S-ADMIN có quyền cluster-admin trên cluster K8S.

Đầu tiên tạo group trên Office 365 hoặc trên Portal Azure AD

tạo group trên Office 365 hoặc trên Portal Azure AD

image023.png

Chú ý Object ID của group, chúng ta sẽ phân quyền dựa theo trường này

 Lưu ý: K8S sử dụng Object ID (UUID) của group, không phải display name. Copy đúng Object ID khi tạo ClusterRoleBinding ở bước sau.

Tạo ClusterRoleBinding để phân quyền cho group vừa tạo

Tạo ClusterRoleBinding để phân quyền

Bây giờ thử lại với kubectl ở máy client

image027.png

Đã có thể thao tác với cluster K8S

Từ giờ trở đi khi có các thay đổi về nhân sự, chúng ta chỉ cần tác động đến group trên Azure mà không cần các bước như tạo user, cấp quyền trực tiếp trên cluster K8S.

Tip: Để buộc login lại hoặc tạo mới token hãy xoá thư mục cache tại $HOME/.kube/cache

Kết luận

Sau khi hoàn thành các bước trên, bạn đã xây dựng được một hệ thống quản lý quyền truy cập Kubernetes tích hợp hoàn toàn với Azure AD. Workflow quản lý từ đây rất đơn giản:

  • Nhân sự mới: Thêm vào group Azure AD → tự động có quyền trên K8S ngay lập tức.
  • Nhân sự nghỉ việc: Disable hoặc xóa tài khoản Azure AD → mất quyền toàn bộ trên K8S, không cần có thêm thao tác nào khác.
  • Thay đổi quyền: Di chuyển user giữa các group Azure AD → quyền K8S thay đổi theo.

Thông thường ở các doanh nghiệp dùng Azure AD (Entra ID), việc on/offboard nhân sự đã được tự động hoá qua HR system → không còn nỗi lo quên revoke quyền trên K8S. Kết hợp với kubeconfig không gán cứng credential, đây chính là cách quản lý Kubernetes đúng nghĩa enterprise. Ở phần sau chúng ta sử dụng Identity open-source dành cho các tổ chức không sử dụng Azure hoặc đơn giản là bạn muốn dùng một Identity private.

See you~