深入理解Pod对象

深入理解Pod对象

POD的基本概念

什么是POD

  • Pod是Kubernetes中最小的单元,它由一组、一个或多个容器组成

  • 每个Pod还包含了一个Pause容器,Pause容器是Pod的父容器,主要负责僵尸进程的回收管理

  • 通过Pause容器可以使同一个Pod里面的多个容器共享存储、网络、PID、IPC等。

  • Pod支持横向扩展和复制

  • Pod的生命周期是短暂的, 用后即焚的实体

    • 注意: 重启Pod中的容器和重启Pod不是一回事
    • Pod只提供容器的运行环境并保持容器的运行状态, 重启容器不会造成Pod重启
  • Pod不会自愈, 如果Pod运行的Node故障, 或者是调度器本身故障, 这个Pod就会被删除

  • 控制器(Deployment)可以自动创建和管理多个Pod, 提供副本管理, 滚动升级和集群级别的自愈能力

Pod实现机制与设计模式

Pod本身是一个逻辑概念,没有具体存在,那究竟是怎么实现的呢?

众所周知,容器之间是通过Namespace隔离的,Pod要想解决上述应用场景,那么就要让Pod里的容器之间高效共享。

具体分为两个部分:网络和存储

  • 共享网络

kubernetes的解法是这样的:会在每个Pod里先启动一个infra container小容器,然后让其他的容器连接进来这个网络命名空间,然后其他容器看到的网络试图就完全一样了,即网络设备、IP地址、Mac地址等,这就是解决网络共享问题。在Pod的IP地址就是infra container的IP地址。

  • 共享存储

比如有两个容器,一个是nginx,另一个是普通的容器,普通容器要想访问nginx里的文件,就需要nginx容器将共享目录通过volume挂载出来,然后让普通容器挂载的这个volume,最后大家看到这个共享目录的内容一样。

例如:

# pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: write
    image: centos
    command: ["bash","-c","for i in {1..100};do echo $i >> /data/hello;sleep 1;done"]
    volumeMounts:
      - name: data
        mountPath: /data

  - name: read
    image: centos
    command: ["bash","-c","tail -f /data/hello"]
    volumeMounts:
      - name: data
        mountPath: /data
  
  volumes:
  - name: data
    emptyDir: {}

上述示例中有两个容器,write容器负责提供数据,read消费数据,通过数据卷将写入数据的目录和读取数据的目录都放到了该卷中,这样每个容器都能看到该目录。

验证:

kubectl apply -f pod.yaml
kubectl logs my-pod -c read -f

在Pod中容器分为以下几个类型:

  • Infrastructure Container:基础容器,维护整个Pod网络空间,对用户不可见
  • InitContainers:初始化容器,先于业务容器开始执行,一般用于业务容器的初始化工作
  • Containers:业务容器,具体跑应用程序的镜像

Pod的生命周期

  • Pod对象自从其创建开始至终止退出的时间范围称为其生命周期

  • 在这段时间中, Pod会处于多种不同的状态, 并执行一些操作

  • 创建主容器(main container) 为必须的操作

  • 其他可选的操作还包括

    • 初始化容器init container
    • 容器启动后钩子post start hook
    • 启动状态检测StartupProbe:便于用户使用同livenessProbe不同参数或阈值;
    • 容器的存活性探测liveness probe:周期性检测,检测未通过时,kubelet会根据restartPolicy的定义来决定是否会重启该容器;未定义时,Kubelet认为只容器未终止,即为健康;
    • 容器就绪性探测readiness probe:周期性检测,检测未通过时,与该Pod关联的Service,会将该Pod从Service的后端可用端点列表中删除;直接再次就绪,重新添加回来。未定义时,只要容器未终止,即为就绪;
    • 容器终止前钩子pre stop hook
  • 上述操作是否执行取决于Pod的定义

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Oix5OSve-1628834816607)(C:\Users\admin\Desktop\截图\k8s\Pod生命周期示意图.png)]

pod的探针:

  • StartupProbe:k8s1.16版本后新加的探测方式,用于判断容器内应用程序是否已经启动。如果配置了startupProbe,就会先禁止其他的探测,直到它成功为止,成功后将不在进行探测。

  • LivenessProbe:周期性检测,检测未通过时,与该Pod关联的Service,会将该Pod从Service的后端可用端点列表中删除;直接再次就绪,重新添加回来。未定义时,只要容器未终止,即为就绪;

  • ReadinessProbe:周期性检测,一般用于探测容器内的程序是否健康,它的返回值如果为success,那么就代表这个容器已经完成启动,并且程序已经是可以接受流量的状态。

镜像拉取策略

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
    - name: java
      image: lizhenliang/java-demo
      imagePullPolicy: IfNotPresent

imagePullPolicy 字段有三个可选值:

  • IfNotPresent:默认值,镜像在宿主机上不存在时才拉取(镜像标签是指定版本时的默认选项)

  • Always:每次创建 Pod 都会重新拉取一次镜像(镜像标签是latest的默认选项)

  • Never: Pod 永远不会主动拉取这个镜像

如果拉取公开的镜像,直接按照上述示例即可,但要拉取私有的镜像,是必须认证镜像仓库才可以,即docker login,而在K8S集群中会有多个Node,显然这种方式是很不放方便的!为了解决这个问题,K8s 实现了自动拉取镜像的功能。 以secret方式保存到K8S中,然后传给kubelet。

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  imagePullSecrets:
    - name: myregistrykey
  containers:
    - name: java
      image: lizhenliang/java-demo
      imagePullPolicy: IfNotPresent

上述中名为 myregistrykey 的secret是由kubectl create secret docker-registry命令创建:

 kubectl create secret docker-registry myregistrykey --docker-username=admin --docker-password=Harbor12345 [email protected] --docker-server=192.168.31.70
  • docker-server: 指定docke仓库地址
  • docker-username: 指定docker仓库账号
  • docker-password: 指定docker仓库密码
  • docker-email: 指定邮件地址(选填)

POD的YAML清单

YAML内容解析

在K8S部署一个应用的YAML内容大致分为两部分:

深入理解Pod对象_第1张图片

控制器定义:定义控制器属性

被控制对象:Pod模板,定义容器属性

具体字段意义:

apiVersion API版本
kind 资源类型
metadata 资源元数据
spec 资源规格
replicas 副本数量
selector 标签选择器
template Pod模板
metadata Pod元数据
spec Pod规格
containers 容器配置

资源字段太多,记不住怎么办?

很多同学YAML不会写!主要原因还是用的少,里面都是由于各个资源组成,熟悉了每个资源应用,自然就会写了,但也不用等到熟悉各种资源,这里教你几个技巧,帮助快速上手。

  • 用run命令生成部署模板

    kubectl create deployment nginx --image=nginx:1.14 -o yaml --dry-run> my-deploy.yaml

  • 用get命令将已有部署的应用yaml导出

    kubectl get my-deploy/nginx -o=yaml --export > my-deploy.yaml

  • 如果某个字段单词不记得了,可以通过explain查看更详细的帮助文档获得

    kubectl explain pods.spec.containers

定义一个pod

apiVersion: v1 # 必选,API的版本号
kind: Pod       # 必选,类型Pod
metadata:       # 必选,元数据
  name: nginx   # 必选,符合RFC 1035规范的Pod名称
  namespace: default # 可选,Pod所在的命名空间,不指定默认为default,可以使用-n指定namespace 
  labels:       # 可选,标签选择器,一般用于过滤和区分Pod
    app: nginx
    role: frontend # 可以写多个
  annotations:  # 可选,注释列表,可以写多个
    app: nginx
spec:   # 必选,用于定义容器的详细信息
  initContainers: # 初始化容器,在容器启动之前执行的一些初始化操作
  - command:
    - sh
    - -c
    - echo "I am InitContainer for init some configuration"
    image: busybox
    imagePullPolicy: IfNotPresent
    name: init-container
  containers:   # 必选,容器列表
  - name: nginx # 必选,符合RFC 1035规范的容器名称
    image: nginx:latest    # 必选,容器所用的镜像的地址
    imagePullPolicy: Always     # 可选,镜像拉取策略
    command: # 可选,容器启动执行的命令
    - nginx 
    - -g
    - "daemon off;"
    workingDir: /usr/share/nginx/html       # 可选,容器的工作目录
    volumeMounts:   # 可选,存储卷配置,可以配置多个
    - name: webroot # 存储卷名称
      mountPath: /usr/share/nginx/html # 挂载目录
      readOnly: true        # 只读
    ports:  # 可选,容器需要暴露的端口号列表
    - name: http    # 端口名称
      containerPort: 80     # 端口号
      protocol: TCP # 端口协议,默认TCP
    env:    # 可选,环境变量配置列表
    - name: TZ      # 变量名
      value: Asia/Shanghai # 变量的值
    - name: LANG
      value: en_US.utf8
    resources:      # 可选,资源限制和资源请求限制
      limits:       # 最大限制设置
        cpu: 1000m	#1核=1000m
        memory: 1024Mi
      requests:     # 启动所需的资源
        cpu: 100m
        memory: 512Mi
    startupProbe: # 可选,检测容器内进程是否完成启动。注意三种检查方式同时只能使用一种。
      httpGet:      # httpGet检测方式,生产环境建议使用httpGet实现接口级健康检查,健康检查由应用程序提供。
            path: /api/successStart # 检查路径
            port: 80
    readinessProbe: # 可选,健康检查。注意三种检查方式同时只能使用一种。
      httpGet:      # httpGet检测方式,生产环境建议使用httpGet实现接口级健康检查,健康检查由应用程序提供。
            path: / # 检查路径
            port: 80        # 监控端口
    livenessProbe:  # 可选,健康检查
      exec:        # 执行容器命令检测方式
            #command: 
            #- cat
            #- /health
    httpGet:       # httpGet检测方式
       path: /_health # 检查路径
       port: 8080
       httpHeaders: # 检查的请求头
       - name: end-user
         value: Jason 
      tcpSocket:    # 端口检测方式
            port: 80
      initialDelaySeconds: 60       # 初始化时间
      timeoutSeconds: 2     # 超时时间
      periodSeconds: 5      # 检测间隔
      successThreshold: 1 	# 检查成功为2次表示就绪
      failureThreshold: 2 	# 检测失败1次表示未就绪
    lifecycle:
      postStart: # 容器创建完成后执行的指令, 可以是exec httpGet TCPSocket
        exec:
          command:
          - sh
          - -c
          - 'mkdir /data/ '
      preStop:
        httpGet:      
              path: /
              port: 80
        exec:
          command:
          - sh
          - -c
          - sleep 9
  restartPolicy: Always   # 可选,默认为Always,容器故障或者没有启动成功,那就自动重启该容器,Onfailure: 容器以不为0的状态终止,自动重启该容器, Never:无论何种状态,都不会重启
  nodeSelector: # 可选,指定Node节点
        region: subnet7
  imagePullSecrets:     # 可选,拉取镜像使用的secret,可以配置多个
  - name: default-dockercfg-86258
  hostNetwork: false    # 可选,是否为主机模式,如是,会占用主机端口
  volumes:      # 共享存储卷列表
  - name: webroot # 名称,与上述对应
    emptyDir: {}    # 挂载目录
        hostPath:              # 挂载本机目录
          path: /etc/hosts

Pod的生命周期

  • Pod对象自从其创建开始至终止退出的时间范围称为其生命周期

  • 在这段时间中, Pod会处于多种不同的状态, 并执行一些操作

  • 创建主容器(main container) 为必须的操作

  • 其他可选的操作还包括

    • 初始化容器init container
    • 容器启动后钩子post start hook
    • 启动状态检测StartupProbe
    • 容器的存活性探测liveness probe
    • 容器就绪性探测readiness probe
    • 容器终止前钩子pre stop hook:
  • 上述操作是否执行取决于Pod的定义

在Pod中容器分为以下几个类型:

  • Infrastructure Container:基础容器,维护整个Pod网络空间,对用户不可见

  • InitContainers:初始化容器,先于业务容器开始执行,一般用于业务容器的初始化工作

  • Containers:业务容器,具体跑应用程序的镜像

深入理解Pod对象_第2张图片

初始化容器init container

  • 先于主容器启动,有些比较重要的初始化操作,需要在主容器启动前启动。
  • 一般情况下,在一个pod内,使用init container来进行特权操作,因为init container执行完就终止。
  • init container执行完对整个容器内的网络名称空间已经生效,然后init container退出,再运行主容器
  • 主容器内核继承了init container的执行结果,但主容器不具有特权

init-container

apiVersion: v1
kind: Pod
metadata:
  name: init-container-demo
  namespace: default
spec:
  initContainers:
  - name: iptables-init
    image: ikubernetes/admin-box:latest
    imagePullPolicy: IfNotPresent
    command: ['/bin/sh','-c']
    args: ['iptables -t nat -A PREROUTING -p tcp --dport 8080 -j REDIRECT --to-port 80']
    securityContext:
      capabilities:
        add:
        - NET_ADMIN
  containers:
  - name: demo
    image: ikubernetes/demoapp:v1.0
    imagePullPolicy: IfNotPresent
    ports:
    - name: http
      containerPort: 80

post start hook和pre stop hook的作用

  • post start hook:容器创建完成后立即运行的钩子处理器,主要为容器启动后做一些简单初始化操作,只有启动成功了pod才能正常工作,处于running状态
  • pre stop hook:主进程结束前做一些清理操作,清理完成后pod才会成功终止

lifecycle-demo

apiVersion: v1
kind: Pod
metadata:
  name: lifecycle-demo
  namespace: default
spec:
  containers:
  - name: demo
    image: ikubernetes/demoapp:v1.0
    imagePullPolicy: IfNotPresent
    securityContext:
      capabilities:
        add:
        - NET_ADMIN
    livenessProbe:
      httpGet:
        path: '/livez'
        port: 80
        scheme: HTTP
      initialDelaySeconds: 5
    lifecycle:
      postStart:
        exec:
          command: ['/bin/sh','-c','iptables -t nat -A PREROUTING -p tcp --dport 8080 -j REDIRECT --to-ports 80']
      preStop:
        exec:
          command: ['/bin/sh','-c','while killall python3; do sleep 1; done']
  restartPolicy: Always

也支持三种探针

pod的三种探针:

spec:
  containers:
  - name: …
    image: …
    livenessProbe:
      exec        # 命令式探针
      httpGet     # http GET类型的探针
      tcpSocket   # tcp Socket类型的探针
      initialDelaySeconds     # 发起初次探测请求的延后时长
      periodSeconds           # 请求周期
      timeoutSeconds          # 超时时长
      successThreshold        # 成功阈值
      failureThreshold        # 失败阈值
 
  

PS:在一个pod中exec、httpGet、tcpSocket三种探针使用一种即可

  • StartupProbe:k8s1.16版本后新加的探测方式,用于判断容器内应用程序是否已经启动。如果配置了startupProbe,就会先禁止其他的探测,直到它成功为止,成功后将不在进行探测。便于用户使用同livenessProbe不同参数或阈值;

  • LivenessProbe:周期性检测,检测未通过时,kubelet会根据restartPolicy的定义来决定是否会重启该容器;未定义时,Kubelet认为只要容器未终止,即为健康;

  • ReadinessProbe:周期性检测,检测未通过时,与该Pod关联的Service,会将该Pod从Service的后端可用端点列表中删除;直接再次就绪,重新添加回来。未定义时,只要容器未终止,即为就绪;

    • 0/1:前面数字表示就绪状态,0表示service不会把流量调度给这个容器,后面1表示这个pod内一共有几个容器

Pod探针的检测方式

  • ExecAction:在容器内执行一个命令,如果返回值为0,则认为容器健康。

  • TCPSocketAction:通过TCP连接检查容器内的端口是否是正常打开,如果正常打开的就认为容器健康。

  • HTTPGetAction:向应用程序暴露的API地址发HTTP请求来检测程序是否正常,如果状态码为2xx,3xx则认为容器健康。

探针检查参数配置

  • initialDelaySeconds: 60 # 初次探测延后的时间
  • periodSeconds: 5 # 检测间隔
  • timeoutSeconds: 2 # 超时时间,不要超过检测间隔
  • successThreshold: 1 # 检查成功为1次表示就绪
  • failureThreshold: 2 # 检测失败2次表示未就绪

例如:

liveness-exec

apiVersion: v1
kind: Pod
metadata:
  name: liveness-exec-demo
  namespace: default
spec:
  containers:
  - name: demo
    image: ikubernetes/demoapp:v1.0
    imagePullPolicy: IfNotPresent
    livenessProbe:
      exec:
        command: ['/bin/sh', '-c', '[ "$(curl -s 127.0.0.1/livez)" == "OK" ]']
      initialDelaySeconds: 5
      timeoutSeconds: 1
      periodSeconds: 5

[ “$(curl -s 127.0.0.1/livez)” == “OK” ]:shell判断语句,等值判断,curl -s 127.0.0.1/livez成功则显示OK

liveness-httpget

apiVersion: v1
kind: Pod
metadata:
  name: liveness-httpget-demo
  namespace: default
spec:
  containers:
  - name: demo
    image: ikubernetes/demoapp:v1.0
    imagePullPolicy: IfNotPresent
    livenessProbe:
      httpGet:
        path: '/livez'
        port: 80
        scheme: HTTP
      initialDelaySeconds: 5

scheme: HTTP意思是使用HTTP协议

只以响应码作为容器是否健康的标准,返回的响应码为2xx,3xx为健康

liveness-tcpsocket

apiVersion: v1
kind: Pod
metadata:
  name: liveness-tcpsocket-demo
  namespace: default
spec:
  containers:
  - name: demo
    image: ikubernetes/demoapp:v1.0
    imagePullPolicy: IfNotPresent
    ports:
    - name: http
      containerPort: 80   
    livenessProbe:
      tcpSocket:
        port: http
      periodSeconds: 5
      initialDelaySeconds: 5

port: http是引用上面ports.name: http,类似于变量的用法

readiness-httpget

apiVersion: v1
kind: Pod
metadata:
  name: readiness-httpget-demo
  namespace: default
spec:
  containers:
  - name: demo
    image: ikubernetes/demoapp:v1.0
    imagePullPolicy: IfNotPresent
    readinessProbe:
      httpGet:
        path: '/readyz'
        port: 80
        scheme: HTTP
      initialDelaySeconds: 15
      timeoutSeconds: 2
      periodSeconds: 5
      failureThreshold: 3
  restartPolicy: Always

startup-exec

apiVersion: v1
kind: Pod
metadata:
  name: startup-exec-demo
  namespace: default
spec:
  containers:
  - name: demo
    image: ikubernetes/demoapp:v1.0
    imagePullPolicy: IfNotPresent
    startupProbe:
      exec:
        command: ['/bin/sh','-c','test','"$(curl -s 127.0.0.1/livez)"=="OK"']
      initialDelaySeconds: 0
      failureThreshold: 3
      periodSeconds: 5

startup检测成功后,LivenessProbe和ReadinessProbe探针才会启动

Pod的多容器

  • sidecar:为主容器提供辅助作用,为了外部环境更好接入主容器,如日志收集,代理服务等

  • adapater:为主容器的某个功能,能更好的适应外部环境

  • ambassador:为了让主容器接入外部环境,如代表主容器访问数据

sidecar-container

apiVersion: v1
kind: Pod
metadata:
  name: sidecar-container-demo
  namespace: default
spec:
  containers:
  - name: proxy
    image: envoyproxy/envoy-alpine:v1.14.1
    command: ['/bin/sh','-c']
    args: ['sleep 5 && envoy -c /etc/envoy/envoy.yaml']
    lifecycle:
      postStart:
        exec:
          command: ['/bin/sh','-c','wget -O /etc/envoy/envoy.yaml http://ilinux.io/envoy.yaml']
  - name: demo
    image: ikubernetes/demoapp:v1.0
    imagePullPolicy: IfNotPresent
    env:
    - name: HOST
      value: "127.0.0.1"
    - name: PORT
      value: "8080"

POD的资源限制

Pod计算资源配额有两种

  • request:下阈值;限制配额:容器能使用的最大配置

    spec.containers[].resources.limits.cpu

    spec.containers[].resources.limits.memory

  • Limit:上阈值; 申请配额:调度时使用,参考是否有节点满足该配置

    spec.containers[].resources.requests.cpu

    spec.containers[].resources.requests.memory

计算资源的单位:

  • CPU:1核=1000m
  • Memory:Ki、Mi

resource-requests

apiVersion: v1
kind: Pod
metadata:
  name: stress-pod
spec:
  containers:
  - name: stress
    image: ikubernetes/stress-ng
    command: ["/usr/bin/stress-ng", "-c 1", "-m 1", "--metrics-brief"]
    resources:
      requests:
        memory: "128Mi"
        cpu: "200m"
      limits:
        memory: "512Mi"
        cpu: "400m"

/usr/bin/stress-ng专门做压力测试的应用程序

resource-limites

apiVersion: v1
kind: Pod
metadata:
  name: memleak-pod
  labels:
    app: memleak
spec:
  containers:
  - name: simmemleak
    image: ikubernetes/simmemleak
    imagePullPolicy: IfNotPresent
    resources:
      requests:
        memory: "64Mi"
        cpu: "1"
      limits:
        memory: "64Mi"
        cpu: "1"

设定requests和limits值相同是强行限制pod的计算资源。

强行限制的pod的计算资源后,如果pod内存不够,启动失败会显示OOMKilled

k8s的退避算法:第一次失败1秒后重启,第二次失败10秒后重启,之后重启时间翻倍,到第7次重启300秒还是失败后,显示CrashLoopBackOff

POD服务质量类别

基本概念

pod过载使用资源的情况下,无法同时满足绑定其上的所有对象以资源满载的方式运行,在内存资源紧缺的情况下。Kubernetes根据Pod中Containers Resource的request和limit的值,把Pod对象归类为Guaranteed、 Burstable、和Best-Effort这3个服务质量类别(QoS )。

  • Guaranteed:Pod内的每个容器都分别设定了CPU和Memroy的资源需求和资源限制,CPU的需求与限制相等,而且Memory的需求与限制也相等。这类Pod对象具有最高级别服务质量
  • Burstable:至少一个容器设置了CPU或Memory的资源需求或资源限制,这类Pod对象具有中等级别服务质量
  • BestEffort:Pod中所有容器的所有Resource的request和limit都没有赋值,这类Pod对象具有最低级别服务质量

如何根据不同的QoS回收Resources

  • CPU 当CPU使用不能达到request值,比如系统任务和daemons使用了大量CPU,则Pods不会被kill,CPU效率会下降(throttled)。
  • Memory 内存是不可压缩资源,从内存管理的角度做如下区分:
    • Best-Effort pods 优先级最低。如果系统内存耗尽,该类型的pods中的进程最先被kill。这些容器可以使用系统上任意量的空闲内存。
    • Guaranteed pods 优先级最高。它们能够确保不达到容器设置的limit上限一定不会被kill。只有在系统存在内存压力且没有更低优先级容器时才被驱逐。
    • Burstable pods 有一些形式的最小资源保证,但当需要时可以使用更多资源。在系统存在内存瓶颈时,一旦内存超过他们的request值并且没有Best-Effort 类型的容器存在,这些容器就先被kill掉。

POD的安全上下文:securityContext

apiVersion: v1	#查看版本:kubectl api-version
kind: Pod
metadata: {…}
spec:
  securityContext: # Pod级别的安全上下文,对内部所有容器均有效
    runAsUser  # 以指定的用户身份运行容器进程,默认由镜像中的USER指定
    runAsGroup  # 以指定的用户组运行容器进程,默认使用的组随容器运行时
    supplementalGroups  <[]integer>  # 为容器中1号进程的用户添加的附加组;
    fsGroup  # 为容器中的1号进程附加的一个专用组,其功能类似于sgid
    runAsNonRoot  # 是否以非root身份运行
    seLinuxOptions  # SELinux的相关配置
    sysctls  <[]Object>  # 应用到当前Pod上的网络名称空间级别的sysctl参数设置列表
    windowsOptions  # Windows容器专用的设置
  containers:	#容器级别的安全上下文
  - name: …
    image: …
    securityContext:       # 容器级别的安全上下文,仅生效于当前容器
      runAsUser    # 以指定的用户身份运行容器进程
      runAsGroup    # 以指定的用户组运行容器进程
      runAsNonRoot   # 是否以非root身份运行
      allowPrivilegeEscalation  # 是否允许特权升级
      capabilities   # 于当前容器上添加(add)或删除(drop)的内核能力
        add  <[]string>  # 添加由列表定义的各内核能力
        drop  <[]string>  # 移除由列表定义的各内核能力
      privileged   # 是否运行为特权容器,若设定为true,就等于是宿主机上的用户,若以管理员身份运行,可直接操作宿主机的内核,不建议使用
      procMount    # 设置容器的procMount类型,默认为DefaultProcMount;
      readOnlyRootFilesystem  # 是否将根文件系统设置为只读模式
      seLinuxOptions   # SELinux的相关配置
      windowsOptions   # windows容器专用的设置
 
  

指定运行容器的用户和组:securitycontext-runasuser-demo

apiVersion: v1
kind: Pod
metadata:
  name: securitycontext-runasuser-demo
  namespace: default
spec:
  containers:
  - name: demo
    image: ikubernetes/demoapp:v1.0
    imagePullPolicy: IfNotPresent
    env:
    - name: PORT
      value: "8080"
    securityContext:
      runAsUser: 1001
      runAsGroup: 1001

PS:普通用户(1001)没有权限监听1024以内的特权端口,所以加了env,把端口改成8080

添加禁止容器的内核功能:securitycontext-capabilities-demo

apiVersion: v1
kind: Pod
metadata:
  name: securitycontext-capabilities-demo
  namespace: default
spec:
  containers:
  - name: demo
    image: ikubernetes/demoapp:v1.0
    imagePullPolicy: IfNotPresent
    command: ["/bin/sh","-c"] #改变镜像启动为容器时,镜像内设置默认要启动的命令,自定义运行的程序
    args: ["/sbin/iptables -t nat -A PREROUTING -p tcp --dport 8080 -j REDIRECT --to-port 80 && /usr/bin/python3 /usr/local/bin/demo.py"] #向自定义command命令传递的参数  
    securityContext:
      capabilities:
        add: ['NET_ADMIN']
        drop: ['CHOWN']

常用的capabilities:

  • CAP_CHOWN:改变文件的UID和GID的能力;
  • CAP_MKNOD:mknod(),能使用这个系统调用创建设备文件;
  • CAP_NET_ADMIN:(最常用)网络管理权限;
  • CAP_SYS_ADMIN:大部分的管理权限(若需要pod具有一些管理权限,建议add这个选项,不建议使用特权容器privileged: true);
  • CAP_SYS_TIME:设定系统时钟和硬件时钟;
  • CAP_SYS_MODULE:装载卸载内核模块
  • CAP_NET_BIND_SERVER:是否允许普通用户绑定1024以内的特权端口;

修改容器的内核参数:securitycontext-sysctls-demo

apiVersion: v1
kind: Pod
metadata:
  name: securitycontext-sysctls-demo
  namespace: default
spec:
  securityContext:
    sysctls:
    - name: kernel.shm_rmid_forced
      value: "0"
    - name: net.ipv4.ip_unprivileged_port_start
      value: "0"
  containers:
  - name: demo
    image: ikubernetes/demoapp:v1.0
    imagePullPolicy: IfNotPresent
    securityContext:
      runAsUser: 1001
      runAsGroup: 1001

Pod内可安全使用的内核参数只有三个:

  • kernel.shm_rmid_forced
  • net.ipv4.ip_local_port_range
  • net.ipv4.tcp_syncookies

若需要添加不被允许的内核参数,需要添加如下文件:

vim /etc/default/kubelet
KUBELET_EXTRA_ARGS='需要添加的内核参数'

PS:且每一个节点都需要修改,且修改后要重启kubelet后才能生效

all-in-one

apiVersion: v1
kind: Pod
metadata:
  name: all-in-one
  namespace: default
spec:
  initContainers:
  - name: iptables-init
    image: ikubernetes/admin-box:latest
    imagePullPolicy: IfNotPresent
    command: ['/bin/sh','-c']
    args: ['iptables -t nat -A PREROUTING -p tcp --dport 8080 -j REDIRECT --to-port 80']
    securityContext:
      capabilities:
        add:
        - NET_ADMIN
  containers:
  - name: sidecar-proxy
    image: envoyproxy/envoy-alpine:v1.13.1
    command: ['/bin/sh','-c']
    args: ['sleep 3 && envoy -c /etc/envoy/envoy.yaml']
    lifecycle:
      postStart:
        exec:
          command: ['/bin/sh','-c','wget -O /etc/envoy/envoy.yaml http://ilinux.io/envoy.yaml']
    livenessProbe:
      tcpSocket:
        port: 80
      initialDelaySeconds: 5
    readinessProbe:
      tcpSocket:
        port: 80
      initialDelaySeconds: 5
  - name: demo
    image: ikubernetes/demoapp:v1.0
    imagePullPolicy: IfNotPresent
    env:
    - name: PORT
      value: '8080'
    livenessProbe:
      httpGet:
        path: '/livez'
        port: 8080
      initialDelaySeconds: 5
    readinessProbe:
      httpGet:
        path: '/readyz'
        port: 8080
      initialDelaySeconds: 15
    securityContext:
      runAsUser: 1001
      runAsGroup: 1001
    resources:
      requests:
        cpu: 0.5
        memory: "64Mi"
      limits:
        cpu: 2 
        memory: "1024Mi"
  securityContext:
    supplementalGroups: [1002, 1003]
    fsGroup: 2000

你可能感兴趣的:(运维,k8s,kubernetes,云计算)