认证相关问题
目前主流是RBAC认证
官方文档地址
划重点的一段话
-
尽管无法通过 API 调用来添加普通用户,Kubernetes 仍然认为能够提供由集群的证书 机构签名的合法证书的用户是通过身份认证的用户。基于这样的配置,Kubernetes 使用证书中的 'subject' 的通用名称(Common Name)字段(例如,"/CN=bob")来 确定用户名。接下来,基于角色访问控制(RBAC)子系统会确定用户是否有权针对 某资源执行特定的操作。进一步的细节可参阅 证书请求 下普通用户主题。
-
与此不同,服务账号是 Kubernetes API 所管理的用户。它们被绑定到特定的名字空间, 或者由 API 服务器自动创建,或者通过 API 调用创建。服务账号与一组以 Secret 保存 的凭据相关,这些凭据会被挂载到 Pod 中,从而允许集群内的进程访问 Kubernetes API。
-
API 请求则或者与某普通用户相关联,或者与某服务账号相关联,亦或者被视作 匿名请求。这意味着集群内外的每个进程在向 API 服务器发起 请求时都必须通过身份认证,否则会被视作匿名用户。这里的进程可以是在某工作站上 输入 kubectl 命令的操作人员,也可以是节点上的 kubelet 组件,还可以是控制面 的成员。
点击查看代码
openssl x509 -in /etc/kubernetes/pki/front-proxy-ca.crt -noout -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 0 (0x0)
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN = front-proxy-ca
Validity
Not Before: Mar 5 11:42:53 2022 GMT
Not After : Mar 2 11:42:53 2032 GMT
Subject: CN = front-proxy-ca
下面回用两种方式来创建kubeconfig 文件 sa and ca
sa method
点击查看代码
#!/bin/bash
set -e
set -o pipefail
# Add user to k8s using service account, no RBAC (must create RBAC after this script)
if [[ -z "$1" ]] || [[ -z "$2" ]]; then
echo "usage: $0 <service_account_name> <namespace>"
exit 1
fi
SERVICE_ACCOUNT_NAME=$1
NAMESPACE="$2"
KUBECFG_FILE_NAME="/tmp/kube/k8s-${SERVICE_ACCOUNT_NAME}-${NAMESPACE}-conf"
TARGET_FOLDER="/tmp/kube"
create_target_folder() {
echo -n "Creating target directory to hold files in ${TARGET_FOLDER}..."
mkdir -p "${TARGET_FOLDER}"
printf "done"
}
create_service_account() {
echo -e "\\nCreating a service account in ${NAMESPACE} namespace: ${SERVICE_ACCOUNT_NAME}"
kubectl create sa "${SERVICE_ACCOUNT_NAME}" --namespace "${NAMESPACE}"
}
get_secret_name_from_service_account() {
echo -e "\\nGetting secret of service account ${SERVICE_ACCOUNT_NAME} on ${NAMESPACE}"
SECRET_NAME=$(kubectl get sa "${SERVICE_ACCOUNT_NAME}" --namespace="${NAMESPACE}" -o json | jq -r .secrets[].name)
echo "Secret name: ${SECRET_NAME}"
}
extract_ca_crt_from_secret() {
echo -e -n "\\nExtracting ca.crt from secret..."
kubectl get secret --namespace "${NAMESPACE}" "${SECRET_NAME}" -o json | jq \
-r '.data["ca.crt"]' | base64 -D > "${TARGET_FOLDER}/ca.crt"
printf "done"
}
get_user_token_from_secret() {
echo -e -n "\\nGetting user token from secret..."
USER_TOKEN=$(kubectl get secret --namespace "${NAMESPACE}" "${SECRET_NAME}" -o json | jq -r '.data["token"]' | base64 -D)
printf "done"
}
set_kube_config_values() {
context=$(kubectl config current-context)
echo -e "\\nSetting current context to: $context"
CLUSTER_NAME=$(kubectl config get-contexts "$context" | awk '{print $3}' | tail -n 1)
echo "Cluster name: ${CLUSTER_NAME}"
ENDPOINT=$(kubectl config view \
-o jsonpath="{.clusters[?(@.name == \"${CLUSTER_NAME}\")].cluster.server}")
echo "Endpoint: ${ENDPOINT}"
# Set up the config
echo -e "\\nPreparing k8s-${SERVICE_ACCOUNT_NAME}-${NAMESPACE}-conf"
echo -n "Setting a cluster entry in kubeconfig..."
kubectl config set-cluster "${CLUSTER_NAME}" \
--kubeconfig="${KUBECFG_FILE_NAME}" \
--server="${ENDPOINT}" \
--certificate-authority="${TARGET_FOLDER}/ca.crt" \
--embed-certs=true
echo -n "Setting token credentials entry in kubeconfig..."
kubectl config set-credentials \
"${SERVICE_ACCOUNT_NAME}-${NAMESPACE}-${CLUSTER_NAME}" \
--kubeconfig="${KUBECFG_FILE_NAME}" \
--token="${USER_TOKEN}"
echo -n "Setting a context entry in kubeconfig..."
kubectl config set-context \
"${SERVICE_ACCOUNT_NAME}-${NAMESPACE}-${CLUSTER_NAME}" \
--kubeconfig="${KUBECFG_FILE_NAME}" \
--cluster="${CLUSTER_NAME}" \
--user="${SERVICE_ACCOUNT_NAME}-${NAMESPACE}-${CLUSTER_NAME}" \
--namespace="${NAMESPACE}"
echo -n "Setting the current-context in the kubeconfig file..."
kubectl config use-context "${SERVICE_ACCOUNT_NAME}-${NAMESPACE}-${CLUSTER_NAME}" \
--kubeconfig="${KUBECFG_FILE_NAME}"
}
create_target_folder
create_service_account
get_secret_name_from_service_account
extract_ca_crt_from_secret
get_user_token_from_secret
set_kube_config_values
echo -e "\\nAll done! Test with:"
echo "KUBECONFIG=${KUBECFG_FILE_NAME} kubectl get pods"
echo "you should not have any permissions by default - you have just created the authentication part"
echo "You will need to create RBAC permissions"
KUBECONFIG=${KUBECFG_FILE_NAME} kubectl get pods
ca method
点击查看代码
mkdir zhengshu
cd zhengshu
cp ~/.kube/config .
编辑当前目录下的config 文件更改用户名为 song
#生产 csr
openssl genrsa -out song.key 2048
openssl req -new -key song.key -out song.csr -subj "/CN=song/O=lovexlq"
# 获取证书
kubectl certificate approve song123
kubectl get csr song123 -o jsonpath='{.status.certificate}'| base64 -d > myuser.crt
# 生产 csr 对象
cat <<EOF | kubectl apply -f -
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: song123
spec:
request: `cat song.csr | base64 | tr -d "\n"`
signerName: kubernetes.io/kube-apiserver-client
expirationSeconds: 600 # one day
usages:
- client auth
EOF
# 生成 rolebind
kubectl create role developer --verb=create --verb=get --verb=list --verb=update --verb=delete --resource=pods
kubectl create rolebinding developer-binding-song --role=developer --user=song
# 设置 rolebind
KUBECONFIG=./config kubectl config set-credentials song --client-certificate=/root/zhengshu/song.crt --client-key=`pwd`/song.key --embed-certs=true
kubectl create rolebinding developer-binding-song --role=developer --user=song
KUBECONFIG=./config kubectl get pod
证书会不会过期,过期有什么影响
官方文档给你介绍了很多,为了防止集群之间api 错误调用引发的问题。集群之间的通信要依靠tls 双向认证去做。一个集群由一个独立的CA系统提供证书。各个组件启动命令行有 -- bootstrap-config 的配置项,例如向kubelet 这个组件启动流程
在启动 kubelet 时,如果 --kubeconfig 标志所指定的文件并不存在,会使用通过标志 --bootstrap-kubeconfig 所指定的启动引导 kubeconfig 配置来向 API 服务器请求 客户端证书。在证书请求被批复并被 kubelet 收回时,一个引用所生成的密钥和所获得 证书的 kubeconfig 文件会被写入到通过 --kubeconfig 所指定的文件路径下。 证书和密钥文件会被放到 --cert-dir 所指定的目录中。
由于我们的集群体系是以kubeadm 的方式进行的安装,主要组件apiserver controller schedluer kube-proxy 默认运行在容器模式下 启动依赖的kubeconfig 文件中使用的是是token。 理论上我们只需要保证kubelet 和 etcd 集群的证书健康即可。
kubelet 证书自动approve
点击查看代码
kubeadm certs 命令使用
聚合层的apiserver 概念
配置聚合层 可以允许 Kubernetes apiserver 使用其它 API 扩展,这些 API 不是核心 Kubernetes API 的一部分。
通俗一点翻译就是,你可以向apiserver 中注册api 。当有请求到apiserver 时,通过鉴权后这部分流量会转发到对应的服务上,下面已常用的metrics-server 为例子说明一下:
点击查看代码
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:"
labels:
k8s-app: metrics-server
name: v1beta1.metrics.k8s.io
spec:
group: metrics.k8s.io
groupPriorityMinimum: 100
insecureSkipTLSVerify: true
service:
name: metrics-server
namespace: kube-system
port: 443
version: v1beta1
versionPriority: 100
---
当有服务要请求v1beta1.metrics.k8s.io流程如下:
1. 请求到达apiserver
2. 进行鉴权(OIDC或者certs),鉴权通过进行下一步,不通过直接返回错误
3. 鉴权通过后使用 front-proxy-client.ca 来进行服务请求到对应的服务metrics-server
4.扩展 apiserver:对来自原始用户的请求鉴权
5. metrics-server 处理请求后返回