目录
[3.4,Service Account](#3.4,Service Account)
一、Service与服务发现
1.1,Service资源基本概念
Service是Kubernetes标准的API资源类型之一,主要功能如下:
1,服务发现 (发现一组提供了相同服务的Pod):通过标签选择器,在同一名称空间中筛选符合的条件的Pod(实际上并非由Service资源自己完成,而是借助于被称为Endpoints/EndpointSlice完成的;
2,负载均衡(Service作为流量入口和负载均衡器,其入口为ClusterIP):由服务发现筛选出的Pod的IP地址,将作为该Service的后端服务器进行调度;
3,为该组Pod所代表的服务提供一个名称:依赖于Cluster DNS,对于每个Service,自动生成一个A、PTR和SRV记录(端口名称解析)。
Service类型(根据其所支持的客户端接入的方式):--ClusterIP:支持Service_IP:Service_Port接入
流量方向: Client --> Service_IP:Service_Port --> Pod_IP:Pod_Port
--NodePort:支持Node_IP:Node_Port接入,是ClusterIP的增强版
流量方向: Client --> Node_IP:NodePort --> Pod_IP:Pod_Port
--LoadBalancer:支持通过外部的LoadBalancer的LB_IP:LB_Port接入,是NodePort的增强版,流量方向:
Client --> LB_IP:LB_PORT --> Node_IP:NodePort --> Pod_IP:Pod_Port
--ExternalName:将集群内部定义的service名称直接解析为集群外部service服务名称,并通过外部DNS服务器将服务名称解析为真实的IP(后续将外部服务迁移至内部集群后对service类型进行调整即可修改为内部服务类型)
externalTrafficPolicy(外部流量策略)参数:
Cluster----请求报文从哪个节点进入,该节点上的Service会调度至任一可用后端Pod(存在跨节点网络损耗)
Local-------请求报文从哪个节点进入,Service只会调度至本节点的后端Pod(需要外部LB,只能把流量转发给运行有该Service关联的Pod的Node之上)
Service组成:1,负载均衡器入口:ClusterIP及相关的Service Port、NodePort
2,标签选择器:用于筛选Pod,并基于筛选出的Pod的IP生成后端端点列表
3,Service类型的专有配置
--标签:附加在资源对象上的键值型元数据
键标识:由"键前缀(可选)"和"键名"组成,键前缀必须使用DNS域名格式
键名的命名格式:支持字母、数字、连接号、下划线和点号,且只能以字母或数字开头,最长63个字符
--标签选择器:基于标签筛选对象的过滤条件,支持两种类型
基于等值关系(==,!=)
基于集合关系(in,notin,exists)
1.2,名称解析
Cluster DNS(CoreDNS)是Kubernetes集群的必备附件,负责提供名称解析和服务发现,会持续监视API Server上的Service资源对象的变动,并实时反映到相关的DNS资源记录中。每个Service资源对象,在CoreDNS上都会自动生成一个遵循"<service>.<ns>.svc.<zone>"(zone为集群域名,默认为cluster.local)格式的名称,如demoservice.demo.svc.cluster.local。
A,AAAA记录-----Service名称解析为ClusterIP
PTR记录------------ClusterIP解析为服务名称
SRV记录------------Service端口名称解析为Service端口号
Pod创建时,容器默认会在/etc/resolve.conf中,将其nameserver指向CoreDNS的ip地址(默认为Service Network中的第10个地址),还会自动配置搜索域。
Kubernetes支持在单个Pod资源规范上自定义DNS解析策略和配置,并组合生效:
spec.dnsPolicy:解析策略--Default:从运行在的节点继承DNS名称解析相关的配置
--ClusterFirst:于集群DNS服务上解析集群域内的名称,其他域名的解析则交由从节点继承而来的上游名称服务器
--ClusterFirstWithHostNet:对于设置了hostNetwork(直接共享宿主机网络名称空间)的Pod对象,优先在集群DNS服务上解析集群域内的名称
--None:用于忽略Kubernetes集群的默认设定,而仅使用由dnsConfig自定义的配置
spec.dnsConfig:名称解析机制
--nameservers:DNS名称服务器列表,附加于由dnsPolicy生成的DNS名称服务器之后
--searches:DNS名称解析时的搜索域,附加由于dnsPolicy生成的搜索域之后
--options :DNS解析选项列表,同dnsPolicy生成的解析选项合并成最终生效的定义
Headless Service:广义上,没有ClusterIP的Service统称为Headless Service,可以分为两种情况
1,有标签选择器,或者没有标签选择器,但有着与Service对象同名的Endpoint资源
2,无标签选择器且也没有与Service对象同名的Endpoint资源
Service的DNS名称会生成一条CNAME记录,对应值由Service对象上的spec.externalName字段指定
二、应用编排
Kubernetes是以应用为中心的容器编排系统,对应用生命周期(部署,扩容和缩容,更新,卸载)管理,有专用的控制器--工作负载型控制器(WorkLoad Controller)。根据应用编排需求可以将工作负载型控制器分为以下几种:
1,服务端应用:始终处于运行状态
Deployment(编排无状态应用):基于ReplicaSet实现软件滚动更新
ReplicaSet(编排无状态应用):完成应用的部署、扩缩容、卸载等
StatefulSet(编排有状态应用):
DaemonSet(专用于编排系统级应用,在集群中的每一个节点部署且仅部署一个实例)
2,作业类应用:存在运行结束的时刻,终止而退出
Job(运行一次的任务)
CronJob(基于特定的时间周期重复或反复运行的Job):会创建jobTemplate(Job模板),通过模板定时创建Job
2.1,Deployment控制器
ReplicaSet是负责编排无状态应用的基础控制器,相应的资源类型通过三个关键组件定义如何编排一个无状态应用
--replicas:期望运行的Pod副本数
--selector:标签选择器
--podTemplate:Pod模板
Deployment是建立在ReplicaSet上层的高级控制器,当应用内容发生变化时会生成新的ReplicaSet,并通过保有多个ReplicaSet(此时相当于模板)实现应用的滚动更新和回滚。其更新策略有以下两种:
--滚动式更新(RollingUpdate) :逐批次更新Pod的方式,支持按百分比或具体的数量定义批次规模,默认策略;触发条件:podTemplate的Hash码变动(产生的问题:必须以Pod为原子单位切割规模比例,且无法控制流量路由比例)
--重建式更新(Recreate):在Pod资源被删除时,使用新的模板定义被足缺失的Pod数量,完成更新
拓展HPA--Horizontal Pod AutoScaler(横向自动扩容管理器):通过关联的指标(CPU,Memory,自定义的指标)的变动增加或减少Pod数量
VPA--Vertical Pod AutoScaler(纵向自动扩容管理器):通过更改Pod的资源限制更改CPU和Memory的数值
2.2,DaemonSet和StatefulSet控制器
DaemonSet与Deployment类似,基于标签选择器管控一组Pod副本,用于确保所有或选定的工作节点上都运行有一个Pod,主要运用于集群存储守护进程、集群日志收集守护进程以及节点监控守护进程等。与Deployment不同的是,DaemonSet不需要定义replicas数量,其Pod 数随选定的节点数而定。
DaemonSet更新策略:
--rollingUpdate:滚动更新,自动触发
--onDelete:删除时更新,手动触发
StatefulSet负责编排有状态的应用,这些应用主要负责保存业务逻辑模块产生的状态数据,如消息队列,数据库和缓存系统等。在Kubernetes内依赖几个特殊设计实现:
1,各Pod副本分别具有唯一的名称标识,这依赖于一个专用的Headless Service实现
2,基于Pod管理策略(Pod Management Policy),定义创建、删除及扩缩容等管理操作期间,Pod副本操作机制:
--OrderedReady:顺次进行Pod创建,只有前一个Pod状态转为Reday才能进行下一步操作
--Parallel:各Pod副本的创建或删除可同时进行
3,各Pod副本存储的状态数据并不相同,因而需要稳定的Volume
有状态的应用或分布式服务在启动,扩容,缩容等操作上差异过大甚至完全不同,因而StatefulSet只能提供一个基础的编排框架,若要对该类应用执行管理操作,需要由用户自行编写代码完成,因此为更好的管理有状态应用需要使用Operator(增强型控制器)。
Operator 是 Kubernetes 的扩展软件, 它利用定制的资源类型来增强自动化管理应用及其组件的能力,从而扩展了集群的行为模式, 使用自定义资源(例如CRD)来管理应用程序及其组件,可通过operatorhub官网获取该类资源。 OperatorHub.io | The registry for Kubernetes OperatorsThe registry for Kubernetes Operatorshttps://operatorhub.io/
2.3,Job和CronJob控制器
Job负责编排运行有结束时间的一次性任务,但是有些Job可以运行多次(次数固定)。Job资源需要标签选择器和Pod模板,但不需要指定replicas,而是给定completions(即需要完成的作业次数,默认为1次),同时若要设置并行Job还需要指定parallelism的值(任务并行度,即最大可同行运行的Pod数量)
注意:
Job所在资源组为batch/v1
Job资源中Pod的RestartPolicy只能为Never或OnFailure
CronJob是Job的高级的控制器,以Job控制器完成单批次的任务编排。在资源内需指定schedule(调度时间设定),此处使用的通配符"?"和"*"意义 相同,都表示任何可用的有效值
三、认证体系
API Server是Kubernetes集群的网关,是能够与etcd通信惟一入口,因此对API Server的安全访问至关重要,在API Server内置了一个三级访问控制机制:
认证 :鉴别用户身份,并确保仅得到许可的用户进行访问
授权 :鉴别操作权限,依赖认证过程识别出的用户身份
准入控制:将数据写入etcd前负责检查内容的有效性,仅生效于写操作,分为两类:validating(效验), mutating(补全)
以上控制机制均支持多种插件栈,认证与授权过程遵循或逻辑满足一种插件认证即可通过,准入控制检查过程遵循与逻辑且无论成败,每次的操作请求都要经由所有插件的检验
3.1,认证介绍
Kubernetes上的用户为服务请求者的身份指代,一般使用身份标识符(包括用户标识【用户名或用户ID】和用户组)进行识别,其用户大体可分为 2 类:
Service Account:服务账户,指Pod内的进程访问API Server时使用的身份信息
User Account:用户账户,指非Pod类的客户端访问API Server时使用的身份标识
不能被识别为Service Account或User Account的用户,通称为匿名用户,建议禁用匿名用户认证
身份认证策略:-X.509客户端证书认证
-持有者令牌(bearer token)
-静态令牌文件(Static Token File)
--Bootstrap令牌
--Service Account令牌
--OIDC(OpenID Connect)令牌
--Webhook令牌
-身份认证代理(Authenticating Proxy)
-匿名请求
kubeadm v1.29部署的集群默认启用的认证在/etc/kubernetes/manifests/kube-apiserver.yaml文件内可查看,依次是
--X509客户端证书认证
--Bootstrap令牌认证
--身份认证代理
--Service Account认证
注意:各认证插件的生效测序并不一定与定义的次序相同
3.2,X.509数字认证
在双向TLS通信中,API Server内的CA(通过--client-ca-file传递选项,默认存储位置/etc/kubernetes/pki/ca.crt)签发客户端证书即可完成认证,客户端数字证书中的CN(Common Name)即被识别为用户名,而O(Organization)被识别为组名。
#配置证书认证
root@k8s-master02:~# cd /etc/kubernetes/pki/ #进入控制节点的CA证书存储位置
root@k8s-master02:/etc/kubernetes/pki# (umask 077; openssl genrsa -out ming.key 4096) #生成私钥
root@k8s-master02:/etc/kubernetes/pki# openssl req -new -key ./ming.key -out ./ming.csr -subj '/CN=ming/O=kubeadmin' #创建证书签署请求
root@k8s-master02:/etc/kubernetes/pki#openssl x509 -req -days 3650 -CAkey ./ca.key -CA ./ca.crt -CAcreateserial -in ./ming.csr -out ./ming.crt #由CA签署证书
root@k8s-master02:/etc/kubernetes/pki# rsync -a ./ming.crt ./ming.key 172.29.7.13:/etc/kubernetes/pki/ #将证书文件下载至客户端
#测试证书root@k8s-work01:~# cd /etc/kubernetes/pki/ #进入证书存储位置
root@k8s-work01:/etc/kubernetes/pki#ls #客户端需要以下证书
ca.crt ming.crt ming.key
root@k8s-work01:/etc/kubernetes/pki# kubectl -s https://172.29.7.10:6443 --client-certificate=./ming.crt --client-key=./ming.key --certificate-authority=./ca.crt get pods #使用kucectl命令通过URL方式访问pod(未授权所以结果未禁止访问)
Error from server (Forbidden): pods is forbidden: User "ming" cannot list resource "pods" in API group "" in the namespace "default"
root@k8s-work01:/etc/kubernetes/pki# kubectl get pods --client-certificate=./ming.crt --client-key=./ming.key --certificate-authority=./ca.crt --server=https://kubeapi.wlm.com:6443/ #使用kucectl命令直接访问Pod
Error from server (Forbidden): pods is forbidden: User "ming" cannot list resource "pods" in API group "" in the namespace "default"
3.3,静态令牌认证
静态令牌信息保存于CSV文件内,每行定义一个用户,由由"令牌、用户名、用户ID和所属的用户组"四个字段组成,由kube-apiserver在启动时通过--token-auth-file选项加载(对kube-apiserver的修改会自动加载),加载完成后文件的变动只能通过重启程序进行重载。可以使用curl命令通过"Authorization Bearer TOKEN"标头附带令牌完成身份认证。
静态令牌认证信息保存在yaml格式的kubeconfig文件内,kubeconfig文件可以保存认证到一至多个Kubernetes集群的相关配置信息,并允许管理员按需在各配置间灵活切换
--clusters:Kubernetes集群访问端点(API Server)列表
--users:认证到API Server的身份凭据列表
--contexts:将每一个user同可认证到的cluster建立关联的上下文列表
--current-context:当前默认使用的context
客户端程序加载的kubeconfig文件的方法:
1,添加--kubeconfig选项
2,配置KUBECONFIG环境变量:其值可以是包含有kubeconfig文件的列表
3,默认路径:$HOME/.kube/config
#控制节点kubeconfig参数查询root@k8s-master01:~# kubectl config get-clusters
NAME
kubernetes
root@k8s-master01:~# kubectl config get-users
NAME
kubernetes-admin
root@k8s-master01:~#kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* kubernetes-admin@kubernetes kubernetes kubernetes-admin
root@k8s-master01:~#kubectl config current-context
kubernetes-admin@kubernetes
root@k8s-master01:~#kubectl config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://kubeapi.wlm.com:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
user:
client-certificate-data: DATA+OMITTED
client-key-data: DATA+OMITTED
#在控制节点02上配置静态令牌(以下配置只在当前节点生效,要使其他控制节点生效需要同时修改配置)root@k8s-master02:~# echo "(openssl rand -hex 3).(openssl rand -hex 8)" #通过命令生成随机字符作为token令牌
e559dd.7180594a120eadf7
root@k8s-master02:~# mkdir /home/bak
root@k8s-master02:~#cp -a /etc/kubernetes/manifests/kube-apiserver.yaml /home/bak/ #复制api server文件修改后再覆盖,避免直接修改文件过程中配置生效
root@k8s-master02:~# cp -a /etc/kubernetes/manifests/kube-apiserver.yaml /root/ #备份
root@k8s-master02:~# cd /etc/kubernetes/
root@k8s-master02:/etc/kubernetes# mkdir authfile
root@k8s-master02:/etc/kubernetes# vim ./authfile/tokens.csv #创建静态令牌保存文件
e559dd.7180594a120eadf7,fang,1001,kubeadmin
26a9db.5e7f112e3e4f56dc,hong,1002,kubeuser
7775d6.6d6a3dba90339f09,wang,1003,kubeadmin
root@k8s-master02:/etc/kubernetes# cd /root
root@k8s-master02:~# vim /home/bak/kube-apiserver.yaml #启用静态令牌参数
......
--authorization-mode=Node,RBAC
--token-auth-file=/etc/kubernetes/authfile/tokens.csv
......
- mountPath: /etc/kubernetes/authfile/tokens.csv
name: static-tokens
readOnly: true......
- hostPath:
path: /etc/kubernetes/authfile/tokens.csv
type: FileOrCreate
name: static-tokens......
root@k8s-master02:~# cp /home/bak/kube-apiserver.yaml /etc/kubernetes/manifests/kube-apiserver.yaml #覆盖旧文件进行更新
root@k8s-work01:~# kubectl --server=https://172.29.7.11:6443 --token='26a9db.5e7f112e3e4f56dc' --insecure-skip-tls-verify=true get pods #在工作节点可指定调度的控制节点和token进行访问测试,此时认证通过但是无权限
Error from server (Forbidden): pods is forbidden: User "hong" cannot list resource "pods" in API group "" in the namespace "default"
root@k8s-work01:~# cd /etc/kubernetes/pki/
root@k8s-work01:/etc/kubernetes/pki# kubectl config set-cluster mykube --embed-certs=true --certificate-authority=./ca.crt --server="https://kubeapi.wlm.com:6443" #创建集群
Cluster "mykube" set.
root@k8s-work01:/etc/kubernetes/pki# kubectl config set-cluster kube01 --embed-certs=true --certificate-authority=./ca.crt --server="https://172.29.7.10:6443"
Cluster "kube01" set.
root@k8s-work01:/etc/kubernetes/pki# kubectl config set-cluster kube02 --embed-certs=true --certificate-authority=./ca.crt --server="https://172.29.7.11:6443"
Cluster "kube02" set.
root@k8s-work01:/etc/kubernetes/pki#ls /root/.kube/ #查看工作节点默认kubeconfig文件位置
cache config
root@k8s-work01:/etc/kubernetes/pki# kubectl config view #查看工作节点默认kubeconfig配置为空
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://kubeapi.wlm.com:6443
name: mykube
contexts: null
current-context: ""
kind: Config
preferences: {}
users: null
root@k8s-work01:/etc/kubernetes/pki#kubectl config set-credentials ming --embed-certs=true --client-certificate=./ming.crt --client-key=./ming.key #创建证书认证的用户
User "ming" set.
root@k8s-work01:/etc/kubernetes/pki#kubectl config set-credentials fang --token='e559dd.7180594a120eadf7' #创建静态令牌认证的用户
User "fang" set.
root@k8s-work01:/etc/kubernetes/pki# kubectl config set-context ming@mykube --cluster=mykube --user=ming #创建上下文
Context "ming@mykube" created.
root@k8s-work01:/etc/kubernetes/pki# kubectl config get-users #依次创建以下用户
NAME
fang
hong
ming
wang
root@k8s-work01:/etc/kubernetes/pki# kubectl config get-clusters #依次创建以下集群
NAME
mykube
kube01
kube02
root@k8s-work01:/etc/kubernetes/pki# kubectl config get-contexts #生成如下的上下文
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
fang@mykube mykube fang
hong@kube02 kube02 hong
ming@mykube mykube ming
wang@kube01 kube01 wang
root@k8s-work01:/etc/kubernetes/pki#kubectl config current-context #查看当前上下文
error: current-context is not set
root@k8s-work01:/etc/kubernetes/pki# kubectl config use-context ming@mykube #指定当前上下文
Switched to context "ming@mykube".
root@k8s-work01:/etc/kubernetes/pki# kubectl get pods #使用Ca签发证书的用户指向集群代理认证正常
Error from server (Forbidden): pods is forbidden: User "ming" cannot list resource "pods" in API group "" in the namespace "default"
root@k8s-work01:/etc/kubernetes/pki# kubectl config use-context fang@mykube
Switched to context "fang@mykube".
root@k8s-work01:/etc/kubernetes/pki# kubectl get pods #静态令牌只在控制节点2配置,故指向集群代理的fang用户无法通过认证
error: You must be logged in to the server (Unauthorized)
root@k8s-work01:/etc/kubernetes/pki# kubectl config use-context hong@kube02
Switched to context "hong@kube02".
root@k8s-work01:/etc/kubernetes/pki# kubectl get pods #静态令牌只在控制节点2配置,故指向控制节点2的hong用户可以通过认证
Error from server (Forbidden): pods is forbidden: User "hong" cannot list resource "pods" in API group "" in the namespace "default"
root@k8s-work01:/etc/kubernetes/pki# kubectl config use-context wang@kube01
Switched to context "wang@kube01".
root@k8s-work01:/etc/kubernetes/pki#kubectl get pods #静态令牌只在控制节点2配置,故指向控制节点1的wang用户无法通过认证
error: You must be logged in to the server (Unauthorized)
#对以上错误上下文重新修改
root@k8s-work01:/etc/kubernetes/pki# kubectl config use-context ming@mykube
root@k8s-work01:/etc/kubernetes/pki#kubectl config get-contexts #修改过程省略,修改所有令牌认证用户指向控制节点2,结果如下
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
fang@kube02 kube02 fang
hong@kube02 kube02 hong
* ming@mykube mykube ming
wang@kube02 kube02 wang
3.4,Service Account
ServiceAccount是以Pod形式运行的进程应用托管于Kubernetes上,需要直接与API Server交互获取自身信息,以及能够管理所处集群上特定名称空间下资源或集群本身权限的情况下,能够完成认证功能所需要的账号类型。
ServiceAccount是API Server支持的标准资源类型之一,当Pod创建后会由准入控制器附加一个 SA,通常是在名称空间下默认的ServiceAccount,也可以通过Service Account和Service AccountName参数自行指定。
ServiceAccount创建命令:kubectl create serviceaccount NAME --dry-run=server|client|none
四、鉴权体系
API Server中支持的鉴权模块:
Node:专用的授权模块,它基于kubelet将要运行的Pod向kubelet进行授权;
ABAC:通过将属性(包括资源属性、用户属性、对象和环境属性等)组合在一起的策略,将访问权限授予用户;
RBAC:基于企业内个人用户的角色来管理对计算机或网络资源的访问的鉴权方法;
Webhook:用于支持同Kubernetes外部的授权机制进行集成;
特殊的鉴权模块:
--AlwaysDeny
--AlwaysAllow
API Server鉴权模块配置方法:
在kube-apiserver上使用 --authorization-mode 选项进行定义,多个模块彼此间以逗号分隔(使用kubeadm部署的集群,默认启用了Node和RBAC )
4.1,RBAC鉴权模型
RBAC基础概念:
实体(Entity):也称为Subject,通常指的是User、Group或者是ServiceAccount;
角色(Role):承载资源操作权限的容器;
资源(Resource):也称为Object,指代Subject期望操作的目标,例如Secret、Pod及Service对象等,通常起始的路径为/api/v1/和/apis/<group>;其它路径对应的端点均被视作"非资源类请求(Non-Resource Requests)",例如/api或/healthz等端点;
动作(Actions):Subject可以于Object上执行的特定操作,具体的可用动作取决于Kubernetes的定义
-资源型对象
--只读操作:get、list、watch等
--读写操作:create、update、patch、delete、deletecollection等
-非资源型端点仅支持get操作
角色绑定(Role Binding):将角色关联至实体上,它能够将角色具体的操作权限赋予给实体;
|------------|------------------------------------|--------------------------|
| 资源级别 | Cluster级别 | NameSpace级别 |
| 角色类型 | ClusterRole | Role |
| 定义范围 | 集群范围内的资源操作权限集合, 包括集群级别及名称空间级别的资源对象 | 名称空间范围内的资源操作权限集合 |
| 角色绑定类型 | ClusterRoleBinding | RoleBinding |
| 定义范围 | 可以将实体关联至ClusterRole | 可以将实体关联至ClusterRole或Role |
| 将实体使用RoleBinding关联至ClusterRole后,实体的权限会降级至RoleBinding所属的名称空间范围内 |||
|--------------------|---------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------|
| 默认的ClusterRole | 默认的ClusterRoleBinding | 描述 |
| cluster-admin | system:masters组 | 允许用户在目标范围内的任意资源上执行任意操作;使用ClusterRoleBinding关联至用户时,授权操作集群及所有名称空间中任何资源;使用RoleBinding关联至用户时,授权控制其所属名称空间中的所有资源,包括Namespace资源自身; |
| admin | | 管理员权限,主要用于结合RoleBinding为特定名称空间快速授权生成管理员用户,它能够将RoleBinding所属名称空间中的大多数资源的读/写权限授予目标用户,包括创建RoleRoleBinding的能力;但不支持对ResourceQuota及Namespace本身进行操作; |
| edit | | 接近于admin的权限,支持对名称空间内的大多数对象进行读/写操作,包括Secret,但不允许查看或修改Role及RoleBinding; |
| view | | 允许以只读方式访问名称空间中的大多数对象,但不包括Role、RoleBinding和Secret |
4.2,RBAC鉴权使用示例
root@k8s-master01:~# kubectl create role pods-viewer --verb='get,list,watch' --resource='pods' --namespace='default' --dry-run=client -o yaml #创建role并赋予资源类型和权限
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
creationTimestamp: null
name: pods-viewer
namespace: default
rules:
apiGroups:
""
resources:
- pods
verbs:
get
list
watch
root@k8s-master01:~# kubectl create role pods-viewer --verb='get,list,watch' --resource='pods' --namespace='default' --dry-run=client -o yaml > role-pods-viewer.yaml
root@k8s-master01:~# kubectl create rolebinding fang-pods-viewer --role=pods-viewer --user=fang -n default --dry-run=client -o yaml #绑定user和role的关系
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
creationTimestamp: null
name: fang-pods-viewer
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: pods-viewer
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: fang
root@k8s-master01:~#kubectl create rolebinding fang-pods-viewer --role=pods-viewer --user=fang -n default --dry-run=client -o yaml > rolebinding-fang-pods-viewer.yaml
root@k8s-master01:~#kubectl apply -f role-pods-viewer.yaml
root@k8s-master01:~# kubectl apply -f rolebinding-fang-pods-viewer.yaml
root@k8s-work01:~#kubectl config use-context fang@kube02 #在work节点测试
root@k8s-work01:~# kubectl get pods -n default
NAME READY STATUS RESTARTS AGE
demoapp-7c58cd6bb-rsrj8 1/1 Running 2 (62m ago) 11d
demoapp-7c58cd6bb-z9wp4 1/1 Running 2 (62m ago) 11d
#创建jenkins名称空间下的ServiceAccount/jenkins-master,并授予其具有jenkins名称空间的管理权限
root@k8s-master01:~# kubectl create ns jenkins
root@k8s-master01:~# kubectl create serviceaccount jenkins-service -n jenkins --dry-run=client -o yaml > jenkins-service.yaml
root@k8s-master01:~# kubectl create rolebinding jenkins-master --role=admin --serviceaccount=jenkins:jenkins-service --dry-run=client -o yaml > jenkins-master.yaml
五、Ingress与应用发布
5.1,Ingress基本概念
Kubernetes内的Service是四层负载均衡器,支持流量分发、可做为流量网关,但不支持基于内容的分发,也不支持TLS会话卸载。主要是借助于各节点的Kube Proxy实现,存在两种实现方式:iptables和ipvs。
为了弥补四层负载均衡器的不足,引入了七层负载均衡器Ingress。Ingress是API Server上的标准资源类型,通过通用的ingress格式来定义流量代理和分发策略,基本组成如下:
--Ingress API:者负责以k8s标准的资源格式定义流量调度、路由等规则
--Ingress Controller:负责监视(watch)Ingress并生成自身的配置,并据此完成流量转发。通常以Pod形式额外部署于Kubernetes集群,一般应该由专用的LB Service负责为其接入集群外部流量(若安无外部LB,可以动修改Service配置文件将node上未使用的IP作为外部IP,具体做法未在spec字段添加externalIPs: - IP地址,再将nginx-controller的service内修改externalTrafficPolicy模式为cluster)
Ingress-control具有多种实现方案,如Ingress-Nginx、HAProxy、Traefik、Gloo、Contour和Kong等,Kubernetes支持同时部署二个或以上的数量的Ingress Controller。当部署多个Ingress-control 时,可通过特定的annotation 或spec中嵌套ingressClassName字段指明期望加载该资源的Ingress Controller。
流量转发过程:
客户端将流量(client)转发给-->外部负载均衡器(LB Service),如OpenELB、MetaILB等-->会传输到Ingress Controller Pod控制器,由控制器进行转发-->最后直接调度到被请求的后端服务Upstream Pod
Ingress Controller需要依赖Upstream Service的服务发现功能来确认可被调度的Upstream Pod,但是流量不会由Ingress Controller Pod发往Upstream Service。
5.2,Ingress资源类型
Ingress类型
1, 使用基于FQDN的虚拟主机(即多域解析同一IP),来接入发往不同后端服务的流量
2,若需要在同一个FQDN所代表的虚拟主机上,可以指定不同的URI,来接入发往不同后端服务的流量
3,为以上两种类型提供TLS8机制,仅限于443/TCP端口(TLS Secret必须包含名为tls.crt和 的密钥tls.key,它们分别含有TLS的证书和私钥)
#准备环境,在default名称空间下创建两个demoapp及service服务root@k8s-master01:~# kubectl create deployment demoapp10 --image=ikubernetes/demoapp:v1.0 --replicas=3
root@k8s-master01:~# kubectl create service clusterip demoapp10 --tcp=80:80
root@k8s-master01:~# kubectl create deployment demoapp11 --image=ikubernetes/demoapp:v1.1 --replicas=3
root@k8s-master01:~# kubectl create service clusterip demoapp11 --tcp=80:80
root@k8s-master01:~# kubectl get ep #查看当前名称空间下的enterpoints
NAME ENDPOINTS AGE
demoapp10 10.244.2.18:80,10.244.3.16:80,10.244.4.38:80 118s
demoapp11 10.244.2.19:80,10.244.3.17:80,10.244.4.39:80 3s
kubernetes 172.29.7.10:6443,172.29.7.11:6443,172.29.7.12:6443 19d
#为demoapp10创建ingress
root@k8s-master01:~# kubectl get ingressclass #查看当前名称空间默认ingress控制器
NAME CONTROLLER PARAMETERS AGE
nginx k8s.io/ingress-nginx <none> 18d
root@k8s-master01:~# kubectl create ingress demoapp10 --rule="www.wlm.com/*"=demoapp10:80 --class=nginx --dry-run=client -o yaml #创建ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
creationTimestamp: null
name: demoapp10
spec:
ingressClassName: nginx
rules:
- host: www.wlm.com
http:
paths:
- backend:
service:
name: demoapp10
port:
number: 80
path: /
pathType: Prefix
status:
loadBalancer: {}
root@k8s-master01:~# kubectl create ingress demoapp10 --rule="www.wlm.com/*"=demoapp10:80 --class=nginx --dry-run=client -o yaml > ingress-demoapp10.yaml
root@k8s-master01:~# kubectl apply -f ingress-demoapp10.yaml
ingress.networking.k8s.io/demoapp10 created
root@k8s-master01:~#kubectl get ingresses #查看当前名称空间的ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
demoapp10 nginx www.wlm.com 80 3s
root@k8s-master01:~# kubectl get service -n ingress-nginx #查看ingress外部IP
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller LoadBalancer 10.109.123.184 172.29.7.52 80:30189/TCP,443:30862/TCP 18d
ingress-nginx-controller-admission ClusterIP 10.109.0.131 <none> 443/TCP 18d
#在本地主机将www.wlm.com解析至172.29.7.52,在本地浏览器即可访问demoapp10;此时本地通过IP172.29.7.52可以同时解析到www.wlm.com和kuboard.wlm.com
#同一个FQDN虚拟主机上,指定不同的URI
root@k8s-master01:~# kubectl create ingress demoapp11 --rule="baidu.wlm.com/pc(/|)(.\*)"=demoapp10:80 --rule="baidu.wlm.com/phone(/\|)(.*)"=demoapp11:80 --class=nginx --annotation nginx.ingress.kubernetes.io/rewrite-target='/$2' --dry-run=client -o yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
creationTimestamp: null
name: demoapp11
spec:
ingressClassName: nginx
rules:
- host: baidu.wlm.com
http:
paths:
- backend:
service:
name: demoapp10
port:
number: 80
path: /pc(/|$)(.*)
pathType: Exact
- backend:
service:
name: demoapp11
port:
number: 80
path: /phone(/|$)(.*)
pathType: Exact
status:
loadBalancer: {}
root@k8s-master01:~# kubectl create ingress demoapp11 --rule="baidu.wlm.com/pc(/|)(.\*)"=demoapp10:80 --rule="baidu.wlm.com/phone(/\|)(.*)"=demoapp11:80 --class=nginx --annotation nginx.ingress.kubernetes.io/rewrite-target='/$2' --dry-run=client -o yaml > ingress-baidu.yaml
root@k8s-master01:~# kubectl apply -f ingress-baidu.yaml
六、网络插件
6.1,网络插件基本概念
CNI的全称为"容器网络接口",它是容器引擎与遵循该规范网络插件的中间层,专用于为容器配置网络子系统 ,目前的CNI规范主要由NetPlugin和IPAM两个插件API组成:
网络插件也称Main插件 ,负责创建/删除网络 以及**向网络添加/删除容器,**它专注于连通容器与容器之间以及容器与宿主机之间的通信,同容器相关网络设备通常都由该类插件所创建,例如bridge、ipvlan、macvlan、loopback、ptp、veth以及vlan等虚拟设备;
IPAM的全称"IP Address Management" ,该类插件负责创建/删除地址池 以及分配/回收容器的IP地址,该类型插件的实现主要有host-local和dhcp两个,前一个基于预置的地址范围进行地址分配,而后一个通过dhcp协议获取地址。
NetPlugin常用实现方案有叠加网络(Overlay Network)和承载网络(Underlay Network)两类:承载网络通常使用direct routing(直接路由)技术在Pod的各子网间路由Pod的IP报文,或使用bridge、macvlan或ipvlan等技术直接将容器暴露至外部网络中。
叠加网络借助于VXLAN、UDP、IPIP或GRE等隧道协议,通过隧道协议报文封装Pod间的通信报文(IP报文或以太网帧)来构建虚拟网络。
叠加网络的底层网络也就是承载网络,相当于在承载网络上添加了隧道协议,相较于承载网络,叠加网络由于存在额外的隧道报文封装,会存在一定程度的性能开销,但是可以解决跨路由的问题。
网络插件主流功能:(1)实现Pod间的网络通信,是最为核心的功能
(2)网络策略:允许生成网络策略(NetworkPolicy ),即在节点实现iptables的调度规则
(3)通信加密:通过网络插件使Pod间的通信是tls加密,甚至可以实现0信任网络(即同时启用tls加密和双向证书认证)
目前有多种网络插件可以选择,其中使用较多的主要是Flannel和Calico网络插件 ,具体选择哪种网络插件还需要通过底层系统环境限制 、容器网络的功能需求 和性能需求三个重要的评估标准来衡量插件的适用性
6.2,Flannel简介
Flannel使用"虚拟网桥和veth设备"的方式为Pod创建虚拟网络接口,通过可配置的"后端"定义Pod间的通信网络,支持基于VXLAN和UDP的Overlay网络,以及基于三层路由的Underlay网络。
在IP地址分配方面,它将预留的一个专用网络(默认为10.244.0.0/16)切分成多个子网后作为每个节点的podCIDR,而后由节点以IPAM插件host-local进行地址分配,并将子网分配信息保存于etcd之中。
Flannel在每个主机上运行一个名为flanneld的二进制代理程序,该程序负责从预留的网络中按照指定或默认的掩码长度为当前节点申请分配一个子网(默认切分子网时,子网掩码为24,可以划分256个子网、每个子网可分配254个IP,但是通常节点的Pod数量上限为110,所以可以通过调整子网掩码至26,进一步将子网切分至1024个),并将网络配置、已分配的子网和辅助数据(例如主机的公网IP等)存储于Kubernetes API或etcd之中。
Flannel的后端(backend)选项:
1,host-gw:类似于VXLAN中的直接路由模式,有着较好的转发性能,且易于设定,推荐对报文转发性能要求较高的场景使用,但不支持跨网络的节点,各节点本身必须在同一个二层网络中,不太适用于较大的网络规模 ;
2,vxlan:默认模式,使用Linux内核中的vxlan模块封装隧道报文,以叠加网络模型支持跨节点的Pod间互联互通;
3,vxlan额外支持直接路由(Direct Routing)模式:该模式下位于同二层网络内的节点之上的Pod间通信可通过路由模式直接发送,而跨网络的节点之上的Pod间通信使用VXLAN隧道协议转发 ,flanneld监听于8472/UDP发送封装的数据包;
4,UDP:使用常规UDP报文封装完成隧道转发,性能较以上方式低很多,它只适用于不支持以上后端的环境中使用,flanneld监听于8285/UDP发送封装的报文。
#修改Flannel的模式至vxlan支持直接路由模式,提高转发性能root@k8s-master01:~# kubectl get configmap kube-flannel-cfg -n kube-flannel -o yaml > ./test/kube-flannel-cfg.yaml #查看flannel配置,导出后再修改
root@k8s-master01:~#vim ./test/kube-flannel-cfg.yaml #修改backend配置
.....
net-conf.json: |
{
"Network": "10.244.0.0/16",
"EnableNFTables": false,
"Backend": {
"Type": "vxlan",
"Directrouting": true
.....
root@k8s-master01:~# kubectl apply -f ./test/kube-flannel-cfg.yaml #更新Flannel配置
root@k8s-master01:~# kubectl get daemonsets -n kube-flannel #查看daemonsets名称
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
kube-flannel-ds 6 6 6 6 6 <none> 20d
root@k8s-master01:~# kubectl rollout restart daemonsets kube-flannel-ds -n kube-flannel #滚动重启daemonsets更新所有Flannel
6.3,Calico简介
ProjectCalico是一个三层的虚拟网络方案,它把每个节点都当作虚拟路由器(vRouter),把每个节点上的Pod都当作是"节点路由器"后的一个终端设备并为其分配一个IP地址;各节点路由器通过BGP(Border Gateway Protocol)协议学习生成路由规则从而实现不同节点上Pod间的互联互通。
Calico组件:
Felix:Calico Agent,运行于每个节点,主要负责维护虚拟接口设备和路由信息
Orchestrator Plugin:编排系统(例如Kubernetes、OpenStack等)用于将Calico整合进行系统中的插件,例如Kubernetes的CNI
etcd:持久存储Calico数据的存储管理系统
BIRD:负责分发路由信息的BGP客户端
BGP Route Reflector:BGP路由反射器,可选组件,用于较大规模的网络场景
Calico的BGP路由模型要求所有节点必须要位于同一个二层网络,并非所有网络都能支持该协议,所以Calico支持混合使用路由和叠加网络模型,常见模式如下:Always模式:默认模式,使用叠加网络模型,如IPIP
Never模式: 使用BGP路由
Cross-Subnet:混合叠加网络模型和BGP
与Flannel不同的是,Calico需要专用的独立etcd集群来保存网络配置,若集群较小也可以使用API Server。Calico在配置网络时使用其专有的配置工具calicoctl,在使用API Server保存网络配置时,需要在kubeconfig文件内定义对kubectl工具的调用。
Calico安装可以参考官方文档(需注意Kubetnetes部署后更换网络插件会产生各类报错,建议重新添加新节点并在新节点安装插件,然后依次替换掉所有旧节点),链接如下:
Install Calico networking and network policy for on-premises deployments | Calico Documentationhttps://docs.tigera.io/calico/latest/getting-started/kubernetes/self-managed-onprem/onpremises 进入官网链接后根据实际情况选择对应版本进行安装
七、Helm程序包管理器
Helm是一款简化安装和管理Kubernetes应用程序的工具,通过Chart格式的程序包进行应用程序的管理。Chart中的资源配置文件通常以模板(go template)形式定义,在部署时,用户可通过向模板参数赋值实现定制化安装的目的,各模板参数通常也有默认值,这些默认值定义在Chart包里一个名为values.yml的文件中
类似于kubectl,Helm也是Kubernetes API Server的命令行客户端工具,支持kubeconfig认证文件,需要事先从仓库或本地加载到要使用目标Chart,并基于Chart完成应用管理。Chart可缓存于Helm本地主机上。
Helm常见命令:
Repostory管理--
repo命令,支持repository的add、list、remove、update和index等子命令
Chart管理--
create、 package、pull、 push、dependency、search、show和verify等操作
Release管理--
install、upgrade、get、list、history、status、rollback和uninstall等操作
Helm常用链接:官方文档--Helm | Docs
下载链接--Releases · helm/helm
Chart仓库--Artifact Hub
Helm v3.16.0下载安装root@k8s-master01:~# curl -OL https://get.helm.sh/helm-v3.16.0-linux-amd64.tar.gz #下载官网二进制包
root@k8s-master01:~# tar xf helm-v3.16.0-linux-amd64.tar.gz
root@k8s-master01:~# mv linux-amd64/helm /usr/local/bin #将二进制文件放在PATH下
root@k8s-master01:~# helm --help