k8s 新建用户远程连接集群和context切换
一、kubectl 远程连接cluster
1、kubectl是k8s的客户端程序,也是k8s的命令行工具,kubectl提供了大量的子命令可以让用户和集群进行交互。
kubectl操作k8s集群对象是通过调用 k8s API实现的
kubectl不一定部署在master上,也可以在内网的私人笔记本上,开发或者运维人员只有config文件和kubectl工具就可操作k8s集群。
2、默认情况下是默认连接本地的apiserver,也可以使用https连接集群。
一般情况下,在k8s 的 master节点上kubectl是连接的本地http 8080端口和apiserver进行通讯的,当然也可以通过https端口进行通讯前提是要生成证书。所以说
kubectl -s 127.0.0.1:8080 get node ###二进制老版本
配置kubectl使用apiserver安全的https端口(6443)连接集群
使用脚本快速添加用户
#!/bin/bash # 每个对应一个namespace,用户名和namespace名称相同 # 注意修改KUBE_APISERVER为你的API Server的地址 KUBE_APISERVER=$1 USER=$2 USAGE="USAGE: create-user.sh <api_server> <username>\n Example: https://192.168.40.134:6443 ops" CSR=`pwd`/user-crt.json SSL_PATH="/root/cfssl" SSL_FILES=(ca-key.pem ca.pem ca-config.json) CERT_FILES=(${USER}.csr $USER-key.pem ${USER}.pem) if [[ $KUBE_APISERVER == "" ]]; then echo -e $USAGE exit 1 fi if [[ $USER == "" ]];then echo -e $USAGE exit 1 fi # 创建用户的csr文件 function createCSR(){ cat>$CSR<<EOF { "CN": "USER", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "k8s", "OU": "System" } ] } EOF # 替换csr文件中的用户名 sed -i "s/USER/$USER/g" $CSR } echo "Create CSR file..." createCSR echo "$CSR created" function ifExist(){ if [ ! -f "$SSL_PATH/$1" ]; then echo "$SSL_PATH/$1 not found." exit 1 fi } ##创建证书配置模板ca-config.json文件 cat > $SSL_PATH/ca-config.json <<EOF { "signing": { "default": { "expiry": "87600h" }, "profiles": { "kubernetes": { "usages": [ "signing", "key encipherment", "server auth", "client auth" ], "expiry": "87600h" } } } } EOF # 判断证书文件是否存在 for f in ${SSL_FILES[@]}; do echo "Check if ssl file $f exist..." ifExist $f echo "OK" done echo "Create user's certificates and keys..." cd $SSL_PATH cfssl gencert -ca=/etc/kubernetes/pki/ca.crt -ca-key=/etc/kubernetes/pki/ca.key -config=ca-config.json -profile=kubernetes $CSR| cfssljson -bare $USER cd - # 设置集群参数 kubectl config set-cluster kubernetes \ --certificate-authority=${SSL_PATH}/ca.pem \ --embed-certs=true \ --server=${KUBE_APISERVER} \ --kubeconfig=${USER}.kubeconfig # 设置客户端认证参数 kubectl config set-credentials $USER \ --client-certificate=$SSL_PATH/${USER}.pem \ --client-key=$SSL_PATH/${USER}-key.pem \ --embed-certs=true \ --kubeconfig=${USER}.kubeconfig # 设置上下文参数 kubectl config set-context kubernetes \ --cluster=kubernetes \ --user=$USER \ --namespace=$USER \ --kubeconfig=${USER}.kubeconfig # 设置默认上下文 kubectl config use-context kubernetes --kubeconfig=${USER}.kubeconfig # 创建 namespace kubectl create ns $USER # 绑定角色 kubectl create rolebinding ${USER}-admin-binding --clusterrole=admin --user=$USER --namespace=$USER --serviceaccount=$USER:default kubectl config get-contexts echo "Congratulations!" echo "Your kubeconfig file is ${USER}.kubeconfig"
注意:
如果是kubeadm方式搭建的k8s环境:
cp /etc/kubernetes/pki/ca.crt /root/cfssl/ca.pem cp /etc/kubernetes/pki/ca.key /root/cfssl/ca-key.pem
3、 使用cfssl签发证书
生成pem和key.pem文件
###集群之前已经有了ca证书那就不需要在生成了,只需要利用该ca证书生成用户证书即可。 cat > ca-config.json <<EOF { "signing": { "default": { "expiry": "87600h" }, "profiles": { "kubernetes": { "usages": [ "signing", "key encipherment", "server auth", "client auth" ], "expiry": "87600h" } } } } EOF
signing
:表示该证书可用于签名其它证书;生成的 ca.pem 证书中 CA=TRUE
;
server auth
:表示可以用该 CA 对 server 提供的证书进行验证;
client auth
:表示可以用该 CA 对 client 提供的证书进行验证;
profile kubernetes
包含了server auth
和client auth
,所以可以签发三种不同类型证书;
expiry 证书有效期,默认50年
cat > zjz-csr.json <<EOF { "CN": "zjz", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "system:masters", "OU": "System" } ] } EOF
注:
- CN就是要创建的用户名,Common Name,kube-apiserver 从证书中提取该字段作为请求的用户名 (User Name)
- profile= 对应的是ca-config.json中的profiles字段
- 证书请求中
O
指定该证书的 Group 为system:masters
,而RBAC
预定义的ClusterRoleBinding
将 Groupsystem:masters
与 ClusterRolecluster-admin
绑定,这就赋予了用户所有集群权限
$ kubectl describe clusterrolebinding cluster-admin Name: cluster-admin Labels: kubernetes.io/bootstrapping=rbac-defaults Annotations: rbac.authorization.kubernetes.io/autoupdate=true Role: Kind: ClusterRole Name: cluster-admin Subjects: Kind Name Namespace ---- ---- --------- Group system:masters
生成zjz用户的证书
cfssl gencert -ca=/etc/kubernetes/pki/ca.crt -ca-key=/etc/kubernetes/pki/ca.key \ -config=ca-config.json -profile=kubernetes zjz-csr.json | cfssljson -bare zjz
查看证书
# ls admin* zjz.csr zjz-csr.json zjz-key.pem zjz.pem
5、配置config
拷贝证书以及相关kubectl到目标机器
scp /opt/kubernetes/bin/kubectl 10.1.210.32:/usr/bin #拷贝kubectl二进制可执行文件 scp zjz* ca.pem 10.1.210.32:/opt/kubernetes/kubectl/ssl # 拷贝证书
配置config和kubectl
#进入证书目录 cd /opt/kubernetes/kubectl/ssl #配置访问的集群 kubectl config set-cluster k8s-cluster1 --server=https://10.25.72.62:6443 --certificate-authority=ca.pem --embed-certs=true Cluster "k8s-cluster1" set. #配置访问特定的集群、特定的context、特定的namespace kubectl config set-context kube-system-ctx --cluster=k8s-cluster1 --user=kubectl --namespace=kube-system Context "kube-system-ctx" modified. #设置用户项中cluster-admin用户证书认证字段 kubectl config set-credentials cluster-admin --certificate-authority=ca.pem --client-key=admin-key.pem --client-certificate=admin.pem #设置默认上下文 kubectl config set-context default --cluster=kubernetes --user=cluster-admin #切换上下文context kubectl config use-context kube-system-ctx Switched to context "kube-system-ctx".
查看config文件
# kubectl config view apiVersion: v1 clusters: - cluster: certificate-authority: /opt/kubernetes/kubectl/ssl/ca.pem server: https://10.1.210.33:6443 name: kubernetes contexts: - context: cluster: kubernetes user: cluster-admin name: default current-context: default kind: Config preferences: {} users: - name: cluster-admin user: client-certificate: /opt/kubernetes/kubectl/ssl/admin.pem client-key: /opt/kubernetes/kubectl/ssl/admin-key.pem
将kubeconfig和kubelet可执行文件拷贝到远程主机或者笔记本上即可(笔记本要有vpn ping得通内网的服务器)
cp zjz.kubeconfig ~/.kube/config
二、context的理解
context:背景,环境,上下文
对上下文(context)的理解:集群包含context,一个k8s集群中可以有多个context,比如ops、dev、lead。在不同的上下文中,资源是相互隔离的,互不干扰。
k8s集群可以通过namespace和context的设置来对不同的工作组进行区分,同一集群,不同的namespace下,不同context,资源隔离,互不干扰。而同一集群,同一namespace,不同context,资源做不到隔离。
另外,如果用一台机器管理多个k8s集群,集群切换操作也可以用context实现。
用途:配置对多集群的访问时,context字段定义用户访问凭证
每个上下文包含三部分(集群、用户和名字空间),
例如config配置如下:
apiVersion: v1 clusters: - cluster: certificate-authority: fake-ca-file server: https://1.2.3.4 name: development - cluster: insecure-skip-tls-verify: true server: https://5.6.7.8 name: scratch contexts: - context: cluster: development namespace: frontend user: developer name: dev-frontend - context: cluster: development namespace: storage user: developer name: dev-storage - context: cluster: scratch namespace: default user: experimenter name: exp-scratch current-context: "" kind: Config preferences: {} users: - name: developer user: client-certificate: fake-cert-file client-key: fake-key-file - name: experimenter user: password: some-password username: exp
dev-frontend
上下文表明:使用 developer
用户的凭证来访问 development
集群的 frontend
名字空间。
查看当前的context(是一个合并后的结果)
$ kubectl config view apiVersion: v1 clusters: - cluster: certificate-authority-data: DATA+OMITTED server: https://xx.xx.xx.xx:6443 name: Kubernetes contexts: - context: cluster: Kubernetes namespace: ops user: ops name: Kubernetes current-context: Kubernetes kind: Config preferences: {} users: - name: ops user: client-certificate-data: REDACTED client-key-data: REDACTED
切换context
kubectl config use-context k8s-cluster-name
验证是否已经切换到了新的context
kubectl config current-context Kubernetes
删除context,不影响其下的资源
kubectl config delete-context context1 deleted context context1 from /Users/zhangjingzhi/.kube/config
新增一个context
kubectl config set-context zjz --namespace=zjz-ops --cluster=Kubernetes --user=ops Context "zjz" created.
查看所有的contexts
$ kubectl config get-contexts CURRENT NAME CLUSTER AUTHINFO NAMESPACE * Kubernetes Kubernetes ops ops context3 Kubernetes ops kube-system zjz Kubernetes ops zjz-ops
设置工作上下文,前提是该命名空间已经存在
kubectl config set-context xxx --namespace=xxxx --cluster=xxxx --user=xxxx
在kubeconfig配置文件中设置一个context。 如果指定了一个已存在的名字,将合并新字段并覆盖旧字段。
kubectl config set-context NAME --cluster=cluster_nickname --user=user_nickname --namespace=namespace
示例
# 设置gce环境项中的user字段,不影响其他字段。 $ kubectl config set-context gce --user=cluster-admin
选项
--cluster="": 设置kuebconfig配置文件中环境选项中的集群。 --namespace="": 设置kuebconfig配置文件中环境选项中的命名空间。 --user="": 设置kuebconfig配置文件中环境选项中的用户。
继承自父命令的选项
--alsologtostderr[=false]: 同时输出日志到标准错误控制台和文件。 --api-version="": 和服务端交互使用的API版本。 --certificate-authority="": 用以进行认证授权的.cert文件路径。 --client-certificate="": TLS使用的客户端证书路径。 --client-key="": TLS使用的客户端密钥路径。 --cluster="": 指定使用的kubeconfig配置文件中的集群名。 --context="": 指定使用的kubeconfig配置文件中的环境名。 --insecure-skip-tls-verify[=false]: 如果为true,将不会检查服务器凭证的有效性,这会导致你的HTTPS链接变得不安全。 --kubeconfig="": 命令行请求使用的配置文件路径。 --log-backtrace-at=:0: 当日志长度超过定义的行数时,忽略堆栈信息。 --log-dir="": 如果不为空,将日志文件写入此目录。 --log-flush-frequency=5s: 刷新日志的最大时间间隔。 --logtostderr[=true]: 输出日志到标准错误控制台,不输出到文件。 --match-server-version[=false]: 要求服务端和客户端版本匹配。 --namespace="": 如果不为空,命令将使用此namespace。 --password="": API Server进行简单认证使用的密码。 -s, --server="": Kubernetes API Server的地址和端口号。 --stderrthreshold=2: 高于此级别的日志将被输出到错误控制台。 --token="": 认证到API Server使用的令牌。 --user="": 指定使用的kubeconfig配置文件中的用户名。 --username="": API Server进行简单认证使用的用户名。 --v=0: 指定输出日志的级别。 --vmodule=: 指定输出日志的模块,格式如下:pattern=N,使用逗号分隔。
测试同一集群中,不同namespace下,不同的context,二者之间的关系
#当前的context如下 kubectl config current-context Kubernetes #在Kubernetes中创建rc资源 kubectl apply -f redis.yaml replicationcontroller/redis-slave created $ kubectl get rc NAME DESIRED CURRENT READY AGE redis-slave 2 2 0 11s #切换到zjz-ops这个context下 $ kubectl config use-context zjz-ops Switched to context "zjz-ops". 查看资源,正常输出是 No resources found in zjz-ops namespace. $ kubectl get rc The connection to the server localhost:8080 was refused - did you specify the right host or port
测试同一个集群,同一个namespace下,不同的context,二者关系
#查看现有的context,zjz1和Kubernetes属于同一集群同一namespace下: kubectl config get-contexts CURRENT NAME CLUSTER AUTHINFO NAMESPACE * Kubernetes Kubernetes ops ops context3 Kubernetes ops kube-system zjz Kubernetes ops zjz-ops zjz1 Kubernetes ops ops #切换到zjz1 kubectl config use-context zjz1 Switched to context "zjz1". #创建资源、查看 $ kubectl create deployment web --image=nginx -n ops deployment.apps/web created $ kubectl get deployment -n ops NAME READY UP-TO-DATE AVAILABLE AGE postgresql 1/1 1 1 41d web 1/1 1 1 21s #切换到Kubernetes kubectl config use-context Kubernetes Switched to context "Kubernetes". $ kubectl config current-context Kubernetes #可以查看zjz1创建的资源,也可以删除 $ kubectl get deployment -n ops NAME READY UP-TO-DATE AVAILABLE AGE postgresql 1/1 1 1 41d web 1/1 1 1 4m13s kubectl delete deployment web -n ops deployment.apps "web" deleted
三、创建用户的shell脚本(cfssl工具生成证书)
#!/usr/bin/env bash # 注意修改KUBE_APISERVER为你的API Server的地址 KUBE_APISERVER=$1 USER=$2 USER_SA=system:serviceaccount:default:${USER} Authorization=$3 USAGE="USAGE: create-user.sh <api_server> <username> <clusterrole authorization>\n Example: https://192.168.1.2:6443 brand" CSR=`pwd`/user-csr.json SSL_PATH="/opt/kubernetes/ssl" USER_SSL_PATH="/opt/kubernetes/create-user" SSL_FILES=(ca-key.pem ca.pem ca-config.json) CERT_FILES=(${USER}.csr $USER-key.pem ${USER}.pem) if [[ $KUBE_APISERVER == "" ]]; then echo -e $USAGE exit 1 fi if [[ $USER == "" ]];then echo -e $USAGE exit 1 fi if [[ $Authorization == "" ]];then echo -e $USAGE exit 1 fi # 创建用户的csr文件 function createCSR(){ cat>$CSR<<EOF { "CN": "USER", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "k8s", "OU": "System" } ] } EOF # 替换csr文件中的用户名 sed -i "s/USER/$USER_SA/g" $CSR } function ifExist(){ if [ ! -f "$SSL_PATH/$1" ]; then echo "$SSL_PATH/$1 not found." exit 1 fi } function ifClusterrole(){ kubectl get clusterrole ${Authorization} &> /dev/null if (( $? !=0 ));then echo "${Authorization} clusterrole there is no" exit 1 fi } # 判断clusterrole授权是否存在 ifClusterrole # 判断证书文件是否存在 for f in ${SSL_FILES[@]}; do echo "Check if ssl file $f exist..." ifExist $f echo "OK" done echo "Create CSR file..." createCSR echo "$CSR created" echo "Create user's certificates and keys..." cd $USER_SSL_PATH cfssl gencert -ca=${SSL_PATH}/ca.pem -ca-key=${SSL_PATH}/ca-key.pem -config=${SSL_PATH}/ca-config.json -profile=kubernetes $CSR| cfssljson -bare $USER_SA # 创建 sa kubectl create sa ${USER} -n default # 设置集群参数 kubectl config set-cluster kubernetes \ --certificate-authority=${SSL_PATH}/ca.pem \ --embed-certs=true \ --server=${KUBE_APISERVER} \ --kubeconfig=${USER}.kubeconfig # 设置客户端认证参数 kubectl config set-credentials ${USER_SA} \ --client-certificate=${USER_SSL_PATH}/${USER_SA}.pem \ --client-key=${USER_SSL_PATH}/${USER_SA}-key.pem \ --embed-certs=true \ --kubeconfig=${USER}.kubeconfig # 设置上下文参数 kubectl config set-context kubernetes \ --cluster=kubernetes \ --user=${USER_SA} \ --namespace=development \ --kubeconfig=${USER}.kubeconfig # 设置默认上下文 kubectl config use-context kubernetes --kubeconfig=${USER}.kubeconfig # 创建 namespace # kubectl create ns $USER # 绑定角色 # kubectl create rolebinding ${USER}-admin-binding --clusterrole=admin --user=$USER --namespace=$USER --serviceaccount=$USER:default kubectl create clusterrolebinding ${USER}-binding --clusterrole=${Authorization} --user=${USER_SA} # kubectl config get-contexts echo "Congratulations!" echo "Your kubeconfig file is ${USER}.kubeconfig"
context和kubeconfig的详细信息可参考官网:
https://kubernetes.io/zh/docs/concepts/configuration/organize-cluster-access-kubeconfig/#%E4%B8%8A%E4%B8%8B%E6%96%87-context https://kubernetes.io/zh/docs/tasks/access-application-cluster/configure-access-multiple-clusters/#set-the-kubeconfig-environment-variable
https://blog.csdn.net/zhangxiangui40542/article/details/81672578/ kubectl config配置示例
https://blog.csdn.net/ywq935/article/details/84840935 K8S基础-鉴权框架与用户权限分配,整理详细
用户认证ServiceAccount与授权策略RBAC · Devops Roadmap (curiouser.top)