美文网首页
k8s pv pvc coredns securityConte

k8s pv pvc coredns securityConte

作者: Joening | 来源:发表于2023-08-24 20:05 被阅读0次

用于记录下k8s集群中pv(Persistent)、sc(Storeage Class)、pvc(PersistenVolumeClaim)的相关概念。

PersistentVolume(PV 存储卷)是集群中的一块存储空间,由集群管理员管理、或者由 Storage Class(存储类)自动管理。PV(存储卷)和 node(节点)一样,是集群中的资源(kubernetes 集群由存储资源和计算资源组成)。PersistentVolumeClaim(存储卷声明)是一种类型的 Volume(数据卷),PersistentVolumeClaim(存储卷声明)引用的 PersistentVolume(存储卷)有自己的生命周期,该生命周期独立于任何使用它的容器组。PersistentVolume(存储卷)描述了如何提供存储的细节信息(NFS、cephfs等存储的具体参数)。

PersistentVolumeClaim(PVC 存储卷声明)代表用户使用存储的请求。Pod 容器组消耗 node 计算资源,PVC 存储卷声明消耗 PersistentVolume 存储资源。Pod 容器组可以请求特定数量的计算资源(CPU / 内存);PersistentVolumeClaim 可以请求特定大小/特定访问模式(只能被单节点读写/可被多节点只读/可被多节点读写)的存储资源。

根据应用程序的特点不同,其所需要的存储资源也存在不同的要求,例如读写性能等。集群管理员必须能够提供关于 PersistentVolume(存储卷)的更多选择,无需用户关心存储卷背后的实现细节。为了解决这个问题,K8s 引入了 StorageClass(存储类)的概念。

PV和PVC的关系
PV是集群中的存储资源,通常由集群管理人员创建和管理;
SC用于对PV进行分类,如果正确配置,SC可以根据PVC的请求动态创建PV;
PVC是使用该资源的请求,通常由应用程序提出的请求,并指定对应的SC和需要的存储空间大小;
PVC可以作为数据卷的一种,被挂载到容器中使用。
PVC的管理过程
PV和PVC的管理过程如下:

存储资源的回收策略
当用户不在需要其数据卷时,可以删除掉其 PVC,此时其对应的 PV 将被集群回收并再利用。K8s 集群根据 PV 中的 reclaim policy(回收策略)决定在其被回收时做对应的处理。当前支持的回收策略有:Retained(保留)、Recycled(重复利用)、Deleted(删除)

Retain
保留策略需要集群管理员手工回收该资源。当绑定的 PVC 被删除后,PV 仍然存在,并被认为是”已释放“。但是此时该存储卷仍然不能被其他 PVC 绑定,因为前一个绑定的 PVC 对应容器组的数据还在其中。

可以通过如下步骤回收该 PV:

删除该 PersistentVolume。PV删除后,其数据仍然存在于对应的外部存储介质中(nfs、cefpfs、glusterfs 等)
手工删除对应存储介质上的数据
手工删除对应的存储介质,也可以创建一个新的PV并再次使用该存储介质。
Recycle
再利用策略将在 PV 回收时,执行一个基本的清除操作(rm -rf /thevolume/*),并使其可以再次被新的 PVC 绑定。
也可以自定义一个 recycler pod template,用于执行清除操作。参考: 官方文档。
Delete
删除策略将从 k8e 集群移除 PV 以及其关联的外部存储介质(云环境中的 AWA EBS、GCE PD、Azure Disk 或 Cinder volume

core-dns的配置文件

coredns部署脚本

#!/bin/bash

# Deploys CoreDNS to a cluster currently running Kube-DNS.

show_help () {
cat << USAGE
usage: $0 [ -r REVERSE-CIDR ] [ -i DNS-IP ] [ -d CLUSTER-DOMAIN ] [ -t YAML-TEMPLATE ]

    -r : Define a reverse zone for the given CIDR. You may specify this option more
         than once to add multiple reverse zones. If no reverse CIDRs are defined,
         then the default is to handle all reverse zones (i.e. in-addr.arpa and ip6.arpa)
    -i : Specify the cluster DNS IP address. If not specified, the IP address of
         the existing "kube-dns" service is used, if present.
    -s : Skips the translation of kube-dns configmap to the corresponding CoreDNS Corefile configuration.

USAGE
exit 0
}

# Simple Defaults
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
CLUSTER_DOMAIN=cluster.local
YAML_TEMPLATE="$DIR/coredns.yaml.sed"
STUBDOMAINS=""
UPSTREAM=\\/etc\\/resolv\.conf

# Translates the kube-dns ConfigMap to equivalent CoreDNS Configuration.
function translate-kube-dns-configmap {
    kube-dns-upstreamnameserver-to-coredns
    kube-dns-stubdomains-to-coredns
}

function kube-dns-upstreamnameserver-to-coredns {
  up=$(kubectl -n kube-system get configmap kube-dns  -ojsonpath='{.data.upstreamNameservers}' 2> /dev/null | tr -d '[",]')
  if [[ ! -z ${up} ]]; then
    UPSTREAM=${up}
  fi
}

function kube-dns-stubdomains-to-coredns {
  STUBDOMAIN_TEMPLATE='
    SD_DOMAIN:53 {
      errors
      cache 30
      loop
      forward . SD_DESTINATION {
        max_concurrent 1000
      }
    }'

  function dequote {
    str=${1#\"} # delete leading quote
    str=${str%\"} # delete trailing quote
    echo ${str}
  }

  function parse_stub_domains() {
    sd=$1

  # get keys - each key is a domain
  sd_keys=$(echo -n $sd | jq keys[])

  # For each domain ...
  for dom in $sd_keys; do
    dst=$(echo -n $sd | jq '.['$dom'][0]') # get the destination

    dom=$(dequote $dom)
    dst=$(dequote $dst)

    sd_stanza=${STUBDOMAIN_TEMPLATE/SD_DOMAIN/$dom} # replace SD_DOMAIN
    sd_stanza=${sd_stanza/SD_DESTINATION/$dst} # replace SD_DESTINATION
    echo "$sd_stanza"
  done
}

  sd=$(kubectl -n kube-system get configmap kube-dns  -ojsonpath='{.data.stubDomains}' 2> /dev/null)
  STUBDOMAINS=$(parse_stub_domains "$sd")
}


# Get Opts
while getopts "hsr:i:d:t:k:" opt; do
    case "$opt" in
    h)  show_help
        ;;
    s)  SKIP=1
        ;;
    r)  REVERSE_CIDRS="$REVERSE_CIDRS $OPTARG"
        ;;
    i)  CLUSTER_DNS_IP=$OPTARG
        ;;
    d)  CLUSTER_DOMAIN=$OPTARG
        ;;
    t)  YAML_TEMPLATE=$OPTARG
        ;;
    esac
done

# Conditional Defaults
if [[ -z $REVERSE_CIDRS ]]; then
  REVERSE_CIDRS="in-addr.arpa ip6.arpa"
fi
if [[ -z $CLUSTER_DNS_IP ]]; then
  # Default IP to kube-dns IP
  CLUSTER_DNS_IP=$(kubectl get service --namespace kube-system kube-dns -o jsonpath="{.spec.clusterIP}")
  if [ $? -ne 0 ]; then
      >&2 echo "Error! The IP address for DNS service couldn't be determined automatically. Please specify the DNS-IP with the '-i' option."
      exit 2
  fi
fi

if [[ "${SKIP}" -ne 1 ]] ; then
    translate-kube-dns-configmap
fi

orig=$'\n'
replace=$'\\\n'
sed -e "s/CLUSTER_DNS_IP/$CLUSTER_DNS_IP/g" \
    -e "s/CLUSTER_DOMAIN/$CLUSTER_DOMAIN/g" \
    -e "s?REVERSE_CIDRS?$REVERSE_CIDRS?g" \
    -e "s@STUBDOMAINS@${STUBDOMAINS//$orig/$replace}@g" \
    -e "s/UPSTREAMNAMESERVER/$UPSTREAM/g" \
    "${YAML_TEMPLATE}"

corednsyaml清单

apiVersion: v1
kind: ServiceAccount
metadata:
  name: coredns
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: system:coredns
rules:
  - apiGroups:
    - ""
    resources:
    - endpoints
    - services
    - pods
    - namespaces
    verbs:
    - list
    - watch
  - apiGroups:
    - discovery.k8s.io
    resources:
    - endpointslices
    verbs:
    - list
    - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: system:coredns
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:coredns
subjects:
- kind: ServiceAccount
  name: coredns
  namespace: kube-system
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: coredns
  namespace: kube-system
data:
  Corefile: |
    .:53 {
        errors
        health {
          lameduck 5s
        }
        ready
        kubernetes CLUSTER_DOMAIN REVERSE_CIDRS {
          fallthrough in-addr.arpa ip6.arpa
        }
        prometheus :9153
        forward . UPSTREAMNAMESERVER {
          max_concurrent 1000
        }
        cache 30
        loop
        reload
        loadbalance
    }STUBDOMAINS
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: coredns
  namespace: kube-system
  labels:
    k8s-app: kube-dns
    kubernetes.io/name: "CoreDNS"
    app.kubernetes.io/name: coredns
spec:
  # replicas: not specified here:
  # 1. Default is 1.
  # 2. Will be tuned in real time if DNS horizontal auto-scaling is turned on.
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
  selector:
    matchLabels:
      k8s-app: kube-dns
      app.kubernetes.io/name: coredns
  template:
    metadata:
      labels:
        k8s-app: kube-dns
        app.kubernetes.io/name: coredns
    spec:
      priorityClassName: system-cluster-critical
      serviceAccountName: coredns
      tolerations:
        - key: "CriticalAddonsOnly"
          operator: "Exists"
      nodeSelector:
        kubernetes.io/os: linux
      affinity:
         podAntiAffinity:
           requiredDuringSchedulingIgnoredDuringExecution:
           - labelSelector:
               matchExpressions:
               - key: k8s-app
                 operator: In
                 values: ["kube-dns"]
             topologyKey: kubernetes.io/hostname
      containers:
      - name: coredns
        image: coredns/coredns:1.9.4
        imagePullPolicy: IfNotPresent
        resources:
          limits:
            memory: 170Mi
          requests:
            cpu: 100m
            memory: 70Mi
        args: [ "-conf", "/etc/coredns/Corefile" ]
        volumeMounts:
        - name: config-volume
          mountPath: /etc/coredns
          readOnly: true
        ports:
        - containerPort: 53
          name: dns
          protocol: UDP
        - containerPort: 53
          name: dns-tcp
          protocol: TCP
        - containerPort: 9153
          name: metrics
          protocol: TCP
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            add:
            - NET_BIND_SERVICE
            drop:
            - all
          readOnlyRootFilesystem: true
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 60
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 5
        readinessProbe:
          httpGet:
            path: /ready
            port: 8181
            scheme: HTTP
      dnsPolicy: Default
      volumes:
        - name: config-volume
          configMap:
            name: coredns
            items:
            - key: Corefile
              path: Corefile
---
apiVersion: v1
kind: Service
metadata:
  name: kube-dns
  namespace: kube-system
  annotations:
    prometheus.io/port: "9153"
    prometheus.io/scrape: "true"
  labels:
    k8s-app: kube-dns
    kubernetes.io/cluster-service: "true"
    kubernetes.io/name: "CoreDNS"
    app.kubernetes.io/name: coredns
spec:
  selector:
    k8s-app: kube-dns
    app.kubernetes.io/name: coredns
  clusterIP: CLUSTER_DNS_IP
  ports:
  - name: dns
    port: 53
    protocol: UDP
  - name: dns-tcp
    port: 53
    protocol: TCP
  - name: metrics
    port: 9153
    protocol: TCP

在Kubernetes中,使用以下默认Corefile配置安装了CoreDNS:

apiVersion: v1
kind: ConfigMap
metadata:
  name: coredns
  namespace: kube-system
data:
  Corefile: |
    .:53 {
        errors
        log
        health {
            lameduck 5s
        }
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa {
            pods insecure
            fallthrough in-addr.arpa ip6.arpa
            ttl 30
        }
        prometheus :9153
        forward . /etc/resolv.conf
        cache 30
        loop
        reload
        loadbalance
    }

Corefile配置包括以下CoreDNS 插件:

errors: 将错误记录到stdout。
log: 记录解析记录的日志。
health:据报告CoreDNS的健康http://localhost:8080/health。使用这种扩展语法,lameduck将使进程运行不正常,然后等待5秒钟,然后关闭进程。
ready:当所有能够发出信号准备就绪的插件都这样做时,端口8181上的HTTP端点将返回200 OK。
kubernetes:CoreDNS将基于Kubernetes的服务和Pod的IP答复DNS查询。可以在CoreDNS网站上找到有关该插件的更多详细信息。ttl允许您为响应设置自定义TTL。默认值为5秒。允许的最小TTL为0秒,最大为3600秒。将TTL设置为0将防止记录被缓存。提供该pods insecure选项是为了与kube-dns向后兼容。您可以使用该pods verified选项,仅当在相同名称空间中存在具有匹配IP的容器时,该选项才返回A记录。pods disabled如果您不使用pod记录,则可以使用该选项。
prometheus:CoreDNS的Metrics可在http://localhost:9153/metrics在普罗米修斯中展示(也称为OpenMetrics)。
forward:不在Kubernetes集群域内的任何查询都将转发到预定义的解析器(/etc/resolv.conf)。若要转发至其他dns服务器,而不是/etc/resolv.conf,可以写为: forward . dns_ip。
cache:这将启用前端缓存。
loop:检测简单的转发循环,如果发现循环,则暂停CoreDNS进程。
reload:允许自动重新加载已更改的Corefile。编辑ConfigMap配置后,请等待两分钟,以使更改生效。
loadbalance:这是一个轮询DNS负载平衡器,用于随机分配答案中A,AAAA和MX记录的顺序。
如何更改configmap
$ kubectl get configmap -n kube-system # 查看当前名称空间
NAME DATA AGE
calico-config 4 24d
coredns 1 24d
extension-apiserver-authentication 6 24d
kube-proxy 2 24d
kubeadm-config 2 24d
kubelet-config-1.18 1 24d

安全上下文 Security Context

一组用于决定容器是如何创建和运行的约束条件,它们代表创建和运行容器时使用的运行时参数;
比如:容器运行时的用户、用户的权限等
Pod上的SC有两个级别 分别为Pod级别、容器级别

常用字段 Pod级别的安全上下文

apiVersion: v1
kind: Pod
metadata: {...}
spec:
  securityContext:    #Pod级别的安全上下文,对内部所有容器均有效
    runAsUser <integer>  #以指定的用户身份运行容器进程,默认由镜像中的USER指定
    runAsGroup <integer>  #以指定的用户组运行容器进程,默认使用的组随容器运行时
    supplementalGroups <[]integer> #为容器中1号进程的用户添加的附加组;
    fsGroup <integer>    #为容器中的1号进程附加的一个专用组,其功能类似于sgid
    runAsNonRoot <boolean> #是否以非root身份运行
    seLinuxOptions <0bject>  #SELinux的相关配置
    windowsOptions<Object>   #Windows容器专用的设置
    sysctls   <[]Object>   #应用到当前Pod上的名称空间级别的sysctl参数设置列表
        Pod内可安全内核参数只有4个: 
        kernel.shm_rmid_forced
        net.ipv4.ip_local_port_range
        net.ipv4.tcp_syncookies
        net.ipv4.ping_group_range (从 Kubernetes 1.18 开始)
        
        其它参数需要重启K8S 在/etc/defaulte/kubelte(如果没有则新建)中添加
        net.ipv4.ip_unprivileged_port_start
        --allowed-unsafe-sysctls=net.core.somaxconn
        ......

常用字段 容器级别的安全上下文

  containers:
  - name: ...
    image: .
    securityContext:  #容器级别的安全上下文,仅生效于当前容器
      runAsUser <integer>    #以指定的用户身份运行容器进程
      runAsGroup <integer>   #以指定的用户组运行容器进程
      runAsNonRoot <boolean>  #是否以非root身份运行
      allowPrivilegeEscalation <boolean> #是否允许特权升级
      capabilities <Object>  #于当前容器上添加(add)或删除(drop)的内核能力
        add<[]string>  #添加由列表定义的各内核能力
        drop <[]string>  #移除由列表定义的各内核能力
            CAP_CHOWN:改变UID和GID;
            CAP_MKNOD:mknod() 创建设备文件;
            CAP_NET_ADMIN:网络管理权限;
            CAP_SYSADMIN:大部分的管理权限;
            CAP_SYS_TIME:同步时间
            CAP_SYS MODULE:装载卸载内核模块
            CAP_NET_BIND_SERVER:允许绑定1024以内特权端口
            也可以管理员 getcap, setcap直接设置权限(了解)
      privileged <boolean>  #是否运行为特权容器 可直接使用宿主机内核 谨慎使用
      procMount <string>   #设置容器的procMount类型,默认为DefaultProcMount;
      readOnlyRootFilesystem boolean>  #是否将根文件系统设置为只读模式
      seLinux0ptions <Object> #SELinux的相关配置
      windowsoptions <Object> #windows容器专用的设置

相关文章

网友评论

      本文标题:k8s pv pvc coredns securityConte

      本文链接:https://www.haomeiwen.com/subject/pbcvmdtx.html