K8S-Demo集群实践20:容器到底是个什么东东?

本文从通俗的角度解释了容器的概念,将其比喻为软件领域的装货箱,介绍了容器如何隔离应用程序的运行环境。同时,对比了容器与虚拟机的区别,强调容器的敏捷性和高性能。通过近距离观察容器的运行,包括使用docker命令、ps命令、find命令等,揭示了容器的本质是进程,并探讨了容器的重要目录。文章最后提到了容器的单进程模型和容器镜像的版本控制。

一、通俗的容器解释

  • 现实生活中的容器是用来装东西的,方便管理和运输,软件领域借鉴了这个思想
  • 先介绍一个大家熟悉的场景,一台PC上安装了Win10,管理员创建了两个账号,A和B,用户A登录后,看到的是自己的桌面,自己的文件以及自己安装的应用程序Word,B登录后,看到的桌面、文件和应用程序则不同,B安装了WPS而不是Word,这就类似两个Win10容器,它们分别“装”了属于两个用户的办公环境,两个人共享Win10操作系统
  • 下面介绍的容器(Linux Container简称LXC)类似这个办公场景,不同的是LXC“装”的是应用程序所依赖的运行环境,它是一种轻量级的操作系统层虚拟化技术,目的是隔离应用程序的运行环境,从而保证了软件交付过程中开发、测试、生产环境的强一致性
  • 容器技术基于Namespace和Cgroup两大机制来实现,Namespace负责隔离,Cgroup(Linux Control Group)负责限制。
  • 那容器镜像又是什么?你可以认为容器镜像是存储在U盘或光盘上的Win10操作系统
  • 容器是运行态(动态),容器镜像是存储文件(静态),一个容器镜像可以多次运行,从而创建多个容器
  • 容器镜像有版本控制,即tag,类似Win7,Win8,Win10
  • 虽然现在大家习惯了先交付容器镜像,然后再运行它创建容器,但是历史上是先有容器技术,容器镜像得益于dotCloud公司的创新,即大家熟悉的Docker。

二、容器和虚拟机比较

在这里插入图片描述

  • 容器具有敏捷和高性能的优点,在运行Win10的电脑上切换一个账号比启动Win10耗时要少的多
  • 但容器的缺点是隔离不彻底,试想在容器中执行top命令,会看到什么?如果容器A中的应用程序修改了系统时间或者优化了内核参数,那容器B中的应用程序会怎样?如果容器A中的应用程序需要运行在Linux4.x内核上,而容器B中的应用程序兼容Linux内核3.x以下版本,那HostOS又该如何处理?
  • 虚拟机具有完全隔离的优势,拥有独立的操作系统,但是在网络性能等方面又会带来15%左右的损耗。
  • 图1中右半边部分和你在其它地方看到的图略微有一点区别,原因是容器的运行并不依赖DockerEngine,容器是直接运行在HostOS上的
  • DockerEngine提供的是容器操作和管理界面,帮助用户启动和管理容器;容器的本质是进程,只不过DockerEngine在创建容器进程的时候,会添加了一些命名空间(Namespace)参数。

三、近距离观察容器

1、docker

[root@node1 ~]# docker ps
CONTAINER ID   IMAGE     COMMAND     CREATED        STATUS        PORTS     NAMES
75f6881e9487   busybox   "/bin/sh"   1 hours ago   Up 1 hours             busybox-1
99986e1623a3   busybox   "/bin/sh"   1 hours ago   Up 1 hours             busybox-2
[root@node1 ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
busybox      latest    b97242f89c8a   3 weeks ago   1.23MB
  • 上面运行了两个容器,使用的是同一个镜像busybox
  • 上面格式化的信息,是docker命令帮我们整理和翻译的,容器的本质是进程

2、ps

  • 通过容器ID,查找容器进程
[root@node1 ~]# ps -ef | grep 75f6881e9487   
root      11501      1  0 2月03 ?       00:00:04 /usr/bin/containerd-shim-runc-v2 -namespace moby -id 75f6881e94874c19047166f39f5d1920423c17f9c927d0f21f00e0c1569f2396 -address /run/containerd/containerd.sock

3、find

  • 通过容器ID,查找容器关联的目录
<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、付费专栏及课程。

余额充值