

Sau khi hoàn tất việc thiết lập môi trường ở Part 2, các node trong cluster đã có thể kết nối và giao tiếp với nhau. Tuy nhiên, việc “kết nối được” không đồng nghĩa với “an toàn” hay “đáng tin cậy”. Ở thời điểm này, hệ thống vẫn chưa có cơ chế để xác thực danh tính giữa các thành phần cũng như bảo vệ dữ liệu khi truyền qua network.
Trong Kubernetes, mọi thành phần đều giao tiếp thông qua API và network. Nếu không có cơ chế xác thực và mã hóa, bất kỳ thành phần nào cũng có thể giả mạo hoặc can thiệp vào hệ thống. Vì vậy, Kubernetes sử dụng PKI và TLS để định danh cho từng component và mã hóa toàn bộ traffic trong cluster.
Để làm được điều đó, trước khi bootstrap cluster, cần thiết lập một số thành phần quan trọng:
Các thành phần này đóng vai trò đảm bảo:
Nội dung bên dưới sẽ hướng dẫn thiết lập lần lượt các thành phần trên để xây dựng nền tảng security và identity cho cluster, làm tiền đề cho việc triển khai control plane ở phần tiếp theo.
Trong Kubernetes, Certificate Authority (CA) đóng vai trò là “gốc tin cậy” của toàn bộ cluster. Mọi certificate của các component sẽ được CA ký để đảm bảo danh tính và tính hợp lệ trong hệ thống.
Trong phần này, chúng ta sẽ khởi tạo một CA dạng self-signed bằng OpenSSL. Đây là mô hình đơn giản phù hợp cho lab, giúp mô phỏng cách Kubernetes quản lý trust chain trong thực tế.
Để đơn giản hóa quá trình tạo certificate cho nhiều thành phần, chúng ta sử dụng file cấu hình OpenSSL (ca.conf). File này định nghĩa sẵn các template cho từng loại certificate như node, kube-apiserver, controller-manager, scheduler và service accounts.
[req]
distinguished_name = req_distinguished_name
prompt = no
x509_extensions = ca_x509_extensions
[ca_x509_extensions]
basicConstraints = CA:TRUE
keyUsage = cRLSign, keyCertSign
[req_distinguished_name]
C = US
ST = Washington
L = Seattle
CN = CA
[admin]
distinguished_name = admin_distinguished_name
prompt = no
req_extensions = default_req_extensions
[admin_distinguished_name]
CN = admin
O = system:masters
# Service Accounts
#
# The Kubernetes Controller Manager leverages a key pair to generate
# and sign service account tokens as described in the
# [managing service accounts](https://kubernetes.io/docs/admin/service-accounts-admin/)
# documentation.
[service-accounts]
distinguished_name = service-accounts_distinguished_name
prompt = no
req_extensions = default_req_extensions
[service-accounts_distinguished_name]
CN = service-accounts
# Worker Nodes
#
# Kubernetes uses a [special-purpose authorization mode](https://kubernetes.io/docs/admin/authorization/node/)
# called Node Authorizer, that specifically authorizes API requests made
# by [Kubelets](https://kubernetes.io/docs/concepts/overview/components/#kubelet).
# In order to be authorized by the Node Authorizer, Kubelets must use a credential
# that identifies them as being in the `system:nodes` group, with a username
# of `system:node:<nodeName>`.
[node-0]
distinguished_name = node-0_distinguished_name
prompt = no
req_extensions = node-0_req_extensions
[node-0_req_extensions]
basicConstraints = CA:FALSE
extendedKeyUsage = clientAuth, serverAuth
keyUsage = critical, digitalSignature, keyEncipherment
nsCertType = client
nsComment = "Node-0 Certificate"
subjectAltName = DNS:node-0, IP:127.0.0.1
subjectKeyIdentifier = hash
[node-0_distinguished_name]
CN = system:node:node-0
O = system:nodes
C = US
ST = Washington
L = Seattle
[node-1]
distinguished_name = node-1_distinguished_name
prompt = no
req_extensions = node-1_req_extensions
[node-1_req_extensions]
basicConstraints = CA:FALSE
extendedKeyUsage = clientAuth, serverAuth
keyUsage = critical, digitalSignature, keyEncipherment
nsCertType = client
nsComment = "Node-1 Certificate"
subjectAltName = DNS:node-1, IP:127.0.0.1
subjectKeyIdentifier = hash
[node-1_distinguished_name]
CN = system:node:node-1
O = system:nodes
C = US
ST = Washington
L = Seattle
# Kube Proxy Section
[kube-proxy]
distinguished_name = kube-proxy_distinguished_name
prompt = no
req_extensions = kube-proxy_req_extensions
[kube-proxy_req_extensions]
basicConstraints = CA:FALSE
extendedKeyUsage = clientAuth, serverAuth
keyUsage = critical, digitalSignature, keyEncipherment
nsCertType = client
nsComment = "Kube Proxy Certificate"
subjectAltName = DNS:kube-proxy, IP:127.0.0.1
subjectKeyIdentifier = hash
[kube-proxy_distinguished_name]
CN = system:kube-proxy
O = system:node-proxier
C = US
ST = Washington
L = Seattle
# Controller Manager
[kube-controller-manager]
distinguished_name = kube-controller-manager_distinguished_name
prompt = no
req_extensions = kube-controller-manager_req_extensions
[kube-controller-manager_req_extensions]
basicConstraints = CA:FALSE
extendedKeyUsage = clientAuth, serverAuth
keyUsage = critical, digitalSignature, keyEncipherment
nsCertType = client
nsComment = "Kube Controller Manager Certificate"
subjectAltName = DNS:kube-controller-manager, IP:127.0.0.1
subjectKeyIdentifier = hash
[kube-controller-manager_distinguished_name]
CN = system:kube-controller-manager
O = system:kube-controller-manager
C = US
ST = Washington
L = Seattle
# Scheduler
[kube-scheduler]
distinguished_name = kube-scheduler_distinguished_name
prompt = no
req_extensions = kube-scheduler_req_extensions
[kube-scheduler_req_extensions]
basicConstraints = CA:FALSE
extendedKeyUsage = clientAuth, serverAuth
keyUsage = critical, digitalSignature, keyEncipherment
nsCertType = client
nsComment = "Kube Scheduler Certificate"
subjectAltName = DNS:kube-scheduler, IP:127.0.0.1
subjectKeyIdentifier = hash
[kube-scheduler_distinguished_name]
CN = system:kube-scheduler
O = system:system:kube-scheduler
C = US
ST = Washington
L = Seattle
# API Server
#
# The Kubernetes API server is automatically assigned the `kubernetes`
# internal dns name, which will be linked to the first IP address (`10.32.0.1`)
# from the address range (`10.32.0.0/24`) reserved for internal cluster
# services.
[kube-api-server]
distinguished_name = kube-api-server_distinguished_name
prompt = no
req_extensions = kube-api-server_req_extensions
[kube-api-server_req_extensions]
basicConstraints = CA:FALSE
extendedKeyUsage = clientAuth, serverAuth
keyUsage = critical, digitalSignature, keyEncipherment
nsCertType = client, server
nsComment = "Kube API Server Certificate"
subjectAltName = @kube-api-server_alt_names
subjectKeyIdentifier = hash
[kube-api-server_alt_names]
IP.0 = 127.0.0.1
IP.1 = 10.32.0.1
DNS.0 = kubernetes
DNS.1 = kubernetes.default
DNS.2 = kubernetes.default.svc
DNS.3 = kubernetes.default.svc.cluster
DNS.4 = kubernetes.svc.cluster.local
DNS.5 = server.kubernetes.local
DNS.6 = api-server.kubernetes.local
[kube-api-server_distinguished_name]
CN = kubernetes
C = US
ST = Washington
L = Seattle
[default_req_extensions]
basicConstraints = CA:FALSE
extendedKeyUsage = clientAuth
keyUsage = critical, digitalSignature, keyEncipherment
nsCertType = client
nsComment = "Admin Client Certificate"
subjectKeyIdentifier = hashMọi CA đều gồm private key và root certificate. Trong phần này, chúng ta tạo một CA self-signed bằng OpenSSL để làm gốc tin cậy cho cluster. Cách này phù hợp cho lab nhưng không dùng trong production. Tiếp theo, chúng ta sẽ tiến hành khởi tạo CA. Kết quả đầu ra gồm hai file: ca.crt và ca.key
openssl genrsa -out ca.key 4096
openssl req -x509 -new -sha512 -noenc \
-key ca.key -days 3653 \
-config ca.conf \
-out ca.crtTiếp theo, chúng ta sẽ tạo certificate cho từng component trong Kubernetes, bao gồm cả client certificate cho user admin để truy cập cluster.
Quá trình này gồm 3 bước lặp lại cho mỗi thành phần: sinh private key, tạo CSR (Certificate Signing Request) và ký CSR bằng CA đã khởi tạo trước đó.
certs=(
"admin" "node-0" "node-1"
"kube-proxy" "kube-scheduler"
"kube-controller-manager"
"kube-api-server"
"service-accounts"
)for i in ${certs[*]}; do
openssl genrsa -out "${i}.key" 4096
openssl req -new -key "${i}.key" -sha256 \
-config "ca.conf" -section ${i} \
-out "${i}.csr"
openssl x509 -req -days 3653 -in "${i}.csr" \
-copy_extensions copyall \
-sha256 -CA "ca.crt" \
-CAkey "ca.key" \
-CAcreateserial \
-out "${i}.crt"
doneSau khi thực thi hai khối lệnh trên, hệ thống sẽ tạo ra private key, Certificate Signing Request (CSR) và certificate đã được ký cho từng thành phần trong Kubernetes. Có thể kiểm tra các file được tạo bằng lệnh sau:
ls -1 *.crt *.key *.csrDanh sách các file tạo ra sẽ bao gồm:
admin.crt
admin.csr
admin.key
ca.crt
ca.key
kube-api-server.crt
kube-api-server.csr
kube-api-server.key
kube-controller-manager.crt
kube-controller-manager.csr
kube-controller-manager.key
kube-proxy.crt
kube-proxy.csr
kube-proxy.key
kube-scheduler.crt
kube-scheduler.csr
kube-scheduler.key
node-0.crt
node-0.csr
node-0.key
node-1.crt
node-1.csr
node-1.key
service-accounts.crt
service-accounts.csr
service-accounts.keyTrong bước này, các chứng chỉ đã tạo sẽ được phân phối đến từng node tại đúng vị trí mà các thành phần Kubernetes sử dụng để xác thực. Trong thực tế, các file này cần được bảo vệ nghiêm ngặt vì chúng đóng vai trò như thông tin định danh giữa các thành phần trong cluster.
Trước tiên, chúng ta sẽ sao chép certificate và private key tương ứng đến các máy node-0 và node-1:
for host in node-0 node-1; do
ssh root@${host} mkdir /var/lib/kubelet/
scp ca.crt root@${host}:/var/lib/kubelet/
scp ${host}.crt \
root@${host}:/var/lib/kubelet/kubelet.crt
scp ${host}.key \
root@${host}:/var/lib/kubelet/kubelet.key
doneSao chép các certificate và private key cần thiết đến máy chủ
scp \
ca.key ca.crt \
kube-api-server.key kube-api-server.crt \
service-accounts.key service-accounts.crt \
root@server:~/Các chứng chỉ client của kube-proxy, kube-controller-manager, kube-scheduler và kubelet sẽ được sử dụng để tạo các file kubeconfig phục vụ xác thực giữa các thành phần trong phần tiếp theo
Phần này tập trung vào việc tạo các file kubeconfig cho các client trong Kubernetes. Đây là các cấu hình dùng để thiết lập kết nối và xác thực với Kubernetes API Server.
Trong bước này, chúng ta sẽ tạo kubeconfig cho kubelet và user admin.
Khi tạo kubeconfig cho kubelet, cần sử dụng client certificate tương ứng với từng node. Điều này đảm bảo kubelet được nhận diện đúng bởi Node Authorizer và được cấp quyền phù hợp trong cluster.
Ghi chú: Các lệnh dưới đây cần được thực thi trong cùng thư mục đã sử dụng để tạo TLS certificates ở phần trước (mục III.5 – Cấp phát CA và tạo chứng chỉ TLS).
Tiếp theo, chúng ta sẽ tạo kubeconfig cho các worker node node-0 và node-1:
for host in node-0 node-1; do
kubectl config set-cluster kubernetes-the-hard-way \
--certificate-authority=ca.crt \
--embed-certs=true \
--server=https://server.kubernetes.local:6443 \
--kubeconfig=${host}.kubeconfig
kubectl config set-credentials system:node:${host} \
--client-certificate=${host}.crt \
--client-key=${host}.key \
--embed-certs=true \
--kubeconfig=${host}.kubeconfig
kubectl config set-context default \
--cluster=kubernetes-the-hard-way \
--user=system:node:${host} \
--kubeconfig=${host}.kubeconfig
kubectl config use-context default \
--kubeconfig=${host}.kubeconfig
doneKết quả sẽ có 2 file
node-0.kubeconfig
node-1.kubeconfigTạo file kubeconfig cho dịch vụ kube-proxy:
kubectl config set-cluster kubernetes-the-hard-way \
--certificate-authority=ca.crt \
--embed-certs=true \
--server=https://server.kubernetes.local:6443 \
--kubeconfig=kube-proxy.kubeconfig
kubectl config set-credentials system:kube-proxy \
--client-certificate=kube-proxy.crt \
--client-key=kube-proxy.key \
--embed-certs=true \
--kubeconfig=kube-proxy.kubeconfig
kubectl config set-context default \
--cluster=kubernetes-the-hard-way \
--user=system:kube-proxy \
--kubeconfig=kube-proxy.kubeconfig
kubectl config use-context default \
--kubeconfig=kube-proxy.kubeconfigKết quả sẽ được file
kube-proxy.kubeconfigTạo file kubeconfig cho dịch vụ kube-controller-manager:
kubectl config set-cluster kubernetes-the-hard-way \
--certificate-authority=ca.crt \
--embed-certs=true \
--server=https://server.kubernetes.local:6443 \
--kubeconfig=kube-controller-manager.kubeconfig
kubectl config set-credentials system:kube-controller-manager \
--client-certificate=kube-controller-manager.crt \
--client-key=kube-controller-manager.key \
--embed-certs=true \
--kubeconfig=kube-controller-manager.kubeconfig
kubectl config set-context default \
--cluster=kubernetes-the-hard-way \
--user=system:kube-controller-manager \
--kubeconfig=kube-controller-manager.kubeconfig
kubectl config use-context default \
--kubeconfig=kube-controller-manager.kubeconfigKết quả thu được file
kube-controller-manager.kubeconfigTạo file kubeconfig cho dịch vụ kube-scheduler:
kubectl config set-cluster kubernetes-the-hard-way \
--certificate-authority=ca.crt \
--embed-certs=true \
--server=https://server.kubernetes.local:6443 \
--kubeconfig=kube-scheduler.kubeconfig
kubectl config set-credentials system:kube-scheduler \
--client-certificate=kube-scheduler.crt \
--client-key=kube-scheduler.key \
--embed-certs=true \
--kubeconfig=kube-scheduler.kubeconfig
kubectl config set-context default \
--cluster=kubernetes-the-hard-way \
--user=system:kube-scheduler \
--kubeconfig=kube-scheduler.kubeconfig
kubectl config use-context default \
--kubeconfig=kube-scheduler.kubeconfigKết quả thu được file
kube-scheduler.kubeconfigTạo file kubeconfig cho user admin:
kubectl config set-cluster kubernetes-the-hard-way \
--certificate-authority=ca.crt \
--embed-certs=true \
--server=https://127.0.0.1:6443 \
--kubeconfig=admin.kubeconfig
kubectl config set-credentials admin \
--client-certificate=admin.crt \
--client-key=admin.key \
--embed-certs=true \
--kubeconfig=admin.kubeconfig
kubectl config set-context default \
--cluster=kubernetes-the-hard-way \
--user=admin \
--kubeconfig=admin.kubeconfig
kubectl config use-context default \
--kubeconfig=admin.kubeconfigKết quả thu được file
admin.kubeconfigTiếp theo, thực hiện copy kubeconfig của kube-controller-manager và kube-scheduler sang máy server:
for host in node-0 node-1; do
ssh root@${host} "mkdir -p /var/lib/{kube-proxy,kubelet}"
scp kube-proxy.kubeconfig \
root@${host}:/var/lib/kube-proxy/kubeconfig \
scp ${host}.kubeconfig \
root@${host}:/var/lib/kubelet/kubeconfig
doneCopy các file kubeconfig tương ứng của kube-controller-manager và kube-scheduler sang máy server:
scp admin.kubeconfig \
kube-controller-manager.kubeconfig \
kube-scheduler.kubeconfig \Kubernetes lưu trữ nhiều loại dữ liệu trong etcd, bao gồm trạng thái cluster, cấu hình và các thông tin nhạy cảm như Secrets. Để bảo vệ dữ liệu này, Kubernetes hỗ trợ cơ chế mã hóa ở mức lưu trữ (encryption at rest).
Trong phần này, chúng ta sẽ tạo encryption key và file cấu hình mã hóa để sử dụng cho Kubernetes Secrets.
Tạo một khóa mã hóa:
export ENCRYPTION_KEY=$(head -c 32 /dev/urandom | base64)Lệnh trên sinh một chuỗi ngẫu nhiên dài 32 byte và mã hóa dưới dạng base64, được sử dụng làm khóa mã hóa.
Tiếp tục thực hiện tạo Tạo file cấu hình encryption-config.yaml:
envsubst < configs/encryption-config.yaml \
> encryption-config.yamlLệnh envsubst sẽ thay thế các biến môi trường (ví dụ ENCRYPTION_KEY) trong file mẫu bằng giá trị thực và tạo ra file cấu hình hoàn chỉnh.
Cuối cùng, thực hiện copy file cấu hình mã hóa encryption-config.yaml tới các instance controller (server node) :
scp encryption-config.yaml root@server:~/Sau khi hoàn thành bước này, các thành phần cần thiết cho cơ chế xác thực và mã hóa dữ liệu trong cluster đã được thiết lập đầy đủ.
Trong phần tiếp theo, chúng ta sẽ bắt đầu bootstrap control plane và đưa Kubernetes cluster vào trạng thái sẵn sàng vận hành.
