认证、授权与准入控制(二)
一、Kubernetes Dashboard
Dashboard 是Kubernetes的web GUI,可用于在Kubernetes集群上部署容器化应用、应用排障、管理集群本身及其附加的资源等。它常被管理员用于集群及应用速览、创建或修改单个资源(如Deployments、Jobs和DaemonSets等),以及扩展Deployment、启动滚动更新、重启Pod或使用部署向导部署一个应用等。
注:Dashboard依赖于Heapster或Metrics Server完成指标数据的采集和可视化
Dashboard的认证和授权均可由Kubernetes集群实现,它自身仅是一个代理,所有的相关操作都将发给API Server进行,而非由Dashboard自行完成。目前它支持使用的认证方式有承载令牌(bear token)和kubeconfig两种,在访问之前需要准备好相应的认证凭证。
1. 部署HTTPS通信的Dashboard
Dashboard 1.7(不含)之前的版本在部署时直接赋予了管理权限,这种方式可能存在安全风险,因此,1.7及之后的版本默认在部署时仅定义了运行Dashboard所需要的最小权限,仅能够在Master主机上通过“kubectl proxy”命令创建代理后于本机进行访问,它默认禁止了来自于其他任何主机的访问请求。若要绕过“kubectl proxy”直接访问Dashboard,则需要在部署时提供证书以便与客户端进行通信时建立一个安全的HTTPS连接。证书既可由公信CA颁发,也可自行使用openssl或cfssl一类的工具来创建。
部署Dashboard时会从Secrets对象中加载所需要的私钥和证书文件,需要事先准备好相关的私钥、证书和Secrets对象。下面命令需要以管理员的身份在Master节点上运行,否则将无法访问到ca.key文件:
[root@k8s-master1 ~]# mkdir dashboard [root@k8s-master1 ~]# cd dashboard/ [root@k8s-master1 dashboard]# [root@k8s-master1 dashboard]# (umask 077;openssl genrsa -out dashboard.key 2048) Generating RSA private key, 2048 bit long modulus ..........+++ ..........+++ e is 65537 (0x10001) [root@k8s-master1 dashboard]# ls -lrt total 4 -rw------- 1 root root 1679 Nov 3 21:15 dashboard.key [root@k8s-master1 dashboard]# openssl req -new -key dashboard.key -out dashboard.csr -subj "/O=iLinux/CN=dashboard" [root@k8s-master1 dashboard]# ls -lrt total 8 -rw------- 1 root root 1679 Nov 3 21:15 dashboard.key -rw-r--r-- 1 root root 915 Nov 3 21:16 dashboard.csr [root@k8s-master1 dashboard]# openssl x509 -req -in dashboard.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out dashboard.crt -days 3650 Signature ok subject=/O=iLinux/CN=dashboard Getting CA Private Key [root@k8s-master1 dashboard]# ls -lrt total 12 -rw------- 1 root root 1679 Nov 3 21:15 dashboard.key -rw-r--r-- 1 root root 915 Nov 3 21:16 dashboard.csr -rw-r--r-- 1 root root 1001 Nov 3 21:18 dashboard.crt
接下来,基于生成的私钥和证书文件创建名为kubernetes-dashboard-certs的Opaque类型的Secret对象,其键名分别为dashboard.key和dashboard.crt:
[root@k8s-master1 dashboard]# kubectl create ns kubernetes-dashboard namespace/kubernetes-dashboard created You have new mail in /var/spool/mail/root [root@k8s-master1 dashboard]# kubectl create secret generic kubernetes-dashboard-certs --from-file=dashboard.crt=./dashboard.crt --from-file=dashboard.key=./dashboard.key -n kubernetes-dashboard secret/kubernetes-dashboard-certs created [root@k8s-master1 dashboard]# kubectl get secrets kubernetes-dashboard-certs -n kubernetes-dashboard NAME TYPE DATA AGE kubernetes-dashboard-certs Opaque 2 19s [root@k8s-master1 dashboard]# kubectl describe secrets kubernetes-dashboard-certs -n kubernetes-dashboard Name: kubernetes-dashboard-certs Namespace: kubernetes-dashboard Labels: <none> Annotations: <none> Type: Opaque Data ==== dashboard.crt: 1001 bytes dashboard.key: 1679 bytes
Secret对象准备完成后即可部署Dashboard。Dashboard配置清单文件如下,清单中也创建了NameSpace和Secrets对象,因此,创建过程中可能会发出告警信息。
[root@k8s-master1 dashboard]# cat kubernetes-dashboard.yaml
# Copyright 2017 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: v1
kind: Namespace
metadata:
name: kubernetes-dashboard
---
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
---
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
ports:
- port: 443
targetPort: 8443
selector:
k8s-app: kubernetes-dashboard
---
apiVersion: v1
kind: Secret
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-certs
namespace: kubernetes-dashboard
type: Opaque
---
apiVersion: v1
kind: Secret
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-csrf
namespace: kubernetes-dashboard
type: Opaque
data:
csrf: ""
---
apiVersion: v1
kind: Secret
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-key-holder
namespace: kubernetes-dashboard
type: Opaque
---
kind: ConfigMap
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-settings
namespace: kubernetes-dashboard
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
rules:
# Allow Dashboard to get, update and delete Dashboard exclusive secrets.
- apiGroups: [""]
resources: ["secrets"]
resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs", "kubernetes-dashboard-csrf"]
verbs: ["get", "update", "delete"]
# Allow Dashboard to get and update 'kubernetes-dashboard-settings' config map.
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["kubernetes-dashboard-settings"]
verbs: ["get", "update"]
# Allow Dashboard to get metrics.
- apiGroups: [""]
resources: ["services"]
resourceNames: ["heapster", "dashboard-metrics-scraper"]
verbs: ["proxy"]
- apiGroups: [""]
resources: ["services/proxy"]
resourceNames: ["heapster", "http:heapster:", "https:heapster:", "dashboard-metrics-scraper", "http:dashboard-metrics-scraper"]
verbs: ["get"]
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
rules:
# Allow Metrics Scraper to get metrics from the Metrics server
- apiGroups: ["metrics.k8s.io"]
resources: ["pods", "nodes"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: kubernetes-dashboard
subjects:
- kind: ServiceAccount
name: kubernetes-dashboard
namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kubernetes-dashboard
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: kubernetes-dashboard
subjects:
- kind: ServiceAccount
name: kubernetes-dashboard
namespace: kubernetes-dashboard
---
kind: Deployment
apiVersion: apps/v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
k8s-app: kubernetes-dashboard
template:
metadata:
labels:
k8s-app: kubernetes-dashboard
spec:
containers:
- name: kubernetes-dashboard
image: kubernetesui/dashboard:v2.0.0-beta8
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8443
protocol: TCP
args:
- --auto-generate-certificates
- --namespace=kubernetes-dashboard
# Uncomment the following line to manually specify Kubernetes API server Host
# If not specified, Dashboard will attempt to auto discover the API server and connect
# to it. Uncomment only if the default does not work.
# - --apiserver-host=http://my-address:port
volumeMounts:
- name: kubernetes-dashboard-certs
mountPath: /certs
# Create on-disk volume to store exec logs
- mountPath: /tmp
name: tmp-volume
livenessProbe:
httpGet:
scheme: HTTPS
path: /
port: 8443
initialDelaySeconds: 30
timeoutSeconds: 30
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsUser: 1001
runAsGroup: 2001
volumes:
- name: kubernetes-dashboard-certs
secret:
secretName: kubernetes-dashboard-certs
- name: tmp-volume
emptyDir: {}
serviceAccountName: kubernetes-dashboard
nodeSelector:
"beta.kubernetes.io/os": linux
# Comment the following tolerations if Dashboard must not be deployed on master
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
---
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: dashboard-metrics-scraper
name: dashboard-metrics-scraper
namespace: kubernetes-dashboard
spec:
ports:
- port: 8000
targetPort: 8000
selector:
k8s-app: dashboard-metrics-scraper
---
kind: Deployment
apiVersion: apps/v1
metadata:
labels:
k8s-app: dashboard-metrics-scraper
name: dashboard-metrics-scraper
namespace: kubernetes-dashboard
spec:
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
k8s-app: dashboard-metrics-scraper
template:
metadata:
labels:
k8s-app: dashboard-metrics-scraper
annotations:
seccomp.security.alpha.kubernetes.io/pod: 'runtime/default'
spec:
containers:
- name: dashboard-metrics-scraper
image: kubernetesui/metrics-scraper:v1.0.1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8000
protocol: TCP
livenessProbe:
httpGet:
scheme: HTTP
path: /
port: 8000
initialDelaySeconds: 30
timeoutSeconds: 30
volumeMounts:
- mountPath: /tmp
name: tmp-volume
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsUser: 1001
runAsGroup: 2001
serviceAccountName: kubernetes-dashboard
nodeSelector:
"beta.kubernetes.io/os": linux
# Comment the following tolerations if Dashboard must not be deployed on master
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
volumes:
- name: tmp-volume
emptyDir: {}
创建dashboard命令如下:
[root@k8s-master1 dashboard]# kubectl apply -f kubernetes-dashboard.yaml Warning: resource namespaces/kubernetes-dashboard is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by kubectl apply. kubectl apply should only be used on resources created declaratively by either kubectl create --save-config or kubectl apply. The missing annotation will be patched automatically. namespace/kubernetes-dashboard configured serviceaccount/kubernetes-dashboard created service/kubernetes-dashboard created Warning: resource secrets/kubernetes-dashboard-certs is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by kubectl apply. kubectl apply should only be used on resources created declaratively by either kubectl create --save-config or kubectl apply. The missing annotation will be patched automatically. secret/kubernetes-dashboard-certs configured secret/kubernetes-dashboard-csrf created secret/kubernetes-dashboard-key-holder created configmap/kubernetes-dashboard-settings created role.rbac.authorization.k8s.io/kubernetes-dashboard created clusterrole.rbac.authorization.k8s.io/kubernetes-dashboard unchanged rolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created clusterrolebinding.rbac.authorization.k8s.io/kubernetes-dashboard unchanged deployment.apps/kubernetes-dashboard created service/dashboard-metrics-scraper created deployment.apps/dashboard-metrics-scraper created
查看创建的资源信息如下:
[root@k8s-master1 dashboard]# kubectl get pods -n kubernetes-dashboard NAME READY STATUS RESTARTS AGE dashboard-metrics-scraper-7445d59dfd-5875f 1/1 Running 0 3m kubernetes-dashboard-54f5b6dc4b-wz68l 1/1 Running 0 3m You have new mail in /var/spool/mail/root [root@k8s-master1 dashboard]# kubectl get svc -n kubernetes-dashboard NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE dashboard-metrics-scraper ClusterIP 10.97.28.167 <none> 8000/TCP 3m11s kubernetes-dashboard ClusterIP 10.98.71.77 <none> 443/TCP 3m12s
可以看到创建的Service对象类型为ClusterIP,它仅能在Pod客户端中访问,若需要在集群外通过浏览器访问Dashboard,则需要将其修改成NodePort类型:

[root@k8s-master1 dashboard]# kubectl edit svc kubernetes-dashboard -n kubernetes-dashboard service/kubernetes-dashboard edited You have new mail in /var/spool/mail/root [root@k8s-master1 dashboard]# kubectl get svc -n kubernetes-dashboard NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE dashboard-metrics-scraper ClusterIP 10.97.28.167 <none> 8000/TCP 8m25s kubernetes-dashboard NodePort 10.98.71.77 <none> 443:30302/TCP 8m26s
确定其使用的NodePort之后,便可在集群外通过浏览器进行访问,输入https://10.0.0.131:30302,则显示如下图,下图为其默认的登录页面,支持的认证方式为kubeconfig和token两种:

Dashboard是运行于Pod对象中的应用,其连接API Server的账户应为ServiceAccount类型,因此,用户在登录页面提供的用户账号须得是此类账户,而且访问权限也取决于kubeconfig或token认证时的ServiceAccount用户的权限。ServiceAccount的集群资源访问权限取决于它绑定的角色或集群角色。
2. 配置token认证
集群级别的管理操作依赖于集群管理员的权限。例如,管理持久存储卷和名称空间等资源,内建的cluster-admin集群角色拥有相关的全部权限,创建ServiceAccount并将其绑定其上即可完成集群管理员授权。而用户通过相应的ServiceAccount的token信息完成Dashboard认证也就能扮演起Dashboard接口上的集群管理员角色。例如上面创建的名为kubernetes-dashboard的ServiceAccount,完成集群角色绑定,使其具有管理员权限:
[root@k8s-master1 ~]# kubectl get sa -n kubernetes-dashboard NAME SECRETS AGE default 1 2d22h kubernetes-dashboard 1 2d22h [root@k8s-master1 ~]# kubectl create clusterrolebinding dashboard-cluster-admin --clusterrole=cluster-admin --serviceaccount=kubernetes-dashboard:kubernetes-dashboard clusterrolebinding.rbac.authorization.k8s.io/dashboard-cluster-admin created [root@k8s-master1 ~]# kubectl get clusterrolebinding dashboard-cluster-admin NAME ROLE AGE dashboard-cluster-admin ClusterRole/cluster-admin 14s
创建ServiceAccount对象时,它会自动为用户生成用于认证的token信息,这一点可以从与其相关的Secrets对象上获取:
[root@k8s-master1 ~]# kubectl get secrets -n kubernetes-dashboard
NAME TYPE DATA AGE
default-token-9snc4 kubernetes.io/service-account-token 3 2d22h
kubernetes-dashboard-certs Opaque 2 2d22h
kubernetes-dashboard-csrf Opaque 1 2d22h
kubernetes-dashboard-key-holder Opaque 2 2d22h
kubernetes-dashboard-token-s599v kubernetes.io/service-account-token 3 2d22h
You have new mail in /var/spool/mail/root
[root@k8s-master1 ~]# kubectl describe secrets kubernetes-dashboard-token-s599v -n kubernetes-dashboard
Name: kubernetes-dashboard-token-s599v
Namespace: kubernetes-dashboard
Labels: <none>
Annotations: kubernetes.io/service-account.name: kubernetes-dashboard
kubernetes.io/service-account.uid: c7533525-7164-4fc7-801e-68e460851f88
Type: kubernetes.io/service-account-token
Data
====
namespace: 20 bytes
token: eyJhbGciOiJSUzI1NiIsImtpZCI6IkxKVHlZMHFIMWpxRnlOSWRPMmVDQnBPdGFwdWRlbkdrLUpuOG50WUhfbEkifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJrdWJlcm5ldGVzLWRhc2hib2FyZC10b2tlbi1zNTk5diIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6ImM3NTMzNTI1LTcxNjQtNGZjNy04MDFlLTY4ZTQ2MDg1MWY4OCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlcm5ldGVzLWRhc2hib2FyZDprdWJlcm5ldGVzLWRhc2hib2FyZCJ9.SuEBft4utO45S49XEeoxp-3uZevUWnbZopEasiCtzSMaRf4GxrMhaYTerlq66Noh2SjVUeATBqxSJnZxZsGDqdGcblgT4ubfqoSQ6_Supt5x1UfuzV6s9O3GC76c4OcRCwXjzFzw9moAkMRdz67wJ7UdMKw2TY9JN26mVh5qBr4Ws39YbwP045nmr9OVPTjoKrZM4PUsf9_B6JUjrlWvIB55nqPS7GoOO3xdjADrUrwJxWw9ZhXb8uvA6kf3BFb6GbqDaAiRCbd4yN8pVbqmVE7V-zM_YC6ZnPeR2tiNOfTqVnFrQwK-7ugXI9youPW8MG9Kf2daZT6UE32ssSjaow
ca.crt: 1066 bytes
对上面获取到的token在登录界面选择令牌认证方式,并键入token令牌即要登录的Dashboard,其效果如图所示:
点击Sign in后,其效果显示如下图:

上面认证时用到的令牌将采用base64的编码格式,且登录时需要将原内容粘贴入文本框,存储及操作都有不便之处,建议用户将它存入kubeconfig配置文件中,通过kubeconfig的认证方式进行登录。
3. 配置kubeconfig认证
kubeconfig是认证信息承载工具,它能够存入私钥和证书,或者认证令牌等作为用户的认证配置文件。为了说明如何配置一个仅具有特定名称空间管理权限的登录账号,这里创建一个新的ServiceAccount用于管理默认的default名称空间,并将其绑定于admin集群角色:
[root@k8s-master1 dashboard]# kubectl create sa def-ns-admin -n default serviceaccount/def-ns-admin created [root@k8s-master1 dashboard]# kubectl get sa def-ns-admin -n default NAME SECRETS AGE def-ns-admin 1 28s [root@k8s-master1 dashboard]# kubectl create rolebinding def-ns-admin --clusterrole=admin --serviceaccount=default:def-ns-admin rolebinding.rbac.authorization.k8s.io/def-ns-admin created [root@k8s-master1 dashboard]# kubectl get rolebinding def-ns-admin -n default NAME ROLE AGE def-ns-admin ClusterRole/admin 21s
下面分步骤说明如何创建所需的kubeconfig文件。
1)初始化集群信息,提供API Server的URL,以及验证API Server证书所用到的CA证书等。
[root@k8s-master1 dashboard]# kubectl config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://10.0.0.131:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kube-user1
name: kube-user1@kubernetes
- context:
cluster: kubernetes
namespace: default
user: kubernetes-admin
name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kube-user1
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
- name: kubernetes-admin
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
[root@k8s-master1 dashboard]# kubectl config set-cluster kubernetes --embed-certs=true --server="https://10.0.0.131:6443" --certificate-authority=/etc/kubernetes/pki/ca.crt --kubeconfig=./def-ns-admin.kubeconfig
Cluster "kubernetes" set.
[root@k8s-master1 dashboard]# ll
total 24
-rw-r--r-- 1 root root 1001 Nov 3 21:18 dashboard.crt
-rw-r--r-- 1 root root 915 Nov 3 21:16 dashboard.csr
-rw------- 1 root root 1679 Nov 3 21:15 dashboard.key
-rw------- 1 root root 1624 Nov 6 21:01 def-ns-admin.kubeconfig
-rw-r--r-- 1 root root 7614 Nov 3 21:38 kubernetes-dashboard.yaml
[root@k8s-master1 dashboard]# cat def-ns-admin.kubeconfig
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM1ekNDQWMrZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJeU1EZ3dNVEV5TkRNMU1Wb1hEVE15TURjeU9URXlORE0xTVZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTDJOCmRLRjdRZnZqYjkzWExneXd6endxaGQvZ3lLOWhuZHQzUk05dlQ5QngvQTNWSTBwdnE2Q3NKOE8yUlBrRHA4V2gKWXhlTFZlS29zU1Y2eVROMWhvdkJoc1cwTWZEL2FxYjAzdjN1TUo3QVdvY1dhako3cWNocjRTT2NzcTRqbmJSagoxUmtsdDY3eFVKYjA2ZXZsUFFKSFUyem5ZYkE5VUFsYUlOYytycmVaZE1FbnM5eE9UcU1ZcE9BcjJzNkV5NXhRCkZJY2FCSG5uT0l6WDYxcWhnUFNmMzlVQmJ3bGozK0pVT0M3alR2ZDNSRGkycGNXZVJtZUVNNVNkUDRCSFN5dXkKOE5POGc4d28zVGFTSXZhN0VseTdHUDhNcFZHMHpuR2V3dVA2WGJUOW0rbjgwei9ZcnUwZmoyQXRsbHhoUmJ2LwpyWHcwYUZYU29DOEt4dXZ3S01FQ0F3RUFBYU5DTUVBd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZHMkdLSWJYcDRhTGRiRWw4aks5UTVrWldqN1hNQTBHQ1NxR1NJYjMKRFFFQkN3VUFBNElCQVFCakFncE5mNEJFOXFEY1k4dUk5a3lYa2ZjaE5Ic0JvTVExbnFFbkhUclJhdXlnUnBoTwpYMWVlZ0J4UjlxL2JkNGVxbmVBMjRBZ1A2VXJPYVJCNHZmM2ppTXFrOC9PdmlNMmFVVVczaXdiNHczWnRhY2VUCnFPWGlVRTYxVTJDamVSbFdNTkR6MUpWQWVud0JqeWFadFpuQlIxWFhuVzBKZy9EUm1VYkpxdkZER3Q3ekJ2cHkKcXZZNDZXZTRFYkp2R05UWWdIZE9uZXd2d1ZudFZLeWIydDlocmx5OGxJQlc2UGtQbGpEc2Zma21CV0NHcTJObgpOU2FZa29iQXlGOU43bk0yUElEdUZKQjEvZVR2NGVYbWg2bEFqRjgzZjRlS1o3TUJqczdjOHFjeVJlYjNrVE5VCkhMN1VsWVVGR0ZvQyt1cHFCamJ4ZVpYbkNENUZUcitSWWZKdQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
server: https://10.0.0.131:6443
name: kubernetes
contexts: null
current-context: ""
kind: Config
preferences: {}
users: null
2)获取def-ns-admin的token,并将其作为认证信息。由于直接得到的token为base64编码格式,因此,下面使用了“base64 -d”命令将其解码还原:
[root@k8s-master1 dashboard]# kubectl get secrets | grep -i def-ns-admin
def-ns-admin-token-rrvkx kubernetes.io/service-account-token 3 15m
[root@k8s-master1 dashboard]# DEFNS_ADMIN_TOKEN=$(kubectl get secrets def-ns-admin-token-rrvkx -n default -o jsonpath={.data.token}|base64 -d)
[root@k8s-master1 dashboard]# echo $DEFNS_ADMIN_TOKEN
eyJhbGciOiJSUzI1NiIsImtpZCI6IkxKVHlZMHFIMWpxRnlOSWRPMmVDQnBPdGFwdWRlbkdrLUpuOG50WUhfbEkifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlZi1ucy1hZG1pbi10b2tlbi1ycnZreCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJkZWYtbnMtYWRtaW4iLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI5MjkwYWU2Ni01MTYyLTQ3NWUtOGIwZC1iZGVlMWE1YzliYWQiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVmYXVsdDpkZWYtbnMtYWRtaW4ifQ.YpF94wYp5071Te8mzUlZltu1Umdl5tuNdqlA3RxLbOMeKSn0LfTVk8sbRnV_EwoiPL00mPm_hFIoGzvRBWqhREpzU7iZfSYwph4QtQL5MCfbePAdmrJIYpXgIvqYYDXK0Nw8sK7QK0s_OsL0S17GsGqPmLXXYssu14p49AeJXkI_0VHTO3DlPOQg1xXY_0ZDJsLtRwKXsD9QjfBOr4jvB1qBIT5NHg2Yb0hYJsR2yN8lMRsQgqZucvMQg9EQFuN7ud06GFUIasjKmVKRfFIyqRHgoQxr2zfG6rlj6o0IE3Nrdx_Z_yTcPpiVnHoKYtOGTT4lEvF0JnkpGd8PtSVPZw
[root@k8s-master1 dashboard]# kubectl describe secrets def-ns-admin-token-rrvkx -n default
Name: def-ns-admin-token-rrvkx
Namespace: default
Labels: <none>
Annotations: kubernetes.io/service-account.name: def-ns-admin
kubernetes.io/service-account.uid: 9290ae66-5162-475e-8b0d-bdee1a5c9bad
Type: kubernetes.io/service-account-token
Data
====
ca.crt: 1066 bytes
namespace: 7 bytes
token: eyJhbGciOiJSUzI1NiIsImtpZCI6IkxKVHlZMHFIMWpxRnlOSWRPMmVDQnBPdGFwdWRlbkdrLUpuOG50WUhfbEkifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlZi1ucy1hZG1pbi10b2tlbi1ycnZreCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJkZWYtbnMtYWRtaW4iLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI5MjkwYWU2Ni01MTYyLTQ3NWUtOGIwZC1iZGVlMWE1YzliYWQiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVmYXVsdDpkZWYtbnMtYWRtaW4ifQ.YpF94wYp5071Te8mzUlZltu1Umdl5tuNdqlA3RxLbOMeKSn0LfTVk8sbRnV_EwoiPL00mPm_hFIoGzvRBWqhREpzU7iZfSYwph4QtQL5MCfbePAdmrJIYpXgIvqYYDXK0Nw8sK7QK0s_OsL0S17GsGqPmLXXYssu14p49AeJXkI_0VHTO3DlPOQg1xXY_0ZDJsLtRwKXsD9QjfBOr4jvB1qBIT5NHg2Yb0hYJsR2yN8lMRsQgqZucvMQg9EQFuN7ud06GFUIasjKmVKRfFIyqRHgoQxr2zfG6rlj6o0IE3Nrdx_Z_yTcPpiVnHoKYtOGTT4lEvF0JnkpGd8PtSVPZw
You have new mail in /var/spool/mail/root
[root@k8s-master1 dashboard]# kubectl config set-credentials def-ns-admin --token=${DEFNS_ADMIN_TOKEN} --kubeconfig=./def-ns-admin.kubeconfig
User "def-ns-admin" set.
#查看kubeconfig文件内容
[root@k8s-master1 dashboard]# cat def-ns-admin.kubeconfig
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM1ekNDQWMrZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJeU1EZ3dNVEV5TkRNMU1Wb1hEVE15TURjeU9URXlORE0xTVZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTDJOCmRLRjdRZnZqYjkzWExneXd6endxaGQvZ3lLOWhuZHQzUk05dlQ5QngvQTNWSTBwdnE2Q3NKOE8yUlBrRHA4V2gKWXhlTFZlS29zU1Y2eVROMWhvdkJoc1cwTWZEL2FxYjAzdjN1TUo3QVdvY1dhako3cWNocjRTT2NzcTRqbmJSagoxUmtsdDY3eFVKYjA2ZXZsUFFKSFUyem5ZYkE5VUFsYUlOYytycmVaZE1FbnM5eE9UcU1ZcE9BcjJzNkV5NXhRCkZJY2FCSG5uT0l6WDYxcWhnUFNmMzlVQmJ3bGozK0pVT0M3alR2ZDNSRGkycGNXZVJtZUVNNVNkUDRCSFN5dXkKOE5POGc4d28zVGFTSXZhN0VseTdHUDhNcFZHMHpuR2V3dVA2WGJUOW0rbjgwei9ZcnUwZmoyQXRsbHhoUmJ2LwpyWHcwYUZYU29DOEt4dXZ3S01FQ0F3RUFBYU5DTUVBd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZHMkdLSWJYcDRhTGRiRWw4aks5UTVrWldqN1hNQTBHQ1NxR1NJYjMKRFFFQkN3VUFBNElCQVFCakFncE5mNEJFOXFEY1k4dUk5a3lYa2ZjaE5Ic0JvTVExbnFFbkhUclJhdXlnUnBoTwpYMWVlZ0J4UjlxL2JkNGVxbmVBMjRBZ1A2VXJPYVJCNHZmM2ppTXFrOC9PdmlNMmFVVVczaXdiNHczWnRhY2VUCnFPWGlVRTYxVTJDamVSbFdNTkR6MUpWQWVud0JqeWFadFpuQlIxWFhuVzBKZy9EUm1VYkpxdkZER3Q3ekJ2cHkKcXZZNDZXZTRFYkp2R05UWWdIZE9uZXd2d1ZudFZLeWIydDlocmx5OGxJQlc2UGtQbGpEc2Zma21CV0NHcTJObgpOU2FZa29iQXlGOU43bk0yUElEdUZKQjEvZVR2NGVYbWg2bEFqRjgzZjRlS1o3TUJqczdjOHFjeVJlYjNrVE5VCkhMN1VsWVVGR0ZvQyt1cHFCamJ4ZVpYbkNENUZUcitSWWZKdQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
server: https://10.0.0.131:6443
name: kubernetes
contexts: null
current-context: ""
kind: Config
preferences: {}
users:
- name: def-ns-admin
user:
token: eyJhbGciOiJSUzI1NiIsImtpZCI6IkxKVHlZMHFIMWpxRnlOSWRPMmVDQnBPdGFwdWRlbkdrLUpuOG50WUhfbEkifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlZi1ucy1hZG1pbi10b2tlbi1ycnZreCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJkZWYtbnMtYWRtaW4iLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI5MjkwYWU2Ni01MTYyLTQ3NWUtOGIwZC1iZGVlMWE1YzliYWQiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVmYXVsdDpkZWYtbnMtYWRtaW4ifQ.YpF94wYp5071Te8mzUlZltu1Umdl5tuNdqlA3RxLbOMeKSn0LfTVk8sbRnV_EwoiPL00mPm_hFIoGzvRBWqhREpzU7iZfSYwph4QtQL5MCfbePAdmrJIYpXgIvqYYDXK0Nw8sK7QK0s_OsL0S17GsGqPmLXXYssu14p49AeJXkI_0VHTO3DlPOQg1xXY_0ZDJsLtRwKXsD9QjfBOr4jvB1qBIT5NHg2Yb0hYJsR2yN8lMRsQgqZucvMQg9EQFuN7ud06GFUIasjKmVKRfFIyqRHgoQxr2zfG6rlj6o0IE3Nrdx_Z_yTcPpiVnHoKYtOGTT4lEvF0JnkpGd8PtSVPZw
3)设置context列表,定义一个名为def-ns-admin的context:
[root@k8s-master1 dashboard]# kubectl config set-context def-ns-admin --cluster=kubernetes --user=def-ns-admin --kubeconfig=./def-ns-admin.kubeconfig
Context "def-ns-admin" created.
You have new mail in /var/spool/mail/root
[root@k8s-master1 dashboard]# cat def-ns-admin.kubeconfig
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM1ekNDQWMrZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJeU1EZ3dNVEV5TkRNMU1Wb1hEVE15TURjeU9URXlORE0xTVZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTDJOCmRLRjdRZnZqYjkzWExneXd6endxaGQvZ3lLOWhuZHQzUk05dlQ5QngvQTNWSTBwdnE2Q3NKOE8yUlBrRHA4V2gKWXhlTFZlS29zU1Y2eVROMWhvdkJoc1cwTWZEL2FxYjAzdjN1TUo3QVdvY1dhako3cWNocjRTT2NzcTRqbmJSagoxUmtsdDY3eFVKYjA2ZXZsUFFKSFUyem5ZYkE5VUFsYUlOYytycmVaZE1FbnM5eE9UcU1ZcE9BcjJzNkV5NXhRCkZJY2FCSG5uT0l6WDYxcWhnUFNmMzlVQmJ3bGozK0pVT0M3alR2ZDNSRGkycGNXZVJtZUVNNVNkUDRCSFN5dXkKOE5POGc4d28zVGFTSXZhN0VseTdHUDhNcFZHMHpuR2V3dVA2WGJUOW0rbjgwei9ZcnUwZmoyQXRsbHhoUmJ2LwpyWHcwYUZYU29DOEt4dXZ3S01FQ0F3RUFBYU5DTUVBd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZHMkdLSWJYcDRhTGRiRWw4aks5UTVrWldqN1hNQTBHQ1NxR1NJYjMKRFFFQkN3VUFBNElCQVFCakFncE5mNEJFOXFEY1k4dUk5a3lYa2ZjaE5Ic0JvTVExbnFFbkhUclJhdXlnUnBoTwpYMWVlZ0J4UjlxL2JkNGVxbmVBMjRBZ1A2VXJPYVJCNHZmM2ppTXFrOC9PdmlNMmFVVVczaXdiNHczWnRhY2VUCnFPWGlVRTYxVTJDamVSbFdNTkR6MUpWQWVud0JqeWFadFpuQlIxWFhuVzBKZy9EUm1VYkpxdkZER3Q3ekJ2cHkKcXZZNDZXZTRFYkp2R05UWWdIZE9uZXd2d1ZudFZLeWIydDlocmx5OGxJQlc2UGtQbGpEc2Zma21CV0NHcTJObgpOU2FZa29iQXlGOU43bk0yUElEdUZKQjEvZVR2NGVYbWg2bEFqRjgzZjRlS1o3TUJqczdjOHFjeVJlYjNrVE5VCkhMN1VsWVVGR0ZvQyt1cHFCamJ4ZVpYbkNENUZUcitSWWZKdQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
server: https://10.0.0.131:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: def-ns-admin
name: def-ns-admin
current-context: ""
kind: Config
preferences: {}
users:
- name: def-ns-admin
user:
token: eyJhbGciOiJSUzI1NiIsImtpZCI6IkxKVHlZMHFIMWpxRnlOSWRPMmVDQnBPdGFwdWRlbkdrLUpuOG50WUhfbEkifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlZi1ucy1hZG1pbi10b2tlbi1ycnZreCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJkZWYtbnMtYWRtaW4iLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI5MjkwYWU2Ni01MTYyLTQ3NWUtOGIwZC1iZGVlMWE1YzliYWQiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVmYXVsdDpkZWYtbnMtYWRtaW4ifQ.YpF94wYp5071Te8mzUlZltu1Umdl5tuNdqlA3RxLbOMeKSn0LfTVk8sbRnV_EwoiPL00mPm_hFIoGzvRBWqhREpzU7iZfSYwph4QtQL5MCfbePAdmrJIYpXgIvqYYDXK0Nw8sK7QK0s_OsL0S17GsGqPmLXXYssu14p49AeJXkI_0VHTO3DlPOQg1xXY_0ZDJsLtRwKXsD9QjfBOr4jvB1qBIT5NHg2Yb0hYJsR2yN8lMRsQgqZucvMQg9EQFuN7ud06GFUIasjKmVKRfFIyqRHgoQxr2zfG6rlj6o0IE3Nrdx_Z_yTcPpiVnHoKYtOGTT4lEvF0JnkpGd8PtSVPZw
4)指定要使用的context为前面定义的名为def-ns-admin的context:
[root@k8s-master1 dashboard]# kubectl config use-context def-ns-admin --kubeconfig=./def-ns-admin.kubeconfig Switched to context "def-ns-admin".
到此为止,一个用于Dashboard登录认证的default名称空间的管理员账号配置文件def-ns-admin.kubeconfig已经设置完成,将文件复制到远程客户端上即可用于登录认证。




可以看到只能看到default名称空间下的资源。
4. 通过Dashboard创建容器
以token方式登录到Dashboard,打开Dashboard界面,点开红色箭头标注的"+",如下图所示,可以看到有三种方式创建资源,a. 直接写资源清单;b. 上传已写好的字眼清单;c. 通过表格方式创建。下面示例以编写资源清单文件创建资源:


点击upload创建


二、准入控制器与应用示例
在经由认证插件与授权插件分别完成身份认证和权限检查之后,准入控制器将拦截那些创建、更新和删除相关的操作请求以强制实现控制器中定义的功能,包括执行对象的语义验证、设置缺失字段的默认值、限制所有容器使用的镜像文件必须来自某个特定的Registry、检查Pod对象的资源需求是否超出了指定的限制范围等。
在具体运行时,准入控制可分为两个阶段,第一个阶段串行运行各变异型控制器,第二个阶段串行运行各验证型控制器,在此过程中,一旦任一阶段中的任何控制器拒绝请求,则立即拒绝整个请求,并向用户返回错误。
1. LimitRange资源与LimitRanger准入控制器
虽然用户可以为容器指定资源需求及资源限制,但未予指定资源限制属性的容器应用很有可能因故吞掉所在工作节点上的所有可用计算资源,因此妥当的做法是使用LimitRange资源在每个名称空间中为每个容器指定最小及最大计算资源用量,甚至是设置默认的计算资源需求和计算资源限制。在名称空间上定义了LimitRange对象后,客户端提交创建或修改的资源对象将受到LimitRanger控制器的检查,任何违反LimitRange对象定义的资源最大用量的请求将被直接拒绝。
LimitRange资源支持限制容器、Pod和PersistentVolumeClaim三种资源对象的系统资源用量,其中Pod和容器主要用于定义可用的CPU和内存资源范围,而PersistentVolumeClaim则主要定义存储空间的限制范围。下面配置清单以容器的CPU资源为例,default用于定义默认的资源限制,defaultRequest定义默认的资源需求,min定义最小的资源用量,而最大的资源用量既可以使用max给出的固定值,也可以使用maxLimitRequestRatio设定为最小用量的指定倍数:
[root@k8s-master1 ~]# mkdir limitrange
[root@k8s-master1 ~]# cd limitrange/
[root@k8s-master1 limitrange]# vim cpu-limit-range.yaml
You have new mail in /var/spool/mail/root
[root@k8s-master1 limitrange]# cat cpu-limit-range.yaml
apiVersion: v1
kind: LimitRange
metadata:
name: cpu-limit-range
spec:
limits:
- default:
cpu: 1000m
defaultRequest:
cpu: 1000m
min:
cpu: 500m
max:
cpu: 2000m
maxLimitRequestRatio:
cpu: 4
type: Container
将配置清单中的资源创建于集群上的default名称空间中,而后即可使用describe命令查看相关资源的生效结果。创建不同的pod对象对默认值、最小资源限制及最大资源限制分别进行测试以验证其限制机制。
[root@k8s-master1 limitrange]# kubectl apply -f cpu-limit-range.yaml limitrange/cpu-limit-range created [root@k8s-master1 limitrange]# kubectl get limitrange cpu-limit-range -o wide NAME CREATED AT cpu-limit-range 2022-11-07T14:16:04Z [root@k8s-master1 limitrange]# kubectl describe limitrange cpu-limit-range Name: cpu-limit-range Namespace: default Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio ---- -------- --- --- --------------- ------------- ----------------------- Container cpu 500m 2 1 1 4
创建一个仅包含一个容器且没有默认系统资源需求和限制的pod对象:
[root@k8s-master1 limitrange]# kubectl run limit-pod1 --image=ikubernetes/myapp:v1 --restart=Never
pod/limit-pod1 created
[root@k8s-master1 limitrange]# kubectl describe pods limit-pod1
Name: limit-pod1
Namespace: default
Priority: 0
Node: k8s-node1/10.0.0.132
Start Time: Mon, 07 Nov 2022 22:21:05 +0800
Labels: run=limit-pod1
Annotations: cni.projectcalico.org/podIP: 10.244.36.89/32
cni.projectcalico.org/podIPs: 10.244.36.89/32
kubernetes.io/limit-ranger: LimitRanger plugin set: cpu request for container limit-pod1; cpu limit for container limit-pod1
Status: Pending
IP:
IPs: <none>
Containers:
limit-pod1:
Container ID:
Image: ikubernetes/myapp:v1
Image ID:
Port: <none>
Host Port: <none>
State: Waiting
Reason: ContainerCreating
Ready: False
Restart Count: 0
Limits:
cpu: 1
Requests:
cpu: 1
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-5n29f (ro)
Conditions:
Type Status
Initialized True
Ready False
ContainersReady False
PodScheduled True
Volumes:
default-token-5n29f:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-5n29f
Optional: false
QoS Class: Burstable
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 13s default-scheduler Successfully assigned default/limit-pod1 to k8s-node1
Normal Pulled 10s kubelet Container image "ikubernetes/myapp:v1" already present on machine
Normal Created 10s kubelet Created container limit-pod1
Normal Started 9s kubelet Started container limit-pod1
从上述命令中可以看到,pod对象limit-pod1的详细信息中,容器状态信息段中,CPU资源被默认设定为如下配置,这正好符合了LimitRange对象中定义的默认值:
Limits:
cpu: 1
Requests:
cpu: 1
若pod对象设定的系统资源需求量小于LimitRange中的最小用量限制,则会触发LimitRanger准入控制器拒绝相关的请求。
[root@k8s-master1 limitrange]# kubectl run limit-pod2 --image=ikubernetes/myapp:v1 --restart=Never --requests='cpu=400m' Error from server (Forbidden): pods "limit-pod2" is forbidden: minimum cpu usage per Container is 500m, but request is 400m
若Pod对象设定的系统资源限制量大于LimitRange中的最大用量限制,则一样会触发LimitRanger准入控制器拒绝相关的请求:
[root@k8s-master1 limitrange]# kubectl run limit-pod3 --image=ikubernetes/myapp:v1 --restart=Never --limits='cpu=3000m' Error from server (Forbidden): pods "limit-pod3" is forbidden: maximum cpu usage per Container is 2, but limit is 3
事实上,在LimitRange对象中设置默认的资源需求和资源限制,同最小资源用量及最大资源用量限制能够组合出多种不同的情形,不同组合场景下真正生效的结果也会存在不小的差异。另外,内存资源及PVC资源限制的实现与CPU资源大同小异。
2. ResourceQuota资源于准入控制器
尽管LimitRange资源能限制单个容器、pod及PVC等相关计算资源或存储资源的用量,但用户依然可以创建数量众多的此类资源对象进而侵占所有的系统资源。于是,kubernetes提供了ResourceQuota资源限制用于定义名称空间的对象数量或系统资源配额,它支持限制每种资源类型的对象总数,以及所有对象所能消耗的计算资源及存储资源总量等。ResourceQuota准入控制器负责观察传入的请求,并确保它没有违反相应的名称空间中ResourceQuota对象定义的任何约束。
于是,管理员可为每个名称空间分别创建一个ResourceQuota对象,随后,用户在名称空间中创建资源对象,ResourceQuota准入控制器将跟踪使用情况以确保它不超过相应ResourceQuota对象中定义的系统资源限制。用户创建或更新资源的操作违反配额约束将导致请求失败,API Server以HTTP状态码“403 FORBIDDEN”作为响应,并显示一条消息以提示可能违反的约束。不过,在名称空间上启用了CPU和内存等系统资源的配额后,用户创建pod对象时必须指定资源需求或资源限制,否则,会触发ResourceQuota准入控制器拒绝执行相应的操作。
资源配额详细说明参考官网说明:https://kubernetes.io/docs/concepts/policy/resource-quotas/
1)计算资源配额:
ResourceQuota对象可限制指定名称空间中非终止状态的所有pod对象的计算资源需求及计算资源限制总量
配额机制所支持的资源类型:

2)存储资源配额
ResourceQuota对象还支持限制特定名称空间中可以使用的PVC数量和这些PVC资源的空间大小总量,以及特定名称空间中可在指定的StorageClass上使用的PVC数量和这些PVC资源的总数
例如:如果一个操作人员针对 gold 存储类型与 bronze 存储类型设置配额, 操作人员可以定义如下配额:
gold.storageclass.storage.k8s.io/requests.storage: 500Gi bronze.storageclass.storage.k8s.io/requests.storage: 100Gi
在 Kubernetes 1.8 版本中,本地临时存储的配额支持已经是 Alpha 功能:

注:说明:如果所使用的是 CRI 容器运行时,容器日志会被计入临时存储配额。 这可能会导致存储配额耗尽的 Pods 被意外地驱逐出节点
3)对象数量配额
可以使用以下语法对所有标准的、命名空间域的资源类型进行配额设置:
count/<resource>.<group>:用于非核心(core)组的资源
count/<resource>:用于核心组的资源
例如以下示例说明:
count/persistentvolumeclaims
count/services
count/secrets
count/configmaps
count/replicationcontrollers
count/deployments.apps
count/replicasets.apps
count/statefulsets.apps
count/jobs.batch
count/cronjobs.batch
当使用 count/* 资源配额时,如果对象存在于服务器存储中,则会根据配额管理资源。 这些类型的配额有助于防止存储资源耗尽。例如,用户可能想根据服务器的存储能力来对服务器中 Secret 的数量进行配额限制。 集群中存在过多的 Secret 实际上会导致服务器和控制器无法启动。 用户可以选择对 Job 进行配额管理,以防止配置不当的 CronJob 在某命名空间中创建太多 Job 而导致集群拒绝服务。
对有限的一组资源上实施一般性的对象数量配额也是可能的。支持以下类型:

下面的配置清单示例定义了一个ResourceQuota资源对象,它配置了计算资源、存储资源及对象计数几个维度的限额:
[root@k8s-master1 resourcequota]# kubectl create ns test
namespace/test created
[root@k8s-master1 resourcequota]# vim quota-example.yaml
You have new mail in /var/spool/mail/root
[root@k8s-master1 resourcequota]# cat quota-example.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: quota-example
namespace: test
spec:
hard:
pods: "5"
requests.cpu: "1"
requests.memory: 1Gi
limits.cpu: "2"
limits.memory: 2Gi
count/deployments.apps: "1"
count/deployments.extensions: "1"
persistentvolumeclaims: "2"
[root@k8s-master1 resourcequota]# kubectl apply -f quota-example.yaml
resourcequota/quota-example created
[root@k8s-master1 resourcequota]# kubectl get quota -n test
NAME AGE REQUEST LIMIT
quota-example 15s count/deployments.apps: 0/1, count/deployments.extensions: 0/1, persistentvolumeclaims: 0/2, pods: 0/5, requests.cpu: 0/1, requests.memory: 0/1Gi limits.cpu: 0/2, limits.memory: 0/2Gi
创建完成后,describe命令可以打印其限额的生效情况,例如,将上面的ResourceQuota对象创建于test名称空间中,其打印效果如下所示:
[root@k8s-master1 resourcequota]# kubectl describe quota quota-example -n test Name: quota-example Namespace: test Resource Used Hard -------- ---- ---- count/deployments.apps 0 1 count/deployments.extensions 0 1 limits.cpu 0 2 limits.memory 0 2Gi persistentvolumeclaims 0 2 pods 0 5 requests.cpu 0 1 requests.memory 0 1Gi
在test名称空间中创建deployment等对象即可进行配额测试、例如,下面的命令创建了一个有着3个pod副本的Deployment对象myapp-deploy:
[root@k8s-master1 resourcequota]# vim myapp-deploy.yaml
[root@k8s-master1 resourcequota]# cat myapp-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deploy
namespace: test
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
resources:
requests:
cpu: 0.2
memory: 256Mi
limits:
cpu: 0.5
memory: 256Mi
[root@k8s-master1 resourcequota]# kubectl apply -f myapp-deploy.yaml
deployment.apps/myapp-deploy created
[root@k8s-master1 resourcequota]# kubectl get deployments -n test
NAME READY UP-TO-DATE AVAILABLE AGE
myapp-deploy 3/3 3 3 8s
创建完成后,test名称空间上的ResourceQuota对象quota-example的各配置属性也相应地变成了如下状态:
[root@k8s-master1 resourcequota]# kubectl describe quota quota-example -n test Name: quota-example Namespace: test Resource Used Hard -------- ---- ---- count/deployments.apps 1 1 count/deployments.extensions 0 1 limits.cpu 1500m 2 limits.memory 768Mi 2Gi persistentvolumeclaims 0 2 pods 3 5 requests.cpu 600m 1 requests.memory 768Mi 1Gi
此时,在扩展myapp-deploy的规模则会很快遇到某一项配额的限制而导致扩展受阻。由分析可知,将pod副本数量扩展至5个就会达到limits.cpu资源上限而导致第5个扩展失败,从下面测试结果可以看出deployment资源只扩展到4个,第5个失败,因为limits.cpu资源达到了上限,requests.memory资源也达到了上限。
[root@k8s-master1 resourcequota]# kubectl scale --current-replicas=3 --replicas=5 deployment/myapp-deploy -n test deployment.apps/myapp-deploy scaled [root@k8s-master1 resourcequota]# kubectl get deployment myapp-deploy -n test -o wide NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR myapp-deploy 4/5 4 4 5m38s nginx nginx:latest app=nginx You have new mail in /var/spool/mail/root [root@k8s-master1 resourcequota]# kubectl describe quota quota-example -n test Name: quota-example Namespace: test Resource Used Hard -------- ---- ---- count/deployments.apps 1 1 count/deployments.extensions 0 1 limits.cpu 2 2 limits.memory 1Gi 2Gi persistentvolumeclaims 0 2 pods 4 5 requests.cpu 800m 1 requests.memory 1Gi 1Gi
需要注意的是,资源配额仅对那些在ResourceQuota对象创建之后生成的对象有效,对已经存在的对象不会产生任何限制。而且,一旦启用了计算资源需求和计算资源限制配额,那么创建的任何pod对象都必须设置此两类属性,否则pod对象的创建将会被相应的ResourceQuota对象所阻止。无须手动为每个pod对象设置此两类属性时,可以使用LimitRange对象为其设置默认值。
4)配额作用域
每个ResourceQuota对象上还支持定义一组相关的 scope(作用域),用于定义其配额仅对作用域内的资源生效。 配额机制仅统计所列举的作用域的交集中的资源用量。当一个作用域被添加到配额中后,它会对作用域相关的资源数量作限制。 如配额中指定了允许(作用域)集合之外的资源,会导致验证错误。
目前可用的scope包括以下几种:

从kubernetes 1.8版本起,管理员可以设置不同的优先级类别PriorityClass来创建pod对象,在1.11版本开始,kubernetes开始支持对每个PriorityClass对象分别设定资源限额,管理员可以使用scopeSelector字段,从而根据pod对象的优先级控制Pod资源对系统资源的消耗。
下面的示例创建一个配额对象,并将其与具有特定优先级的 Pod 进行匹配。 该示例的工作方式如下:
集群中的 Pod 可取三个优先级类之一,即 "low"、"medium"、"high"。
[root@k8s-master1 resourcequota]# vim high-priority.yaml [root@k8s-master1 resourcequota]# cat high-priority.yaml apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: high value: 1000000 globalDefault: false description: "first" [root@k8s-master1 resourcequota]# kubectl create -f high-priority.yaml priorityclass.scheduling.k8s.io/high created [root@k8s-master1 resourcequota]# kubectl get priorityclass high -o wide NAME VALUE GLOBAL-DEFAULT AGE high 1000000 false 28s [root@k8s-master1 resourcequota]# vim medium-priority.yaml [root@k8s-master1 resourcequota]# cat medium-priority.yaml apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: medium value: 5000 globalDefault: false description: "second" [root@k8s-master1 resourcequota]# kubectl create -f medium-priority.yaml priorityclass.scheduling.k8s.io/medium created [root@k8s-master1 resourcequota]# kubectl get priorityclass medium -o wide NAME VALUE GLOBAL-DEFAULT AGE medium 5000 false 23s [root@k8s-master1 resourcequota]# vim low-priority.yaml [root@k8s-master1 resourcequota]# cat low-priority.yaml apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: low value: 100 globalDefault: false description: "third" [root@k8s-master1 resourcequota]# kubectl create -f low-priority.yaml priorityclass.scheduling.k8s.io/low created [root@k8s-master1 resourcequota]# kubectl get priorityclass low -o wide NAME VALUE GLOBAL-DEFAULT AGE low 100 false 9s
为每个优先级创建一个配额对象。将以下 YAML 保存到文件 quota.yml 中
[root@k8s-master1 resourcequota]# vim quota.yml
You have new mail in /var/spool/mail/root
[root@k8s-master1 resourcequota]# cat quota.yml
apiVersion: v1
kind: List
items:
- apiVersion: v1
kind: ResourceQuota
metadata:
name: pods-high
spec:
hard:
cpu: "1"
memory: 2Gi
pods: "10"
scopeSelector:
matchExpressions:
- operator : In
scopeName: PriorityClass
values: ["high"]
- apiVersion: v1
kind: ResourceQuota
metadata:
name: pods-medium
spec:
hard:
cpu: "0.5"
memory: 1Gi
pods: "10"
scopeSelector:
matchExpressions:
- operator : In
scopeName: PriorityClass
values: ["medium"]
- apiVersion: v1
kind: ResourceQuota
metadata:
name: pods-low
spec:
hard:
cpu: "0.02"
memory: 0.3Gi
pods: "10"
scopeSelector:
matchExpressions:
- operator : In
scopeName: PriorityClass
values: ["low"]
[root@k8s-master1 resourcequota]# kubectl create -f quota.yml
resourcequota/pods-high created
resourcequota/pods-medium created
resourcequota/pods-low created
使用 kubectl describe quota 操作验证配额的 Used 值为 0
[root@k8s-master1 resourcequota]# kubectl describe quota Name: pods-high Namespace: default Resource Used Hard -------- ---- ---- cpu 0 1 memory 0 2Gi pods 0 10 Name: pods-low Namespace: default Resource Used Hard -------- ---- ---- cpu 0 20m memory 0 322122547200m pods 0 10 Name: pods-medium Namespace: default Resource Used Hard -------- ---- ---- cpu 0 500m memory 0 1Gi pods 0 10
创建优先级为 "high" 的 Pod对象:
[root@k8s-master1 resourcequota]# vim high-priority-pod.yml
[root@k8s-master1 resourcequota]# cat high-priority-pod.yml
apiVersion: v1
kind: Pod
metadata:
name: high-priority
spec:
containers:
- name: high-priority
image: busybox:latest
imagePullPolicy: IfNotPresent
command: ["/bin/sh"]
args: ["-c", "while true; do echo hello; sleep 10;done"]
resources:
requests:
memory: "1.2Gi"
cpu: "500m"
limits:
memory: "1.5Gi"
cpu: "500m"
priorityClassName: high
[root@k8s-master1 resourcequota]# kubectl apply -f high-priority-pod.yml
pod/high-priority created
[root@k8s-master1 resourcequota]# kubectl get pods high-priority -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
high-priority 1/1 Running 0 17s 10.244.36.94 k8s-node1 <none> <none>
确认 "high" 优先级配额 pods-high 的 "Used" 统计信息已更改,并且其他两个配额未更改
[root@k8s-master1 resourcequota]# kubectl describe quota Name: pods-high Namespace: default Resource Used Hard -------- ---- ---- cpu 500m 1 memory 1288490188800m 2Gi pods 1 10 Name: pods-low Namespace: default Resource Used Hard -------- ---- ---- cpu 0 20m memory 0 322122547200m pods 0 10 Name: pods-medium Namespace: default Resource Used Hard -------- ---- ---- cpu 0 500m memory 0 1Gi pods 0 10

浙公网安备 33010602011771号