写在前面:上篇文章提供了两种简单搭建一个k8s集群的方法,其中两种方式的区别是:kubeadm是直接在主机上进行k8s搭建,kind是在docker中搭建。本文主要分享新建pod等方法。(想了想,对于像我这刚入门的人来说,认识全所有的k8s组件的功能暂时用处也不大,所以还是学习到哪个再查吧,毕竟不总用它真不会用啊!)
补充:各位自行安装docker,k8s中每个pod都是用docker镜像运行的,可以认为就是docker容器。
目录
一.使用kind创建一个具有两个节点(node)的集群
二.组件及名称介绍
三.pod配置文件学习
3.1 yaml文件中必须包含的字段
3.2. 主要参数对象
3.2.1 spec.containers
3.2.2 spec.volumes
3.2.3 额外参数对象
一.使用kind创建一个具有两个节点(node)的集群
问题:①节点干什么用的?②为什么要创建两个?
①: 集群分为一个Master节点和若干Node节点。
Master节点上面主要由四个模块组成:etcd、api server、controller manager、scheduler。
Node上运行着Master分配的pod,当一个Node宕机,其上的pod会被自动转移到其他Node上。每一个Node节点都安装了Node组件,包括kubelet、kube-proxy、container runtime。
②:我们昨天创建的集群就只有一个master节点,如果运行一些镜像,就会出现将系统程序和应用程序搞混了,主要它也不好管理操作,而且出于安全性考虑这样做也不安全。
1.1 使用kind搭建一个具有两个节点的kubernetes集群
首先删除原来建的k8s集群
#如果想要删除某个集群可以使⽤
kind delete cluster --name k8s
新建一个集群配置文件:multi-node-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
运行命令根据配置文件创建集群
kind create cluster --config multi-node-config.yaml \
--image=kindest/node:v1.22.0 --name=k8s
此时我们便可以使用kubectl工具了,查看node
kubectl get nodes -o wide
查看kubenetes自带的一些pod
kubectl get pods --all-namespaces
二.组件及名称介绍
首先我们现在能接触到组件有:pod,deployment,node
相关名词:namespace
pod:可以理解为一个docker容器。(员工)
deployment:让一堆pod(docker)稳定运行的东西。咱们能感受到的直观功能就是,随便添加一个pod进去,它都能安排的明明白白的,让这个pod稳定运行,比如说分配网络啊,分配多大内存啊等等,如果这个pod的程序挂了,它还会自动给你拉起来。(主管)
node:使pod稳定运行和负责通信的。(大区主管)
namespace:主要是为了利用 RBAC(基于角色的访问控制)。(部门)
master:运行着k8s的系统配置。(总经理)
描述一下我所知道的渗透思路:
一般来说是从员工出发,终极目标是成为总经理,就目前的技术而言,主要有三种思路:
1.针对性的社工钓鱼:就是钓有k8smaster权限的主机。(理想情况)
2.利用K8S中的提权漏洞:CVE-2018-1002105。
3.利用配置不当:RBAC权限滥用,污点等。
三.pod配置文件学习
记不住,到时候查,下篇文章做badpods靶场练习
举个例子:everything-allowed-exec-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: everything-allowed-exec-pod
labels:
app: pentest
spec:
hostNetwork: true
hostPID: true
hostIPC: true
containers:
- name: everything-allowed-pod
image: ubuntu
securityContext:
privileged: true
volumeMounts:
- mountPath: /host
name: noderoot
command: [ "/bin/sh", "-c", "--" ]
args: [ "while true; do sleep 30; done;" ]
#nodeName: k8s-control-plane-node # Force your pod to run on the control-plane node by uncommenting this line and changing to a control-plane node name
volumes:
- name: noderoot
hostPath:
path: /
主要关注spec中的参数,这其中的配置是对容器造成影响,配置不当会出现严重的问题。
3.1 yaml文件中必须包含的字段
参数名 | 字段类型 | 说明 |
version | String | 这里是指的是K8S API的版本,目前基本上是v1,可以用kubectl api-versions命令查询 |
kind | String | 这里指的是yaml文件定义的资源类型和角色,比如:Pod |
metadata | Object | 元数据对象,固定值就写metadata |
metadata.name | String | 元数据对象的名字,这里由我们编写,比如命名Pod的名字 |
metadata.namespace | String | 元数据对象的命名空间,由我们自身定义 |
Spec | Object | 详细定义对象,固定值就写Spec |
spec.containers[] | list | 这里是Spec对象的容器列表定义,是个列表 |
spec.containers[].name | String | 这里定义容器的名字 |
spec.containers[].image | String | 这里定义要用到的镜像名称 |
3.2. 主要参数对象
3.2.1 spec.containers
spec.containers:代表的是描述container容器方面的参数。所以它下面的参数是非常多的,具体参数看如下表格:
参数名 | 字段类型 | 说明 |
spec.containers[].name | String | 定义容器的名字 |
spec.containers[].image | String | 定义要用到的镜像名称 |
spec.containers[].imagePullPolicy | String | 定义镜像拉取策略,有Always、Never、IfNotPresent三个值可选(1)Always:意思是每次都尝试重新拉取镜像 (2)Never:表示仅使用本地镜像 (3)IfNotPresent:如果本地有镜像就使用本地镜像,没有就拉取在线镜像。 上面三个值都没设置的话,默认是Always。 |
spec.containers[].command[] | List | 指定容器启动命令,因为是数组可以指定多个,不指定则使用镜像打包时使用的启动命令。 |
spec.containers[].args[] | List | 指定容器启动命令参数,因为是数组可以指定多个。 |
spec.containers[].workingDir | String | 指定容器的工作目录 |
spec.containers[].volumeMounts[] | List | 指定容器内部的存储卷配置 |
spec.containers[].volumeMounts[].name | String | 指定可以被容器挂载的存储卷的名称 |
spec.containers[].volumeMounts[].mountPath | String | 指定可以被容器挂载的存储卷的路径 |
spec.containers[].volumeMounts[].readOnly | String | 设置存储卷路径的读写模式,ture 或者false,默认为读写模式 |
spec.containers[].ports[] | List | 指定容器需要用到的端口列表 |
spec.containers[].ports[].name | String | 指定端口名称 |
spec.containers[].ports[].containerPort | String | 指定容器需要监听的端口号 |
spec.containers[].ports[].hostPort | String | 指定容器所在主机需要监听的端口号,默认跟上面containerPort相同,注意设置了hostPort 同一台主机无法启动该容器的相同副本(因为主机的端口号不能相同,这样会冲突) |
spec.containers[].ports[].protocol | String | 指定端口协议,支持TCP和UDP,默认值为TCP |
spec.containers[].env[] | List | 指定容器运行前需设置的环境变量列表 |
spec.containers[].env[].name | String | 指定环境变量名称 |
spec.containers[].env[].value | String | 指定环境变量值 |
spec.containers[].resources | Object | 指定资源限制和资源请求的值(这里开始就是设置容器的资源上限) |
spec.containers[].resources.limits | Object | 指定设置容器运行时资源的运行上限 |
spec.containers[].resources.limits.cpu | String | 指定CPU的限制,单位为core数,将用于 docker run --cpu-shares参数(这里前面文章Pod资源限制有讲过) |
spec.containers[].resources.limits.memory | String | 指定MEM内存的限制,单位为MIB、GiB |
spec.containers[].resources.requests | Object | 指定容器启动和调度时的限制设置 |
spec.containers[].resources.requests.cpu | String | CPU请求,单位为core数,容器启动时初始化可用数量 |
spec.containers[].resources.requests.memory | String | 内存请求,单位为MIB、GiB,容器启动的初始化可用数量 |
3.2.2 spec.volumes
spec.volumes参数:定义同步存储方面的参数。
参数名 | 字段类型 | 说明 |
spec.volumes[].name | String | 定义Pod的共享存储卷的名称,容器定义部分的spec.containers[].volumeMounts[].name的值跟这里是一样的。 |
spec.volumes[].emptyDir | Object | 指定Pod的临时目录,值为一个空对象:emptyDir:{} |
spec.volumes[].hostPath | Object | 指定挂载Pod所在宿主机的目录 |
spec.volumes[].hostPath.path | String | 指定Pod所在主机的目录,将被用于容器中mount的目录 |
spec.volumes[].secret | Object | 指定类型为secret的存储卷,secret意为私密、秘密的意思,很容易理解,它存储一些密码,token或者秘钥等敏感安全文件。挂载集群预定义的secret对象到容器内部。 |
spec.volumes[].configMap | Object | 指定类型为configMap的存储卷,表示挂载集群预定义的configMap对象到容器内部。 |
spec.volumes[].livenessProbe | Object | 指定Pod内容器健康检查的设置,当探测无响应几次后,系统将自动重启该容器。这个在前面的文章中有说,具体可以设置:exec、httpGet、tcpSocket。 |
spec.volumes[].livenessProbe.exec | Object | 指定Pod内容器健康检查的设置,确定是exec方式 |
spec.volumes[].livenessProbe.exec.command[] | String | 指定exec方式后需要指定命令或者脚本,用这个参数设置 |
spec.volumes[].livenessProbe.httpGet | Object | 指定Pod内容器健康检查的设置,确定是httpGet方式 |
spec.volumes[].livenessProbe.tcpSocket | Object | 指定Pod内容器健康检查的设置,确定是tcpSocket方式 |
spec.volumes[].livenessProbe.initialDelaySeconds | Number | 容器启动完成后手册探测的时间设置,单位为s |
spec.volumes[].livenessProbe.timeoutSeconds | Number | 对容器健康检查的探测等待响应的超时时间设置,单位为S,默认为1s。若超过该超时时间设置,则认为该容器不健康,会重启该容器。 |
spec.volumes[].livenessProbe.periodSeconds | Number | 对容器健康检查的定期探测时间设置,单位为S,默认10s探测一次。 |
3.2.3 额外参数对象
参数名 | 字段类型 | 说明 |
spec.restartPolicy | String | 定义Pod的重启策略,可选值为Always、OnFailure,默认值为Always。 1.Always:Pod一旦终止运行,则无论容器是如何终止的,kubelet服务都将重启它。 2.OnFailure:只有Pod以非零退出码终止时,kubelet才会重启该容器。如果容器正常结束(退出码为0),则kubelet将不会重启它。 3. Never:Pod终止后,kubelet将退出码报告给Master,不会重启该Pod。 |
spec.nodeSelector | Object | 定义Node的Label过滤标签,以key:value格式指定 |
spec.imagePullSecrets | Object | 定义pull镜像时使用secret名称,以name:secretkey格式指定 |
spec.hostNetwork | Boolean | 定义是否使用主机网络模式,默认值为false。设置true表示使用宿主机网络,不使用docker网桥,同时设置了true将无法在同一台宿主机上启动第二个副本。 |
参考:Kubernetes系列学习文章 - Pod YAML文件如何写(五) - 腾讯云开发者社区-腾讯云
总结:本文对Pod配置进行了基本讲解。
如果不是运维人员其实不需要所有Pod参数进行了解,搞安全的话只需要了解一些关键的配置参数以便利用即可,比如说设置特权容器,挂载主机根目录,控制到挂载到某节点等等,在下篇文章的BadPods练习中慢慢学习,主要就是收集危险配置,如果我们有拿到具有create pod权限的账号,那么我们就可以利用危险配置拿下master节点。