第八课:kubernetes核心概念

1.kubernetes对象

服务网络访问:Ingress,Service
容器管理类型:Deployment,Replicaset,ReplicationController,DaemonSet,StatefulSet
容器存储类型:Volume,Secret,Configmap,PersistentVolume

avator

层次结构

avator

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之外的新特性。

  1. Deployment继承了上面描述的RC的全部功能(副本数保持与扩容)。
  2. 容器在升级或者创建过程中,可以查看详细进度和状态。
  3. 当升级Pod镜像或者相关参数的时候,如果发现问题,可以使用回滚操作回滚到上一个稳定的版本或者指定的版本。
  4. 每一次对Deployment的操作,都能保存下来(有操作记录),给与后续可能的回滚使用。
  5. 对于每一次升级,都能够随时暂停和启动(容易控制)。
  6. 多种升级方案:
    a. Recrate:删除所有已存在的pod,重新创建新的。
    b. RollingUpdate: 滚动升级,逐步替换的策略,同时滚动升级时,支持更多的附加参数,例如设置最大不可用pod数量,最小升级间隔时间等。

容器控制器创建pod流程:

  1. 使用deployment来创建replicaset,replicaset则在后台创建pod,检查pod启动状态,是否成功。
  2. 通过更新deployment的PodTemplateSpec字段来申明pod的新状态,之后会创建一个新的replicaset。
  3. 如果新的replicaset启动失败(检查端口策略),则就的replicaset还会继续存在。
  4. 如果扩容成功,则会清理掉旧的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。
使用场景:

  1. 运行集群存储daemon,例如在每个node上运行glusterd,ceph。
  2. 在每个node上运行日志收集daemon,例如fluentd,logstash。
  3. 在每个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代理模式。

  1. iptables模式
    node节点客户端直接访问serviceIP,linux根据iptables协议栈规则策略匹配。
    serviceIP根据标签直接访问Backend Pod。

  2. ipvs代理模式
    ipvs是LVS的一个组件,提供高性能,高可靠性的四层负载均衡器。ipvs是ip virtual server的简写。ipvs构建在netfilter上,作为linux内核的一部分,从传输层实现了负载均衡。ipvs能直接转发基于service的tcp和udp到真实服务器。ipvs能直接构建一个vips并通过负载均衡算法,把请求转发到backend pod。
    算法:
    轮询
    基于权重的轮询
    最小连接数
    基于源地址
    目的地址hash

3.3 service的基本类型(service type)

  1. clusterIP
    通过集群内部的IP暴露服务,选择该值,服务只能够在集群内部访问,这也是默认的service type
  2. nodePort
    通过每个node上的ip和静态端口暴露服务,nodeport服务会路由到clusterip服务,这个clusterip服务会自动创建。通过请求:,可以从集群的外部访问一个nodePort服务。
  3. 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。

  1. nodeport
    通过每个node上的ip和静态端口暴露服务,nodeport服务会路由到clusterip服务,这个clusterip服务会自动创建。通过请求:,可以从集群的外部访问一个nodePort服务。
  2. loadbalance
    使用云提供商的负载均衡器,可以向外部暴露服务。外部的负载均很气可以路由到nodePort服务和clusterIP服务。
  3. 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有三种类型:

  1. service account:用来访问kubernetes API,有kubernetes自动创建,并且会自动挂载到pod的/run/secrets/kubernetes.io/serviceaccount目录中。
  2. opaque: base64编码格式的secret,用来存储密码,密钥等。
  3. 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中的其他对象

  1. rule:规则,规则是一组属于不通API group资源上的一组操作的集合。
  2. 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命名空间的信息
avator
可以查看kube-system命名空间的信息
avator

案例二: 创建一个不受限制的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没有createget的权限
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允许您将配置文件与属性文件分离,以使容器化的应用程序具有可移植性。

  1. kubernetes空间都可以使用。
  2. 可以作为变量或者路径文件使用。
  3. 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"

总结一下,可以使用这种方式给应用服务加载配置文件。

posted @ 2020-08-24 11:19  Doc-Yu  阅读(422)  评论(0编辑  收藏  举报