第八课:kubernetes核心概念
1.kubernetes对象
服务网络访问:Ingress,Service
容器管理类型:Deployment,Replicaset,ReplicationController,DaemonSet,StatefulSet
容器存储类型:Volume,Secret,Configmap,PersistentVolume
层次结构
yaml文件中kind为pod的时候在apiversion为v1的时候不支持多副本,只有在deploymen和replicaset及replicationcontroller的时候可以支持多副本。
2 容器控制器
2.1 ReplicationController
2.2 ReplicaSet
2.3 Deployment
Deployment同样为Kubernetes的一个核心内容,主要职责同样是为了保证pod的数量和健康,90%的功能与Replication Controller完全一样,可以看作新一代的Replication Controller。但是,它具备了RC之外的新特性。
- Deployment继承了上面描述的RC的全部功能(副本数保持与扩容)。
- 容器在升级或者创建过程中,可以查看详细进度和状态。
- 当升级Pod镜像或者相关参数的时候,如果发现问题,可以使用回滚操作回滚到上一个稳定的版本或者指定的版本。
- 每一次对Deployment的操作,都能保存下来(有操作记录),给与后续可能的回滚使用。
- 对于每一次升级,都能够随时暂停和启动(容易控制)。
- 多种升级方案:
a. Recrate:删除所有已存在的pod,重新创建新的。
b. RollingUpdate: 滚动升级,逐步替换的策略,同时滚动升级时,支持更多的附加参数,例如设置最大不可用pod数量,最小升级间隔时间等。
容器控制器创建pod流程:
- 使用deployment来创建replicaset,replicaset则在后台创建pod,检查pod启动状态,是否成功。
- 通过更新deployment的PodTemplateSpec字段来申明pod的新状态,之后会创建一个新的replicaset。
- 如果新的replicaset启动失败(检查端口策略),则就的replicaset还会继续存在。
- 如果扩容成功,则会清理掉旧的replicaset。
2.3.1 POD升级策略与检测机制
2.3.1.1 升级策略 (Deployment)
strategy:
type: RollingUpdate #默认更新策略
rollingUpdate:
maxSurge: 1 #POD的总数最多比所需的POD数多1个
maxUnavailable: 1 #更新过程中最多1个不可用的POD数
2.3.1.2 pod启动与存活机制
pod 就绪探测 (Deployment-template-spec)
readinessProbe: #确定容器是否已经启动正常
tcpSocket:
port: 8080 #检查端口
initialDelaySeconds: 5 #kubelet会在容器启动5秒后发送第一个就绪探测
periodSeconds: 10 #每10秒执行一次存活探测
如果探测成功,这个pod会被标记为就绪状态,kubelet将继续每隔10秒进行一次检测。
pod 存活探测 (Deployment-template-apec)
livenessProbe: #存活探测
tcpSocket:
prot: 8080
initialDelaySeconds: 15 #kubelet会在容器启动15秒后进行第一次存活探测
periodSeconds: 10 #每隔10秒执行一次存活探测
与就绪探测一样,kubelet会尝试连接容器的8080端口,如果存活探测失败,这个容器会被重启。
一般来说就绪探测和存活探测二选其一使用即可。
[root@master01 nginx]# more my-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: nginx-11
name: nginx-11
spec:
replicas: 2
selector:
matchLabels:
app: nginx-11
strategy:
type: RollingUpdate #默认更新策略
rollingUpdate:
maxSurge: 1 #POD的总数最多比所需的POD数多1个
maxUnavailable: 1 #更新过程中最多1个不可用的POD数
template:
metadata:
creationTimestamp: null
labels:
app: nginx-11
spec:
containers:
- image: nginx
name: nginx-11
ports:
- containerPort: 80
readinessProbe: #确定容器是否已经启动正常
tcpSocket:
port: 80 #检查端口
initialDelaySeconds: 5 #kubelet会在容器启动5秒后发送第一个就绪探测
periodSeconds: 10 #每10秒执行一次存活探测
status: {}
kubectl describe deployment nginx-11
可以查看deployment的事件,升级策略,存活或启动策略等。
[root@master01 nginx]# kubectl describe deployment nginx-11
Name: nginx-11
Namespace: default
CreationTimestamp: Sat, 15 Aug 2020 13:27:37 +0800
Labels: app=nginx-11
Annotations: deployment.kubernetes.io/revision: 1
kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"creationTimestamp":null,"labels":{"app":"nginx-11"},"name":"ngin...
Selector: app=nginx-11
Replicas: 2 desired | 2 updated | 2 total | 2 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 1 max unavailable, 1 max surge
Pod Template:
Labels: app=nginx-11
Containers:
nginx-11:
Image: nginx
Port: 80/TCP
Host Port: 0/TCP
Readiness: tcp-socket :80 delay=5s timeout=1s period=10s #success=1 #failure=3
Environment: <none>
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
OldReplicaSets: <none>
NewReplicaSet: nginx-11-6d6cb4f4c7 (2/2 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 10m deployment-controller Scaled up replica set nginx-11-6d6cb4f4c7 to 2
Normal ScalingReplicaSet 20s deployment-controller Scaled up replica set nginx-11-6d6cb4f4c7 to 3
2.4 DaemonSet (容器控制器)
一个DaemonSet对象能确保其创建的pod在集群中的每一台(或指定label)Node上都运行一个副本。如果集群中动态加入了新的node,DaemonSet中的pod也会被添加在新加入的node上运行。删除一个DaemonSet也会级联删除所有其创建的POD。
类似于docker的global mode。
使用场景:
- 运行集群存储daemon,例如在每个node上运行glusterd,ceph。
- 在每个node上运行日志收集daemon,例如fluentd,logstash。
- 在每个node上运行监控daemon,例如prometheus node exporter,zabbix-agent。
2.4.1 案例分析
示例:log-pilot 使用daemonset控制器,在yaml文件中并没有定义副本数量,但是会自动在每个node上运行一个pod用于日志收集。
[root@master01 logs]# more log-pilot-2.0.yml
---
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: log-pilot
namespace: kube-system
labels:
k8s-app: log-pilot
kubernetes.io/cluster-service: "true"
[root@master01 logs]# kubectl get DaemonSet -A
NAMESPACE NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
kube-system log-pilot 2 2 2 2 2 <none> 45h
kube-system traefik-ingress-controller 2 2 2 2 2 IngressProxy=true 3d22h
monitoring node-exporter 2 2 2 2 2 kubernetes.io/os=linux 2d1h
2.5 StatefulSet (SS控制器)
kubernetes从v1.4版本开始引入了PetSet这个新的资源对象,并且在v1.5版本时更名为StatefulSet,从本质上讲,可以看作是Deployment/RC的一个特殊类型。
StatefulSet适合有状态服务,有唯一的pod名称标识,支持持久化存储与滚动更新。
假设StatefulSet运行集群的名字叫elasticsearch,那么第一个pod叫elasticsearch-0,第二pod叫elasticsearch-1,以此类推。证实因为有序的pod的名称,才能够组建集群(需要安装DNS)。
2.5.1 案例: StatefulSet组建Elasticsearch集群
[root@master01 logs]# more elasticsearch.yml
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
name: elasticsearch
namespace: kube-system
labels:
kubernetes.io/cluster-service: "true"
spec:
replicas: 2
serviceName: "elasticsearch-service"
selector:
matchLabels:
app: es
template:
metadata:
labels:
app: es
[root@master01 logs]# kubectl get StatefulSet -A
NAMESPACE NAME READY AGE
kube-system elasticsearch 2/2 46h
monitoring alertmanager-main 2/2 2d3h
monitoring prometheus-k8s 2/2 2d1h
3. 服务发现
3.1 Service (SVC)
在kubernetes中为了更好的定位每一个或者每组POD(label标签),才出现了service的概念。因为POD的IP地址是在每次重启或者容器重新部署之后是变化的。而且容器的IP是无法固定的,所以需要service来定位POD。
通过节点Nodeport端口访问应用
provide-passport.yaml
apiVersion: v1
kind: service
metadata:
name: passport-svc #service 名称
spec:
type: NodePort #service 端口类型
ports:
- port: 8081 #service 端口
targetPort: 8081 #目标容器端口
protocol: TCP #端口协议
selector: #根据label选择容器控制器
app: passport #容器标签为app=passport
3.2 网络代理模式
用户通过service访问服务的时候,是通过node节点上的kube-proxy访问pod服务,在kubernetes v1.2中,kube-proxy的iptables模式为默认设置,在v1.8添加了ipvs代理模式。
-
iptables模式
node节点客户端直接访问serviceIP,linux根据iptables协议栈规则策略匹配。
serviceIP根据标签直接访问Backend Pod。 -
ipvs代理模式
ipvs是LVS的一个组件,提供高性能,高可靠性的四层负载均衡器。ipvs是ip virtual server的简写。ipvs构建在netfilter上,作为linux内核的一部分,从传输层实现了负载均衡。ipvs能直接转发基于service的tcp和udp到真实服务器。ipvs能直接构建一个vips并通过负载均衡算法,把请求转发到backend pod。
算法:
轮询
基于权重的轮询
最小连接数
基于源地址
目的地址hash
3.3 service的基本类型(service type)
- clusterIP
通过集群内部的IP暴露服务,选择该值,服务只能够在集群内部访问,这也是默认的service type - nodePort
通过每个node上的ip和静态端口暴露服务,nodeport服务会路由到clusterip服务,这个clusterip服务会自动创建。通过请求: ,可以从集群的外部访问一个nodePort服务。 - loadBalance
使用云提供商的负载均衡器,可以向外部暴露服务。外部的负载均很气可以路由到nodePort服务和clusterIP服务。
3.4 service端口类型
spec:
type: NodePort #service 端口类型
ports:
- port: 8081 #service 端口
targetPort: 8081 #目标容器端口
protocol: TCP #端口协议
3.5 访问service方式
service的虚拟ip有kubernetes虚拟出来的内部网络(默认是由iptables实现),外部是无法寻址到的。但是有些服务又需要被外部网络访问到,例如web前端。这时候需要添加一层网络转发,及外网到内网的转发。kubernetes提供了NodePort,LoadBalance,Ingress三种方式访问service。
- nodeport
通过每个node上的ip和静态端口暴露服务,nodeport服务会路由到clusterip服务,这个clusterip服务会自动创建。通过请求: ,可以从集群的外部访问一个nodePort服务。 - loadbalance
使用云提供商的负载均衡器,可以向外部暴露服务。外部的负载均很气可以路由到nodePort服务和clusterIP服务。 - ingress
是一种http方式的路由转发机制,有ingress controller和http代理服务器组合而成的。ingress controller试试监控kubernetes API,实时更新http代理服务器的转发规则。http代理服务器有GCE load-balance,haproxy,nginx等开源方案。
4. DNS
DNS服务器监视着创建新service(SVC)的kubernetes API,从而为每一个service创建一组DNS记录,如果整个几区的DNS一直被启用,那么所有的pod应该能够自对service进行名称解析。
例如:有一个名称为my-service的service,它在kubernetes集群中名为my-ns的namespace中,为"my-service.my-ns"创建一条DNS记录。在名称为my-ns的namespace中的pod应该能够简单通过名称查询到my-service。
5. 存储secret
secret解决密码,token,密钥等敏感数据的配置问题,而不会把这些敏感配置暴露到镜像或者pod spec中。secret可以以volume或者环境变量的方式使用。
secret有三种类型:
- service account:用来访问kubernetes API,有kubernetes自动创建,并且会自动挂载到pod的/run/secrets/kubernetes.io/serviceaccount目录中。
- opaque: base64编码格式的secret,用来存储密码,密钥等。
- kubernetes.io/dockerconfigjson: 用来存储私有docker registry的认证信息。
4.1 案例:导入docker Registry认证信息
在kubernetes中需要导入docker私有镜像仓库的登陆信息,才能从私有仓库拉取镜像,登陆信息的存储使用secret加密存储。
方法1:
创建secret密钥
创建secret(注意解析docker-server (hosts))
kubectl create secret docker-registry registry-secret --docker-server=reg.abc.com --docker-username=user --docker-password=123456 --docker-email=user@abc.com
生成secret对应的原始yaml文件
mkdir -p /root/registry && cd /root/registry
kubectl get secret registry-secret -o yaml >> registry-secret.yaml
[root@master01 ~]# kubectl get secret registry-secret -o yaml
apiVersion: v1
data:
.dockerconfigjson: eyJhdXRocyI6eyJyZWcuY2hpbmFjYWNoZS5jb20iOnsidXNlcm5hbWUiOiJqaWEueXUiLCJwYXNzd29yZCI6IkNDaXhAMTIzNDU2IiwiZW1haWwiOiJqaWEueXVAY2hpbmFjYWNoZS5jb20iLCJhdXRoIjoiYW1saExubDFPa05EYVhoQU1USXpORFUyIn19fQ==
kind: Secret
metadata:
creationTimestamp: "2020-08-17T02:32:22Z"
name: registry-secret
namespace: default
resourceVersion: "1102521"
selfLink: /api/v1/namespaces/default/secrets/registry-secret
uid: 34174541-3b61-4556-901d-c2911f54686e
type: kubernetes.io/dockerconfigjson
修改为需要导入的格式
vim registry-secret-01.yaml
apiVersion: v1
kind: Secret
metadata:
name: registry-secret-01
namespace: default
data:
.dockerconfigjson: eyJhdXRocyI6eyJyZWcuY2hpbmFjYWNoZS5jb20iOnsidXNlcm5hbWUiOiJqaWEueXUiLCJwYXNzd29yZCI6IkNDaXhAMTIzNDU2IiwiZW1haWwiOiJqaWEueXVAY2hpbmFjYWNoZS5jb20iLCJhdXRoIjoiYW1saExubDFPa05EYVhoQU1USXpORFUyIn19fQ==
type: kubernetes.io/dockerconfigjson
应用yaml文件生成secret
kubectl apply -f registry-secret-01.yaml
[root@master01 registry]# kubectl apply -f registry-secret-01.yaml
secret/registry-secret-01 created
[root@master01 registry]# kubectl get secret
NAME TYPE DATA AGE
registry-secret kubernetes.io/dockerconfigjson 1 13m
registry-secret-01 kubernetes.io/dockerconfigjson 1 5s
#如果有多个私有镜像仓库可以重复上述方法生成针对不同镜像仓库的不同secret使用。
方法2:
直接用命令生成不同registry对应的secret
kubectl create secret docker-registry registry-secret-01 --docker-server=reg.abc.com --docker-username=user --docker-password=123456 --docker-email=user@abc.com
kubectl create secret docker-registry registry-secret-02 --docker-server=reg.bcd.com --docker-username=user --docker-password=123456 --docker-email=user@bcd.com
使用方法待补充
6. 基于角色的访问控制-RBAC
基于角色(role)的访问控制是一种基于企业汇总用户的角色来控制对计算或者网络资源的访问方法。
RBAC使用rbac.authorization.k8s.io API group 来实现授权决策,允许管理员通过kubernetes API动态配置策略。
启用RBAC,需要在apiserver配置文件中添加参数--zuthorization-mode=RBAC
6.1 RBAC可操作资源列表
资源 | 名称 |
---|---|
PODS | 容器 |
ConfigMaps | 配置 |
Deployment | 容器控制器 |
Nodes | 节点 |
Secrets | 凭证 |
Namespace | 命名空间 |
6.2 资源列表可操作的权限列表
create,get,delete,list,update,edit,watch,exec
6.3 RBAC中的其他对象
- rule:规则,规则是一组属于不通API group资源上的一组操作的集合。
- role和clusterrole: 角色和集群角色,这两个对象都包含上面的rules元素,二者的区别在于,在role中,定义的规则只适用于单个命名空间,也就是和namespace关联的,而clusterrole是集群范围内的,因此定义的规则不受命名空间的约束。
1) subject:主题,对应在及群众尝试操作的对象,及群众定义了3种类型的主题资源
a) user account:用户,这是有外部独立服务进行管理的,管理员进行私钥的分配,用户可以使用keystone或者google账号,甚至一个用户名和密码的文件列表页可以。对于内部的管理集群内部没有一个关联的资源对象,所以用户不能通过集群内部的API来进行管理。
b) group: 组,这是用来关联多个账户的,集群中有一些默认创建的组,比如cluster-admin
c) service account: 服务账户,通过kubernetes API来管理的一些用户账户,和namespace进行关联的,适用于集群内部运行的应用程序,需要通过API来完成授权认证,所以在集群内部进行权限操作,都需要使用到service account。
2) RoleBinding和ClusterRoleBinding: 角色绑定和集群角色绑定,把声明的subject和我们的role进行绑定的过程(给某个用户绑定上操作的权限),二者的区别也是作用范围的区别:rolebinding只会影响到当前namespace下面的资源操作权限,而cluserrolebinding会影响到所有的namespace。
这里可以理解为创建用户,将用户分配到用户组,将用户组的权限和用户进行绑定。
6.4 案例分析
案例一:创建登陆dashboard的用户
创建dashboard用户,并且只能操作kube-system这个命名空间下的pods和deployment,所以需要创建service account对象。
第一步:创建SA对象
kubectl create sa demo-sa -n kube-system
第二步:创建角色kube-sa-role.yaml文件
cd /root/dashboard
vim kube-sa-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: kube-sa-role
namespace: kube-system
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get","watch","list"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get","watch","list","create","update","patch","delete"]
第三步:创建角色
kubectl apply -f kube-role.yaml
[root@master01 dashboard]# kubectl apply -f kube-sa-role.yaml
role.rbac.authorization.k8s.io/kube-sa-role created
查看角色
[root@master01 dashboard]# kubectl get role -n kube-system
NAME AGE
extension-apiserver-authentication-reader 7d4h
kube-sa-role 11s
常用APIgroups列表查询:
https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.15/
第四步:绑定角色
vim kube-sa-rolebinding.yaml
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: kube-sa-rolebinding
namespace: kube-system
subjects:
- kind: ServiceAccount
name: demo-sa
namespace: kube-system
roleRef:
kind: Role
name: kube-sa-role
apiGroup: rbac.authorization.k8s.io
ServiceAccount会生成一个secret对象和它进行映射,这个secret里面包含一个token,如果dashboard也属于kube-system,则这个token可以用来登陆dashboard。
创建角色绑定
[root@master01 dashboard]# kubectl apply -f kube-sa-rolebinding.yaml
rolebinding.rbac.authorization.k8s.io/kube-sa-rolebinding created
[root@master01 dashboard]# kubectl get rolebinding -n kube-system
NAME AGE
kube-sa-rolebinding 18s
第五步:获取token
kubectl get secret -n kube-system | grep demo-sa
[root@master01 dashboard]# kubectl get secret -n kube-system | grep demo-sa
demo-sa-token-rww8s kubernetes.io/service-account-token 3 35m
获取base64
kubectl get secret demo-sa-token-rww8s -o jsonpath={.data.token} -n kube-system |base64 -d
[root@master01 dashboard]# kubectl get secret demo-sa-token-rww8s -o jsonpath={.data.token} -n kube-system |base64 -d
eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkZW1vLXNhLXRva2VuLXJ3dzhzIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImRlbW8tc2EiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJhMWM5MzBkYi00NjMzLTRkNTgtYmJjNS1lODVkNjNhYzk2MjEiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06ZGVtby1zYSJ9.QoWjWeJ_lnzICnTrunulbdHs9ZYE7v-VBMOYEe6T6EKvt_7wGA4pVstne05IAgDX2Qfms8v8ok8rPEyW1AMUK9WmmXUFKDX-b_cUY9hHkcu0rFFea6JZo_mRuW8P62uzORqh_-_tIKoLyWdgAz7DvLKcsnvKvGGyfktrpKF81YOEq5728mZgHQERgRhToTGFbLRufYXZHBZo5jSbjwXl0hfaU4RXgwQpeTPtWBXDxXc0nPoKDlyN1KicKx2OGcbdrnsGbRpTX53VfxJcwo8--6sOf3gDiaajitabOJ238ltBrYQTiPq-sQyDSRsDbPWhnq0Ud7BRHZXhKeBJ1FHiDA
第六步:登陆验证
使用新的token登陆dashboard页面,该用户只能查看命名空间是kube-system的信息。
无法查看default命名空间的信息
可以查看kube-system命名空间的信息
案例二: 创建一个不受限制的SA账号,用于集群内部的认证。
第一步:创建SA(service account)
cat >/root/sa/super-sa.yaml<<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: super-sa
namespace: kube-system
EOF
kubectl apply -f super-sa.yaml
[root@master01 sa]# kubectl apply -f super-sa.yaml
serviceaccount/super-sa created
第二步:创建角色role.yaml文件
系统已经有cluster-admin用户组及相关的权限,可以通过kubectl get clusterrole cluster-admin -o yaml
查看详细信息,所以这里我们就不需要创建角色role,而只需要将super-sa用户绑定到cluster-admin用户组即可
第三步:创建角色
跳过
第四步:绑定用户到角色
cat >super-sa-ClusterRoleBinding.yaml<<EOF
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: super-sa-clusterrolebinding
subjects:
- kind: ServiceAccount
name: super-sa
namespace: kube-system
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
EOF
[root@master01 sa]# kubectl apply -f super-sa-ClusterRoleBinding.yaml
clusterrolebinding.rbac.authorization.k8s.io/super-sa-clusterrolebinding created
第五步:获取token
kubectl get secret -n kube-system | grep super-sa
[root@master01 sa]# kubectl get secret -n kube-system | grep super-sa
super-sa-token-z7cvl kubernetes.io/service-account-token 3 6m57s
kubectl get secret super-sa-token-z7cvl -o jsonpath={.data.token} -n kube-system |base64 -d
[root@master01 sa]# kubectl get secret super-sa-token-z7cvl -o jsonpath={.data.token} -n kube-system |base64 -d
eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJzdXBlci1zYS10b2tlbi16N2N2bCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJzdXBlci1zYSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjJmYzU1NzI4LTA3ZTUtNDJmZS1hZThmLTBhNTBiNzAyNzQ2ZiIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlLXN5c3RlbTpzdXBlci1zYSJ9.iKeak6xiaN4CjLWWp7MJkPq9ekFwJ2JrjsjhRBhEj4Du-W2bZxM5Etk1AhWuDtcAQGVslZ_8Wsa9mmAdTMUFy2iBVJxNVCHNdTp0_qVZIf-2161com0lS2rej6I8OJNzS2-3O8X4_9iEnNfyOcI5_HdTvL7pJMEKWP62W4g6wt498CCbv2QzyWzlMZWjlqc31ig7QRFhm84E6tYnrtfoUclq3EvSxLSOOxhbgF3TxXUGxrM4gqSO7x3jJQ2B3f4MzCFnz5-jLu6f9Qq3y2celEy-ChQoPwJGqtCShIxqm9OPJQ5iD8x1kdl3Wo4fDxt9jLQiRSLYU5Ur3Tkm8Fgl2w
第六步:登陆dashboard测试
使用新的token登陆dashboard后,可以查看所有命名空间的内容,效果等同于管理员账户登录。
案例三:RBAC之yaml授权文件详解:
以我们之前配置prometheus为例来分析权限创建过程
第一步:在monitoring命名空间内创建sa用户prometheus-k8s
[root@master01 prometheus]# kubectl get sa -n monitoring
prometheus-k8s 1 4d2h
第二步:创建角色role
[root@master01 prometheus]# more prometheus-clusterRole.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: prometheus-k8s
rules:
- apiGroups:
- ""
resources:
- nodes/metrics
verbs:
- get
- nonResourceURLs:
- /metrics
verbs:
- get
第三步:查看生成角色
[root@master01 prometheus]# kubectl get ClusterRole |grep prometheus
prometheus-k8s 4d2h
第四步:绑定用户到角色
把prometheus-k8s账户绑定到ClusterRole组内
[root@master01 prometheus]# more prometheus-clusterRoleBinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: prometheus-k8s
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: prometheus-k8s
subjects:
- kind: ServiceAccount
name: prometheus-k8s
namespace: monitoring
第五步:查看secret
[root@master01 prometheus]# kubectl get secret -n monitoring | grep prometheus-k8s
prometheus-k8s-token-v5jb5 kubernetes.io/service-account-token 3 4d2h
案例四:实际操作授权命令
在前章DNS部分我们碰到过一个报错如下:
kubectl run -it --rm --restart=Never --image=infoblox/dnstools:latest dnstools
[root@master01 config]# kubectl run -it --rm --restart=Never --image=infoblox/dnstools:latest dnstools
If you don't see a command prompt, try pressing enter.
Error attaching, falling back to logs: unable to upgrade connection: Forbidden (user=system:anonymous, verb=create, resource=nodes, subresource=proxy)
pod "dnstools" deleted
Error from server (Forbidden): Forbidden (user=system:anonymous, verb=get, resource=nodes, subresource=proxy) ( pods/log dnstools)
出现错误Error from server (Forbidden): Forbidden (user=system:anonymous, verb=get, resource=nodes, subresource=proxy) ( pods/log dnstools)
的解决方法
kubectl create clusterrolebinding system:anonymous --clusterrole=cluster-admin --user=system:anonymous
[root@master01 config]# kubectl create clusterrolebinding system:anonymous --clusterrole=cluster-admin --user=system:anonymous
clusterrolebinding.rbac.authorization.k8s.io/system:anonymous created
报错原因是user=system:anonymous
没有create
和get
的权限
kubectl create clusterrolbinding system:anonymous --clusterrole=cluster-admin --user=system:anonymous
解释:
集群角色绑定用户system:anonymous,拥有cluster-admin的权限,集群角色名称为:system:anonymous.
最后我们再看traefik-rbac.yaml文件就简单明了了。
[root@master01 traefik]# more traefik-rbac.yaml
#创建sa:traefik-ingress-controller
apiVersion: v1
kind: ServiceAccount
metadata:
namespace: kube-system
name: traefik-ingress-controller
---
#创建角色
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: traefik-ingress-controller
rules:
- apiGroups: [""]
resources: ["services","endpoints","secrets"]
verbs: ["get","list","watch"]
- apiGroups: ["extensions"]
resources: ["ingresses"]
verbs: ["get","list","watch"]
- apiGroups: ["extensions"]
resources: ["ingresses/status"]
verbs: ["update"]
- apiGroups: ["traefik.containo.us"]
resources: ["middlewares"]
verbs: ["get","list","watch"]
- apiGroups: ["traefik.containo.us"]
resources: ["ingressroutes"]
verbs: ["get","list","watch"]
- apiGroups: ["traefik.containo.us"]
resources: ["ingressroutetcps"]
verbs: ["get","list","watch"]
- apiGroups: ["traefik.containo.us"]
resources: ["tlsoptions"]
verbs: ["get","list","watch"]
---
#绑定用户到角色
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: traefik-ingress-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: traefik-ingress-controller #role
subjects:
- kind: ServiceAccount
name: traefik-ingress-controller #SA
namespace: kube-system
7. yaml文件详解
7.1 yaml是什么
yaml是一种用来写配置文件的语言,结构上有两种可选的类型:Lists和Maps。list用-(破折号)来定义每一项,map则是一个key:value
的键值对来表示。
yaml语法规则:
大小写敏感
使用缩进表示层级关系
缩进时不允许使用Tab键,只允许使用空格
缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
“#”代表注释,从这个字符一直到行尾,都会被解析器忽略
“---”为可选的分隔符
yaml转properties:http://toyaml.com/index.html
yaml转json:
8. yaml编排配置
8.1 案例一:kubernetes pod编排文件详解
pod在程序中运行的必须的编排文件
apiVersion v1 #必选,指定api版本,此值必须在kubectl api-versions中|
kind: Pod #必选,指定创建资源的角色/类型|
metadata: #必选,资源的元数据/属性
name: test-pod #必选,资源的名字,在同一个namespace中必须唯一
namespace: default #可选,pod所属的命名空间,如不指定则属于默认default命名空间
labels #自定义,设定资源的标签
ks8-app: apache #自定义标签名
version: v1
annotations: #自定义注释列表
- name: string #自定义注解名字
spec: #必选,specfication of the resource content 指定该资源的内容
restartPolicy: Always #可选,表明该容器一直运行,默认k8s的策略,在此容器退出后,会立即创建一个相同的容器,OnFailure表示只有Pod以非0退出码退出才重启,Nerver表示不再重启该Pod
nodeSelector: #节点选择,设置NodeSelector表示将该Pod调度到包含这个label的node上,先给node打标签kubectl label nodes kube-node1 zone=node1
zone: node1 #以key:value的格式指定
containers #必选,pod中容器列表
- name: test-pod #必选,容器的名字
image: chat:latest #必选,容器使用的镜像地址
imagePullPolicy: Never#kubernetes 拉取镜像策略,[Always | Never | IfNotPresent],获取镜像的策略 Alawys表示下载镜像 IfnotPresent表示优先使用本地镜像,否则下载镜像,Nerver表示仅使用本地镜像
command: ["sh"] #启动容器的运行命令,将覆盖容器中的Entrypoint的,对应Dockerfile中的Entrypoint
args: ["$(str)"] #启动容器的命令参数,对应Dockerfile中CMD参数
env: #指定容器中的环境变量
- name: str #变量的名字
value: "/etc/run.sh"#变量的值
resources: #资源管理
requests: #资源请求,容器运行时,最低资源需求,也就是说最少需要多少资源容器才能运行
cpu: 0.1 #cpu资源(核数),两种方式:浮点数或者整数+m,0.1=100m,最少值为0.001核(1m)
memory: 32Mi #容器初始的内存使用量
limits: #资源限制
cpu: 0.5 #cpu限制,单位为core数,将用于docker run --cpu-shares参数
memory: 1000Mi #内存限制,单位可以为Mib/Gib,将用于docker run --memory参数
ports:
- containerPort: 80 #容器开放对外的端口
hostPort: 80 #容器所在主机需要监听的端口号,默认与container相同
name: httpd #端口号名称
protocol: TCP #端口协议,支持TCP和UDP,默认TCP
livenessProbe: #pod内容器健康检查设置
httpGet: #通过httpget检查健康,返回200-399之间,则认为容器正常
path: / #URL地址
port: 80
scheme: HTTP
initialDelaySeconds: 180 #表明第一次检测在容器启动后多长时间后开始
timeoutSeconds: 5 #检测的超时时间
periodSeconds: 15 #检查间隔时间
#也可以用这种方法
#exec: 执行命令的方法进行监测,如果其退出码不为0,则认为容器正常
# command:
# - cat
# - /tmp/health
#也可以用这种方法
#tcpSocket: // 通过tcpsocket检查健康
# port: number
lifecycle: #生命周期管理
postState: #容器运行之前运行的任务
exec:
command:
- 'sh'
- 'yum upgrade -y'
preStop: #容器关闭之前运行的任务
exec:
command: ['service https stop']
volumeMounts: #挂载持久存储卷
- name: volume #挂载设备的名字,与下方volumes[*].name需要对应
mountPath: /data #挂载到容器的/data路径下
readOnly: True #
volumes: #定义一组挂载设备
- name: volume #定义一个挂载设备的名字
#meptyDir: {} #类型为emptyDir的存储卷,与pod同生命周期的一个临时目录,为空值
hostPath: string #类型为hostPath的存储卷,表示挂载pod所在主机的目录
path: /opt #挂载设备类型为hostpath,路径为宿主机下的/opt,这里设备类型支持很多种
#nfs
secret: #类型为secret的存储卷,挂载集群与定义的secre对象到容器内部
scretname: string
items:
- key: string
path: string
configMap: #类型为configMap的存储卷,挂载预定义的configMap对象到容器内部
name: string
items:
- key: string
path: string
8.2 案例二:kubernetes deployment
apiVersion: apps/v1 #1.9.0之前的版本使用apps/v1beta2,可通过命令kubectl api-versions查看
kind: Deployment #指定创建资源的角色/类型
metadata: #资源的元数据/属性
name: web-server #资源的名字,在同一个namespace中必须唯一
spec:
replicas: 2 #pod副本数量
selector: #定义标签选择器
matchLables:
app: web-server #符合目标的pod标签
template: #deployment扩容pod的时候根据此模板
metadata:
labels: #pod的label
app: web-server #pod副本的标签,selector根据此标签选择pod副本
spec: #指定该资源的内容
containers: #定义pod内容器
- name: nginx #容器的名字
image: nginx:latest #容器的镜像地址
ports:
- containerPort: 80 #容器暴露的端口
9. ConfigMap
ConfigMap允许您将配置文件与属性文件分离,以使容器化的应用程序具有可移植性。
- kubernetes空间都可以使用。
- 可以作为变量或者路径文件使用。
- pod支持自动更新内容。
获取系统中的ConfigMap
kubectl get configmap
9.1 案例一: 将ConfigMap中的所有键值对配置为容器环境变量
创建一个包含多个键值对的configmap。
cat >configmap-multikeys.yaml<<EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
SPECIAL_LEVEL: L1
SPECIAL_TYPE: Nginx
EOF
创建configmap
[root@master01 ~]# kubectl apply -f configmap-multikeys.yaml
configmap/special-config created
查看configmap
[root@master01 ~]# kubectl get configmap
NAME DATA AGE
special-config 2 6s
查看configmap详细内容
[root@master01 ~]# kubectl describe configmap special-config
Name: special-config
Namespace: default
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","data":{"SPECIAL_LEVEL":"L1","SPECIAL_TYPE":"Nginx"},"kind":"ConfigMap","metadata":{"annotations":{},"name":"special-co...
Data
====
SPECIAL_LEVEL:
----
L1
SPECIAL_TYPE:
----
Nginx
Events: <none>
创建容器引用configmap
cat >pod-configmap.yaml<<EOF
apiVersion: v1
kind: Pod
metadata:
name: pod-test-configmap
spec:
containers:
- name: pod-test-configmap
image: busybox
command: ["/bin/sh","-c","echo \$(SPECIAL_LEVEL_KEY)\$(SPECIAL_TYPE_KEY)"]
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: SPECIAL_LEVEL
- name: SPECIAL_TYPE_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: SPECIAL_TYPE
restartPolicy: Never
EOF
创建pod,pod里调用我们刚才配置的configmap文件里的2个参数。
kubectl apply -f pod-configmap.yaml
pod/pod-test-configmap created
查看日志可以看到打印出configmap文件内的参数。
[root@master01 configmap]# kubectl logs pod-test-configmap
L1Nginx
9.2 案例二: 将configmap中的所有键值对配置为容器的环境变量
定义配置文件,把redis配置文件存放到configmap
kustomize应用配置管理。
mkdir /root/configmap/redis-confgmap && cd /root/configmap/redis-configmap
cat >kustomization.yaml<<EOF
configMapGenerator:
- name: redis-master-config
files:
- redis-config
resources:
- redis-pod.yaml
EOF
定义redis配置文件
cat>redis-config<<EOF
maxmemory 2mb
maxmemory-policy allkeys-lru
EOF
定义redis pod文件
cat>redis-pod.yaml<<EOF
apiVersion: v1
kind: Pod
metadata:
name: redis
spec:
containers:
- name: redis
image: redis:5.0.4
command:
- redis-server
- "/redis-master/redis.conf"
env:
- name: MASTER
value: "true"
ports:
- containerPort: 6379
hostPort: 6378 #这里使用宿主机的hostport 6378,因为我们在ingress traefik服务已经使用了6379端口,否则在启动容器的时候会报端口已被占用。
protocol: TCP
resources:
limits:
cpu: "0.1"
volumeMounts:
- mountPath: /redis-master-data
name: data
- mountPath: /redis-master
name: config
volumes:
- name: data
emptyDir: {}
- name: config
configMap:
name: redis-master-config
items:
- key: redis-config
path: redis.conf
EOF
创建redis服务
kubectl apply -k .
[root@master01 redis-configmap]# kubectl apply -k .
configmap/redis-master-config-k66gtchdm4 created
pod/redis created
从master02登陆redis,并查看我们设置的内存限制的内容,可以看到已经加载了我们配置的redis.conf
[root@master02 ~]# redis-cli -h 192.168.68.149 -p 6378
192.168.68.149:6378> CONFIG GET maxmemory
1) "maxmemory"
2) "2097152"
192.168.68.149:6378> CONFIG GET maxmemory-policy
1) "maxmemory-policy"
2) "allkeys-lru"
总结一下,可以使用这种方式给应用服务加载配置文件。