k8s-学习总结(控制器:RS\Deploy\DS\Job\CJ)

本文详细介绍了Kubernetes中的关键控制器,包括Replica Set(RS)、Deployment、DaemonSet(DS)、Job和CronJob。通过实例展示了它们的spec字段参数、实践操作以及各自的作用,如RS的标签选择、Deployment的滚动更新和回滚、DaemonSet确保每个节点上的服务、Job的批处理任务和CronJob的定时任务管理。

官网

  • API查看:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#-strong-api-overview-strong-(可以查看控制器样例)
  • 控制器概念:https://kubernetes.io/zh/docs/concepts/workloads/controllers/

概念

控制器类型:

  • Replication Controller【RC,复制控制器】:RC是K8s集群中最早的保证Pod高可用的API对象。通过监控运行中的Pod来保证集群中运行指定数目的Pod副本。指定的数目可以是多个也可以是1个;少于指定数目,RC就会启动运行新的Pod副本;多于指定数目,RC就会杀死多余的Pod副本。即使在指定数目为1的情况下,通过RC运行Pod也比直接运行Pod更明智,因为RC也可以发挥它高可用的能力,保证永远有1个Pod在运行。RC是K8s较早期的技术概念,只适用于长期伺服型的业务类型,比如控制小机器人提供高可用的Web服务。

  • Replica Set【RS,副本集】:RS是新一代RC,提供同样的高可用能力,区别主要在于RS后来居上,能支持更多种类的匹配模式。副本集对象一般不单独使用,而是作为Deployment的理想状态参数使用。ReplicaSet 确保任何时间都有指定数量的 Pod 副本在运行。 然而,Deployment 是一个更高级的概念,它管理 ReplicaSet,并向 Pod 提供声明式的更新以及许多其他有用的功能。 因此建议使用 Deployment 而不是直接使用 ReplicaSet,除非需要自定义更新业务流程或根本不需要更新。这实际上意味着,可能永远不需要操作ReplicaSet 对象:而是使用 Deployment,并在 spec 部分定义应用。

  • Deployment【部署】:部署表示用户对K8s集群的一次更新操作。部署是一个比RS应用模式更广的API对象,可以是创建一个新的服务,更新一个新的服务,也可以是滚动升级一个服务。滚动升级一个服务,实际是创建一个新的RS,然后逐渐将新RS中副本数增加到理想状态,将旧RS中的副本数减小到0的复合操作;这样一个复合操作用一个RS是不太好描述的,所以用一个更通用的Deployment来描述。以K8s的发展方向,未来对所有长期伺服型的的业务的管理,都会通过Deployment来管理。

  • DaemonSet【后台支撑服务集】:长期伺服型和批处理型服务的核心在业务应用,可能有些节点运行多个同类业务的Pod,有些节点上又没有这类Pod运行;而后台支撑型服务的核心关注点在K8s集群中的节点(物理机或虚拟机),要保证每个节点上都有一个此类Pod运行。节点可能是所有集群节点也可能是通过nodeSelector选定的一些特定节点。典型的后台支撑型服务包括,存储,日志和监控等在每个节点上支撑K8s集群运行的服务。

  • Job【任务】:Job是K8s用来控制批处理型任务的API对象。批处理业务与长期伺服业务的主要区别是批处理业务的运行有头有尾,而长期伺服业务在用户不停止的情况下永远运行。Job管理的Pod根据用户的设置把任务成功完成就自动退出了。成功完成的标志根据不同的spec.completions策略而不同:单Pod型任务有一个Pod成功就标志完成;定数成功型任务保证有N个任务全部成功;工作队列型任务根据应用确认的全局成功而标志成功。

  • CornJob【定时任务】:Cron Job 创建基于时间调度的 Jobs。一个 CronJob 对象就像 crontab (cron table) 文件中的一行。它用 Cron 格式进行编写,并周期性地在给定的调度时间执行 Job。CronJob 时间都是基于初始 Job 的主控节点的时区定位的。

  • StatefulSet【有状态服务集】:StatefulSet 是用来管理有状态应用的工作负载 API 对象。StatefulSet 用来管理 Deployment 和扩展一组 Pod,并且能为这些 Pod 提供序号和唯一性保证。和 Deployment 相同的是,StatefulSet 管理了基于相同容器定义的一组 Pod。但和 Deployment 不同的是,StatefulSet 为它们的每个 Pod 维护了一个固定的 ID。这些 Pod 是基于相同的声明来创建的,但是不能相互替换:无论怎么调度,每个 Pod 都有一个永久不变的 ID。StatefulSet 和其他控制器使用相同的工作模式。你在 StatefulSet 对象 中定义你期望的状态,然后 StatefulSet 的 控制器 就会通过各种更新来达到那种你想要的状态

Replica Set

spec字段参数

  1. 与其他API资源清单一致,基础格式
apiVersion: 	#api版本
kind:        	#资源类型
metadata:    	#元数据对象
spec:        	#期望的状态(disired state)
status:	  	#当前状态,本字段有kubernetes自身维护,用户不能去定义
  1. 其中spec中的字段
spec:
  minReadySeconds	<integer>		#最小就绪时间;指定新创建的 Pod 在没有任意容器崩溃情况下的最小就绪时间,以便将其视为可用。默认值为 0
  replicas	<integer>				#Pod副本数量
  selector	<Object> -required-		#Pod选择器
    matchLabels	<map[string]string> #配备标签,主要匹配使用的Pod的标签名,通常与模板中的标签进行匹配
  template	<Object>				#Pod模板,其中主要为容器的设置内容
    metadata  <Object>				#模板中的元数据
    spec  <Object>					#模板中的期望状态

RS控制器实践

一个简单的RS实例

[kubeadm@node1 controller]$ vim rs_myapp.yaml 
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: replicaset-example
spec:
  replicas: 3							#副本数 3
  selector:
    matchLabels:
      app: myapp						#选择器指定标签 app:myapp
  template:
    metadata:
      labels:
        app: myapp						#模板设定标签为 app:myapp 匹配选择器
    spec:
      containers:
      - name: myapp
        image: myapp:v1					#使用容器myapp,镜像随意选择,myapp仅方便测试
[kubeadm@node1 controller]$ kubectl create -f rs_myapp.yaml 
replicaset.apps/replicaset-example created
#创建RS实例
[kubeadm@node1 controller]$ kubectl get pod
NAME                       READY   STATUS    RESTARTS   AGE
replicaset-example-8vlt8   1/1     Running   0          77s
replicaset-example-gkxzg   1/1     Running   0          77s
replicaset-example-jbbxp   1/1     Running   0          77s
#创建结果显示

查看容器创建结果

[kubeadm@node1 controller]$ kubectl get pod -o wide
NAME                       READY   STATUS    RESTARTS   AGE     IP            NODE    NOMINATED NODE   READINESS GATES
replicaset-example-8vlt8   1/1     Running   0          2m45s   10.244.1.31   node2   <none>           <none>
replicaset-example-gkxzg   1/1     Running   0          2m45s   10.244.2.36   node3   <none>           <none>
replicaset-example-jbbxp   1/1     Running   0          2m45s   10.244.1.32   node2   <none>           <none>
[kubeadm@node1 controller]$ curl 10.244.1.31
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[kubeadm@node1 controller]$ curl 10.244.2.36
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[kubeadm@node1 controller]$ curl 10.244.1.32
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
#显示均正常

扩展副本

[kubeadm@node1 controller]$ vim rs_myapp.yaml 
……
  replicas: 6							#副本数修改为6
……
[kubeadm@node1 controller]$ kubectl apply -f rs_myapp.yaml 
Warning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl apply
replicaset.apps/replicaset-example configured
[kubeadm@node1 controller]$ kubectl get pod
NAME                       READY   STATUS    RESTARTS   AGE
replicaset-example-8vlt8   1/1     Running   0          12m
replicaset-example-99hnt   1/1     Running   0          17s
replicaset-example-c8q7z   1/1     Running   0          17s
replicaset-example-gkxzg   1/1     Running   0          12m
replicaset-example-jbbxp   1/1     Running   0          12m
replicaset-example-xzzzh   1/1     Running   0          17s
#已创建6个

RS与标签的关系

  1. RS控制器主要通过标签对Pod进行控制
  2. 修改已有pod的标签,便不会配控制器管理
修改已有pod标签,删除所有pod,查看现象
[kubeadm@node1 controller]$ kubectl get pod --show-labels 
NAME                       READY   STATUS    RESTARTS   AGE     LABELS
replicaset-example-8vlt8   1/1     Running   0          17m     app=myapp
replicaset-example-99hnt   1/1     Running   0          5m22s   app=myapp
replicaset-example-c8q7z   1/1     Running   0          5m22s   app=myapp
replicaset-example-gkxzg   1/1     Running   0          17m     app=myapp
replicaset-example-jbbxp   1/1     Running   0          17m     app=myapp
replicaset-example-xzzzh   1/1     Running   0          5m22s   app=myapp
[kubeadm@node1 controller]$ kubectl label pod replicaset-example-8vlt8 app=myapp1 --overwrite 
pod/replicaset-example-8vlt8 
<think> 我们面对的问题是:在Kubernetes集群中,Jenkins服务账户(位于命名空间`kube-devops`,名为`jenkins-admin`)尝试部署应用到命名空间`k8s-cicd-dev`时,出现了RBAC权限不足的错误。具体错误信息是: ``` from server for: "deploy/cicd-demo-dev.yaml": deployments.apps "k8s-cicd-demo" is forbidden: User "system:serviceaccount:kube-devops:jenkins-admin" cannot get resource "deployments" in API group "apps" in the namespace "k8s-cicd-dev": RBAC: clusterrole.rbac.authorization.k8s.io "jenkins-admin" not found ``` 错误的关键点: 1. 错误表明在命名空间`k8s-cicd-dev`中,对资源`deployments`(属于API组`apps`)执行`get`操作被禁止。 2. 错误还提到集群角色`jenkins-admin`未找到。 根据错误信息,我们可以推断: - Jenkins使用的服务账户`jenkins-admin`在命名空间`kube-devops`中。 - 该服务账户需要被授予在目标命名空间`k8s-cicd-dev`中操作部署(deployments)的权限。 解决方案思路: 1. 创建一个合适的角色(Role)或集群角色(ClusterRole),定义我们需要的权限(例如,对`apps` API组中的`deployments`资源的操作权限)。 2. 将这个角色绑定(RoleBinding)或集群角色绑定(ClusterRoleBinding)到服务账户`jenkins-admin`上,并指定目标命名空间(`k8s-cicd-dev`)。 由于错误信息中提到了一个集群角色`jenkins-admin`未被找到,我们可以选择: - 创建一个名为`jenkins-admin`的集群角色(ClusterRole)并绑定它(但注意,集群角色是集群范围的,可能权限过大)。 - 或者,更安全的方式是创建一个角色(Role)在目标命名空间`k8s-cicd-dev`中,然后将其绑定到服务账户`jenkins-admin`(服务账户在另一个命名空间`kube-devops`中,因此我们需要使用RoleBinding,并且指定服务账户的命名空间)。 但是,由于服务账户`jenkins-admin`位于命名空间`kube-devops`,而目标资源在命名空间`k8s-cicd-dev`,所以我们需要使用RoleBinding在目标命名空间`k8s-cicd-dev`中绑定服务账户(需要指定服务账户的命名空间)或者使用ClusterRoleBinding(绑定集群角色到服务账户,这样权限是集群范围的,但通常我们不需要那么大的权限)。 推荐做法(按最小权限原则): 1. 在目标命名空间`k8s-cicd-dev`中创建一个角色(Role),该角色具有操作部署(deployments)的必要权限(如create, get, update, delete等)。 2. 在目标命名空间`k8s-cicd-dev`中创建一个角色绑定(RoleBinding),将上一步创建的角色绑定到服务账户`jenkins-admin`(来自命名空间`kube-devops`)。 具体步骤: 步骤1:创建角色(Role)在命名空间`k8s-cicd-dev`中,定义对部署(deployments)资源的权限。 ```yaml # jenkins-admin-role.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: k8s-cicd-dev # 目标命名空间 name: jenkins-deploy-role rules: - apiGroups: ["apps"] # API组 resources: ["deployments"] # 资源类型 verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] # 操作权限,根据实际需要调整 ``` 步骤2:创建角色绑定(RoleBinding),将上述角色绑定到服务账户`jenkins-admin`(注意:服务账户在命名空间`kube-devops`中)。 ```yaml # jenkins-admin-rolebinding.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: jenkins-admin-rolebinding namespace: k8s-cicd-dev # 目标命名空间(与Role相同) subjects: - kind: ServiceAccount name: jenkins-admin # 服务账户名称 namespace: kube-devops # 服务账户所在的命名空间 roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: jenkins-deploy-role # 之前创建的Role名称 ``` 步骤3:应用这两个YAML文件。 ``` kubectl apply -f jenkins-admin-role.yaml kubectl apply -f jenkins-admin-rolebinding.yaml ``` 这样,服务账户`jenkins-admin`在命名空间`k8s-cicd-dev`中就有了操作部署的权限。 另外,如果Jenkins需要在多个命名空间中部署应用,那么在每个命名空间中重复上述步骤可能很繁琐。此时,可以考虑使用集群角色(ClusterRole)和集群角色绑定(ClusterRoleBinding)。但是,由于错误信息中提到的集群角色`jenkins-admin`不存在,如果我们想要使用集群角色,可以创建它并绑定到服务账户。 集群角色和集群角色绑定的方式如下: 创建集群角色: ```yaml # jenkins-admin-clusterrole.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: # 因为是集群角色,所以不需要namespace name: jenkins-admin rules: - apiGroups: ["apps"] resources: ["deployments"] verbs: ["*"] # 这里使用*表示所有操作,也可以根据需要指定 ``` 创建集群角色绑定(将集群角色绑定到服务账户,并指定命名空间): ```yaml # jenkins-admin-clusterrolebinding.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: jenkins-admin-clusterrolebinding subjects: - kind: ServiceAccount name: jenkins-admin namespace: kube-devops # 服务账户所在的命名空间 roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: jenkins-admin # 集群角色的名称 ``` 注意:集群角色绑定(ClusterRoleBinding)会将权限授予整个集群,因此服务账户`jenkins-admin`将拥有在所有命名空间中对部署的操作权限。请根据安全策略决定是否使用。 由于最初错误提示是找不到集群角色`jenkins-admin`,可能之前的配置尝试绑定一个集群角色,但是该集群角色不存在。因此,我们可以选择创建这个集群角色并绑定,或者改为使用命名空间级别的角色(如上面第一种方法)。 根据错误上下文,我建议使用第一种方法(命名空间级别的角色),因为更符合最小权限原则。但如果Jenkins确实需要在多个命名空间部署,则使用集群角色更方便。 请根据实际需求选择方案。 最后,在Jenkins中,确保你在使用Kubernetes配置文件或者插件配置时,指定了正确的服务账户(即`jenkins-admin`)和命名空间(`kube-devops`)。 相关问题: 1. 如何检查Kubernetes中的RBAC权限配置是否正确? 2. 在Kubernetes中,如何为服务账户授予多个命名空间的访问权限? 3. 集群角色(ClusterRole)和角色(Role)的主要区别是什么? 4. 如何在Jenkins中配置Kubernetes插件以使用特定的服务账户? </think> ### Kubernetes RBAC权限错误解决方案:Jenkins服务账户权限配置详解 #### 错误诊断与核心问题 在Kubernetes集群中出现的错误: `User "system:serviceaccount:kube-devops:jenkins-admin" cannot get resource "deployments" in API group "apps" in the namespace "k8s-cicd-dev"` 根本原因是: 1. **RBAC权限不足**:Jenkins服务账户`jenkins-admin`缺少操作部署资源的权限 2. **ClusterRole缺失**:系统找不到指定的`jenkins-admin`集群角色 3. **命名空间隔离**:服务账户位于`kube-devops`命名空间,但需要操作`k8s-cicd-dev`命名空间的资源 权限关系公式: $$\text{权限} = \begin{cases} \text{服务账户} & \rightarrow \text{jenkins-admin} \\ \text{目标操作} & \rightarrow \text{deployments} \\ \text{命名空间} & \rightarrow \text{k8s-cicd-dev} \end{cases}$$ #### 完整解决方案(分步骤) ##### 步骤1:创建专用ClusterRole ```yaml # jenkins-clusterrole.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: jenkins-deploy-role # 使用明确的角色名称 rules: - apiGroups: ["apps"] resources: ["deployments", "statefulsets", "daemonsets"] # 扩展部署相关权限 verbs: ["get", "list", "watch", "create", "update", "delete"] - apiGroups: [""] resources: ["pods", "pods/log", "services", "configmaps"] verbs: ["*"] # 开放必要资源权限 ``` ##### 步骤2:创建RoleBinding绑定命名空间 ```yaml # jenkins-rolebinding.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: jenkins-deploy-binding namespace: k8s-cicd-dev # 指定目标命名空间 subjects: - kind: ServiceAccount name: jenkins-admin namespace: kube-devops # 服务账户所在命名空间 roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: jenkins-deploy-role # 匹配ClusterRole名称 ``` ##### 步骤3:应用配置并验证 ```bash # 应用RBAC配置 kubectl apply -f jenkins-clusterrole.yaml kubectl apply -f jenkins-rolebinding.yaml # 验证权限 kubectl auth can-i create deployments \ --as=system:serviceaccount:kube-devops:jenkins-admin \ -n k8s-cicd-dev # 应返回 "yes" ``` #### 关键配置说明 1. **最小权限原则** - 精确限定`apps` API组中的`deployments`资源权限 - 避免使用`ClusterRoleBinding`防止权限过度扩散[^2] 2. **跨命名空间授权** ```mermaid graph LR A[jenkins-admin服务账户] -->|RoleBinding| B(k8s-cicd-dev命名空间) B --> C[deployments资源] ``` 3. **权限验证公式** $$ \text{有效权限} = \frac{\text{ClusterRole权限} \cap \text{RoleBinding范围}}{\text{目标命名空间}} $$ #### Jenkins集成配置 在Jenkins Kubernetes插件配置中: 1. 指定服务账户名称:`jenkins-admin` 2. 设置命名空间:`kube-devops` 3. 添加容器模板时声明命名空间: ```groovy podTemplate( containers: [...], namespace: 'k8s-cicd-dev' // 指定构建目标命名空间 ) ``` #### 相关问题 1. 如何限制Jenkins服务账户只能访问特定命名空间? 2. Kubernetes中ClusterRole和Role的主要区别是什么? 3. 当Jenkins需要部署到多个命名空间时,RBAC应该如何配置? 4. 如何审计Kubernetes中的RBAC权限分配情况? [引用说明] 本文RBAC配置方案参考了Kubernetes官方授权模型[^1],并结合了Jenkins在Kubernetes中的最佳实践[^2][^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值