Kubernetes集群管理与安全认证全解析
1. Azure Kubernetes Service集群管理
在使用Azure Kubernetes Service(AKS)时,探索集群与Azure门户的集成程度是个不错的做法。完成探索后,可能就需要删除集群了。
1.1 删除AKS集群
要删除AKS集群,可在Azure CLI中运行以下命令:
$ az aks delete --resource-group rg-myfirstakscluster-eus --name aks-myfirstakscluster-eus
执行该命令后,系统会询问是否确认删除,输入“yes”即可开始删除集群,此过程大约需要五分钟。需要注意的是,上述命令仅删除集群,而不删除资源组。若要删除资源组,可运行以下命令:
$ az group delete --name rg-myfirstakscluster-eus
同样,系统会询问是否确认删除资源组,输入“yes”即可完成删除。
1.2 集群运行成本
与前两章介绍的其他两种云服务不同,非生产工作负载的集群管理是免费的,只需支付计算资源的费用。例如,在美国东部地区使用两个Standard_DS2_v2实例,每月费用约为213美元;若选择标准集群管理,每月费用则为286美元。
还可以选择新一代实例来降低成本。例如,使用以下命令创建一个新集群:
$ az group create --name rg-myfirstakscluster-eus --location eastus -o table
$ az aks create --resource-group rg-myfirstakscluster-eus --name aks-myfirstakscluster-eus --node-count 2 --enable-addons monitoring --generate-ssh-keys --node-vm-size standard_ds3_v2 -o yaml
若选择非生产选项,此命令将创建一个包含两个节点、四个vCPU和16GB RAM的集群,每月费用约为140美元。
1.3 三大公共云服务对比
以下是Google Kubernetes Engine(GKE)、Amazon Elastic Kubernetes Service(EKS)和Microsoft AKS的对比:
| 特性 | Google Kubernetes Engine (GKE) | Amazon Elastic Kubernetes Service (EKS) | Microsoft AKS |
| — | — | — | — |
| Kubernetes版本支持 | 最新版本,频繁更新 | 版本支持稍落后 | 最新版本,频繁更新 |
| 自动更新 | 控制平面和节点自动更新 | 控制平面按需更新,节点手动更新 | 控制平面和节点按需更新 |
| 易用性 | 高 - 直观界面 | 中 - 复杂设置 | 高 - 直观界面 |
| 与云服务集成 | 与GCP服务强集成 | 与AWS服务强集成 | 与Azure服务强集成 |
| 可扩展性 | 良好,支持自动扩展 | 良好,支持自动扩展 | 良好,支持自动扩展 |
| 安全特性 | 强,与GCP安全工具集成 | 强,与AWS安全工具集成 | 强,与Azure安全工具集成 |
| 定价 | 控制平面免费,按节点付费 | 控制平面每小时0.10美元,加上节点成本 | 控制平面免费,按节点付费 |
| 多区域集群支持 | 是 | 是 | 是 |
| 私有集群支持 | 是 | 是 | 是 |
| 无服务器计算选项 | 是,使用Cloud Run for Anthos | 是,使用Fargate for EKS | 是,使用AKS虚拟节点 |
从上述对比中可以得出以下关键要点:
- GKE在Kubernetes版本支持和自动更新方面往往领先。
- AKS被大多数人认为是最用户友好的,特别是对于已经使用Azure服务的用户。
- EKS对控制平面收费,而GKE和AKS仅对工作节点收费。
- 三大服务都与各自的云生态系统有很强的集成。
- GKE因其先进的特性和性能而经常受到赞誉,这得益于Google作为Kubernetes原始创建者的专业知识。
- 每个服务都有独特的优势:GKE在性能和特性方面,EKS在AWS生态系统集成方面,AKS在易用性和Azure集成方面。
- 最佳选择通常取决于现有的云基础设施、需求以及对云服务提供商生态系统的熟悉程度。
2. Kubernetes安全认证
身份验证和授权是现代软件系统中提供必要身份管理和访问管理的基石。很多人会混淆这两个术语,实际上它们是截然不同的过程。身份验证用于验证用户的身份,通常通过用户名和密码等机制实现;而授权则决定了经过身份验证的用户在系统中可以访问或执行的操作。在Kubernetes中,身份验证总是先于授权进行,之后经过验证的用户才能与系统进行交互。Kubernetes通过基于角色的访问控制(RBAC)进一步扩展了这一概念,允许管理员定义具有特定权限的角色,并将这些角色分配给用户,从而有效实现最小权限原则并实现细粒度的访问控制。
2.1 Kubernetes中的身份验证工作流程
Kubernetes集群的安全防护采用分层方法,主要包括以下几个关键组件:
-
身份验证
:作为第一道防线,验证任何试图访问Kubernetes API服务器的用户身份。用户可以使用密码、令牌或特殊证书来证明自己的授权。
-
授权
:在确认用户身份后,确定用户在集群中实际可以执行的操作。用户可能被授予查看资源的权限,但不能修改它们,或者可能被授权在特定区域创建新资源。
-
准入控制
:增加了额外的审查层。准入控制模块可以检查传入的请求,确保它们符合预定义的安全策略。它们甚至可以修改请求以强制执行特定规则,或者在请求构成威胁时完全拒绝它们。
-
审计
:记录集群内的所有活动,包括用户、应用程序和控制平面本身的操作。这些日志对于监控可疑活动和维护安全环境非常有价值。
graph LR
A[请求] --> B[身份验证]
B --> C{是否通过?}
C -- 是 --> D[授权]
C -- 否 --> E[拒绝/匿名处理]
D --> F[准入控制]
F --> G{是否合规?}
G -- 是 --> H[执行操作]
G -- 否 --> I[拒绝请求]
H --> J[审计记录]
2.2 Kubernetes API身份验证
Kubernetes API身份验证确保只有授权的用户或服务才能与集群中运行的资源进行通信。每个传入的请求都会经过一系列配置好的身份验证模块。请求通常分为以下两类:
- 与外部普通用户或Kubernetes集群中定义的ServiceAccount相关联。
- 如果集群配置为允许匿名请求,则将其视为匿名请求。
身份验证过程使用整个HTTP请求作为输入,但通常只分析请求头或客户端证书。身份验证由依赖于集群配置的身份验证模块执行。集群可能启用了多个身份验证模块,它们将按顺序执行,直到有一个模块验证成功。如果请求验证失败,API服务器将返回HTTP状态码401(未授权),或者如果允许匿名请求,则将其视为匿名请求。匿名请求本质上会被映射到一个特殊的用户名
system:anonymous
和一个组
system:unauthenticated
。
用户分为普通用户和服务账户:
-
普通用户
:由外部管理,独立于Kubernetes集群。目前,Kubernetes没有提供任何对象来表示此类用户。外部用户管理可以简单地使用静态用户密码文件,但不建议这样做。在生产环境中,建议使用现有的身份提供者(IdP),如Google、GitHub、Azure Active Directory(AAD)或AWS IAM,并使用OpenID Connect(OIDC)令牌进行无缝身份验证。普通用户账户在Kubernetes中是全局的,没有命名空间限制。
-
服务账户
:由Kubernetes集群管理,建模为ServiceAccount对象。可以像管理Kubernetes中的其他资源一样创建和管理服务账户。服务账户用于集群组件或Pod中运行的进程。ServiceAccount的凭据将作为Secrets(手动或通过TokenRequest API)创建,并挂载到Pod中,以便容器进程可以使用它们与Kubernetes API服务器进行通信。当进程使用ServiceAccount令牌进行身份验证时,它将被视为
system:serviceaccount:<namespace>:<serviceAccountName>
用户。需要注意的是,ServiceAccount是有命名空间的。
2.3 常见身份验证方法
Kubernetes API服务器支持多种身份验证机制,以下是一些常见的方法:
-
静态令牌文件
:这是Kubernetes提供的最基本的管理普通用户的方法。需要定义一个.csv文件,每行格式如下:
token,user,uid,"group1,group2,group3"
然后在启动Kubernetes API服务器时,通过
token-auth-file
参数传递该文件。在
/etc/kubernetes/manifests/kube-apiserver.yaml
文件中配置如下:
# /etc/kubernetes/manifests/kube-apiserver.yaml
...<removed for brevity>...
spec:
containers:
- command:
- kube-apiserver
- --advertise-address=192.168.59.154
- --allow-privileged=true
- --authorization-mode=Node,RBAC
- --token-auth-file=/etc/kubernetes/user-tokens.csv
- --client-ca-file=/var/lib/minikube/certs/ca.crt
...<removed for brevity>...
要对API服务器进行身份验证,请求需要使用标准的HTTP承载身份验证方案,添加如下请求头:
Authorization: Bearer <token>
使用
kubectl
时,需要修改
kubeconfig
:
$ kubectl config set-credentials <contextUser> --token=<token>
然后使用
kubectl config use-context
命令创建并使用包含该用户的上下文。
静态令牌文件方法的优点是易于配置和理解,但缺点也很明显,如不安全、需要手动管理用户、添加或删除用户以及旋转令牌都需要重启API服务器等。因此,该方法适用于开发环境和学习身份验证原理,但不建议用于生产环境。
-
ServiceAccount令牌
:ServiceAccount用于集群内的进程身份标识,也可用于外部请求的身份验证。ServiceAccount是Kubernetes对象,可以使用
kubectl或直接向API服务器发送HTTP请求进行管理。其令牌是JSON Web Tokens(JWTs),可以按需生成或使用kubectl create token命令生成。
在定义Pod时,可以通过
.spec.serviceAccountName
指定要使用的ServiceAccount。JWT令牌将被注入到容器中,容器内的进程可以使用它通过HTTP承载身份验证方案向Kubernetes API服务器进行身份验证。
在Kubernetes 1.22之前,使用Secrets自动生成API凭据,存在静态令牌存储不安全和难以管理令牌生命周期和权限的问题。从1.22版本开始,采用了更安全的方法,Pods直接通过TokenRequest API获取令牌,这些令牌是短寿命的,并且会自动挂载为卷。
以下是使用ServiceAccount令牌进行身份验证的步骤:
1. 创建一个新的Namespace和ServiceAccount的YAML清单:
# 01_serviceaccount/example-sa-ns.yaml
---
apiVersion: v1
kind: Namespace
metadata:
name: example-ns
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: example-sa
namespace: example-ns
也可以使用命令
kubectl create serviceaccount example-sa
创建资源。
2. 创建一个名为
pod-reader
的Role对象的YAML清单:
# 01_serviceaccount/pod-reader-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: example-ns
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
-
创建一个名为
reads-pods的RoleBinding的YAML清单:
# 01_serviceaccount/read-pods-rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: example-ns
subjects:
- kind: ServiceAccount
name: example-sa
namespace: example-ns
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
-
使用
kubectl apply命令将所有清单文件应用到集群:
$ kubectl apply -f 01_serviceaccount/
- 为ServiceAccount创建令牌:
$ kubectl create token example-sa -n example-ns
收集命令输出中的JWT令牌。
6. 在
kubeconfig
中创建一个新用户:
$ kubectl config set-credentials example-sa --token=<your-token>
-
在
kubeconfig中创建一个使用该用户的新上下文:
$ kubectl config set-context <new-context-name> --user=<new-user-created> --cluster=<clusterName>
例如:
$ kubectl config set-context example-sa-context --user=example-sa --cluster=minikube
-
在切换到新上下文之前,在
example-ns命名空间中创建一个简单的nginx Pod:
$ cp references/sa-demo-nginx-pod.yaml 01_serviceaccount/nginx-pod.yaml
$ kubectl apply -f 01_serviceaccount/nginx-pod.yaml
- 检查当前使用的上下文名称:
$ kubectl config current-context
- 切换到新上下文:
$ kubectl config use-context example-sa-context
- 验证当前使用的凭据身份:
$ kubectl auth whoami
- 验证身份验证和权限:
$ kubectl get po -n example-ns
$ kubectl get pods -n kube-system
$ kubectl get svc -n example-ns
ServiceAccount令牌的优点是易于配置和使用,完全由Kubernetes集群管理,并且是命名空间的。但它主要用于集群内的进程,不建议用户用于外部身份验证,尤其是在生产环境中,主要是出于安全考虑。
Kubernetes集群管理与安全认证全解析
2. Kubernetes安全认证(续)
2.4 X.509客户端证书
使用X.509客户端证书进行身份验证是行业标准做法,但需要良好的证书签名、撤销和轮换管理机制,否则可能会出现与使用ServiceAccount令牌类似的安全问题。
该方法在Kubernetes中的工作流程如下:
1. Kubernetes API服务器启动时使用
client-ca-file
参数,提供用于验证客户端证书的证书颁发机构(CA)信息。可以配置自定义CA证书,也可以使用集群部署时创建的默认CA。例如,使用minikube时,可在
kube-apiserver
中看到已配置的默认CA文件:
# /etc/kubernetes/manifests/kube-apiserver.yaml
...<removed for brevity>...
spec:
containers:
- command:
- kube-apiserver
- --advertise-address=192.168.59.154
- --allow-privileged=true
- --authorization-mode=Node,RBAC
- --client-ca-file=/var/lib/minikube/certs/ca.crt
...<removed for brevity>...
- 用户若要向API服务器进行身份验证,需向CA请求X.509客户端证书,这应该是一个安全且可审计的过程。证书的主题通用名称(CN属性)将在身份验证成功后用作用户名。从Kubernetes 1.19开始,可以使用Certificates API管理签名请求。
- 用户在身份验证时需向API服务器出示客户端证书,API服务器将根据CA验证该证书。若验证成功,请求将通过身份验证;否则将被拒绝。使用minikube集群时,实际上已经在使用基于证书的身份验证。
以下是生成和配置基于证书的身份验证的步骤:
1. 使用
openssl
命令创建私钥:
$ openssl genrsa -out iamgini.key 2048
- 生成证书签名请求(CSR):
$ openssl req -new -key iamgini.key -out iamgini.csr -subj "/CN=iamgini/O=web1/O=frontend"
- 收集CSR数据并使用base64编码:
$ cat iamgini.csr | base64 -w 0
-
使用Certificates API创建CertificateSigningRequest资源,使用
csr.yaml文件:
# csr.yaml
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: iamgini
spec:
request: <your encoded CSR content here from Step.3>
signerName: kubernetes.io/kube-apiserver-client
usages:
- client auth
- 创建CertificateSigningRequest:
$ kubectl apply -f csr.yaml
-
管理员(或具有
certificatesigningrequests权限的用户)查看CSR资源:
$ kubectl get csr
- 检查并批准CSR:
$ kubectl certificate approve iamgini
-
批准CSR后,从批准的CSR资源中收集证书数据并保存到
iamgini.crt文件:
$ kubectl get csr iamgini -o json | jq -r '.status.certificate' | base64 --decode > iamgini.crt
-
此时拥有私钥和证书(可删除
.csr文件):
$ ls iamgini.*
-
在
kubeconfig中配置新用户和上下文,创建新用户条目:
$ kubectl config set-credentials iamgini --client-key=/full-path/iamgini.key --client-certificate=/full-path/iamgini.crt
- 创建使用新用户的新上下文:
$ kubectl config set-context iamgini --cluster=minikube --user=iamgini
-
更新
kubeconfig后,测试访问,切换上下文:
$ kubectl config use-context iamgini
- 验证上下文和连接:
$ kubectl auth whoami
X.509客户端证书身份验证的优点是比使用ServiceAccount令牌或静态令牌文件更安全,证书无法在集群中存储,可按需撤销。缺点是证书有有效期,需要监控证书的过期、撤销和轮换,在浏览器中使用客户端证书进行身份验证比较麻烦。
2.5 OpenID Connect令牌
使用OpenID Connect(OIDC)可以为Kubernetes集群实现单点登录(SSO)体验。OIDC是基于OAuth 2.0的身份验证层,允许第三方应用程序验证最终用户的身份并获取基本用户配置文件信息。OIDC使用JWT令牌,可通过符合OAuth 2.0规范的流程获取。
在Kubernetes中使用OIDC进行身份验证的主要问题是OpenID提供者的可用性有限,但在云环境中,主要的云服务提供商(如Microsoft Azure、Amazon Web Services和Google Cloud Platform)都有自己的OpenID提供者。托管的云Kubernetes服务(如AKS、Amazon EKS和Google Kubernetes Engine)可以直接或通过简单的配置集成其原生OpenID提供者。
OIDC身份验证流程的基本原理如下:
graph LR
A[用户请求] --> B[向IdP请求令牌]
B --> C{IdP验证}
C -- 通过 --> D[返回令牌]
D --> E[用户使用令牌访问Kubernetes API]
E --> F[Kubernetes API验证令牌]
F -- 通过 --> G[允许访问]
F -- 失败 --> H[拒绝访问]
使用OIDC的优点包括:
- 可实现SSO体验,可与组织内的其他服务一起使用。
- 大多数云服务提供商的托管Kubernetes服务可轻松集成其OpenID提供者。
- 也可与其他OpenID提供者和非云部署一起使用,尽管需要更多配置。
- 是一种安全且可扩展的解决方案。
缺点包括:
- Kubernetes没有用于触发身份验证过程的Web界面,需要手动从身份提供者(IdP)请求凭据。在托管云Kubernetes服务中,通常有额外的工具来生成包含凭据的
kubeconfig
。
- OIDC令牌可以由支持令牌端点撤销功能的IdP撤销,但并非所有IdP都支持此功能,且Kubernetes本身不处理令牌撤销。
Kubernetes依赖外部的OIDC身份提供者,如云服务提供商提供的或独立工具(如Dex、Keycloak、UAA、OpenUnison)。要使OIDC身份提供者在Kubernetes中工作,需要满足以下要求:
- 支持OIDC发现,以便Kubernetes可以从发现端点读取IdP的公钥来验证OIDC令牌。
- 符合传输层安全(TLS)要求,处理敏感的身份验证数据。
- 证书必须有CA标志设置为TRUE,因为Kubernetes使用Go的TLS客户端严格要求此条件。
配置Kubernetes API服务器使用OIDC需要设置以下主要标志:
-
oidc-issuer-url
:OIDC提供者的URL,用于验证令牌的真实性。
-
oidc-client-id
:Kubernetes作为客户端与IdP进行身份验证时使用的客户端ID。
-
oidc-username-claim
:指定令牌中哪个声明应映射到Kubernetes用户名。
-
oidc-groups-claim
:将IdP中的组映射到Kubernetes组,以便管理RBAC角色。
2.6 其他方法
Kubernetes还提供了一些其他身份验证方法,主要用于高级用例:
-
身份验证代理
:在Kubernetes API服务器前使用身份验证代理时,可以配置API服务器使用特定的HTTP头从请求中提取身份验证用户信息。即身份验证代理负责验证用户身份,并将信息作为额外的头随请求一起传递。更多信息可参考官方文档(https://kubernetes.io/docs/reference/access-authn-authz/authentication/#authenticating-proxy)。
-
Webhook令牌身份验证
:Kubernetes API服务器使用外部服务验证承载令牌。API服务器通过HTTP POST请求将TokenReview对象发送给外部服务,外部服务进行验证并返回包含结果信息的TokenReview对象。更多信息可参考官方文档(https://kubernetes.io/docs/reference/access-authn-authz/authentication/#webhook-token-authentication)。
综上所述,在配置Kubernetes的身份验证时,尤其是在云环境中部署生产集群,OIDC是最佳选择。但不同的身份验证方法适用于不同的场景,需要根据实际需求进行选择。
超级会员免费看
1144

被折叠的 条评论
为什么被折叠?



