• K8S之应用配置管理笔记


    背景问题

    除了依托容器镜像来定义运行的Container,Pod还需要解决如下问题

    1、不可变基础设施(容器)的可变配置

    2、敏感信息的存储和使用(如:密码,token等)

    3、集群中Pod自我的身份认证

    4、容器运行资源的配置管理

    5、容器的运行安全管控

    6、容器启动前置条件校验

    容器

    • 可变配置:ConfigMap
    • 敏感信息:Secret
    • 身份认证:ServiceAccount
    • 资源配置:Spec.Containers[].Resources.limits/requests
    • 安全管控:Spec.Containers[].SecurityContext
    • 前置校验:Spec.InitContainers

    ConfigMap介绍

    主要管理容器运行所需的配置文件,环境变量,命令行参数等可变配置。用于解耦容器镜像和可变配置,从而保障工作负载(Pod)的可移植性。

    ConfigMAp创建

    创建命令:kubectl create configmap [NAME] [DATA]

    其中DATA:

    • 指定文件或者目录
    • 指定键值对

    示例:

    1、指定文件:

    kubectl create configmap kube-flannel-cfg --from-file=configure-pod-container/configmap/cni-conf.json -n kube-system

    2、指定键值对:

    kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm

    ConfigMap使用

    ConfigMap主要被Pod使用,一般用于挂载Pod用的配置文件,环境变量,命令行参数等。

    具体配置文件:

    1. # 用ConfigMap配置环境变量
    2. apiVersion: v1
    3. kind: Pod
    4. metadata:
    5. name: cm-env-test
    6. spec:
    7. containers:
    8. - name: test-container
    9. image: busybox
    10. command: ["/bin/sh", "-c", "env"]
    11. env:
    12. # 用special-config中special.how定义环境变量
    13. - name: SPECIAL_LEVEL_KEY
    14. valueFrom:
    15. configMapKeyRef:
    16. name: special-config
    17. key: specal.how
    18. restartPolicy: Never
    19. # 用ConfigMap配置管控命令行参数
    20. apiVersion: v1
    21. kind: Pod
    22. metadata:
    23. name: cm-test-test
    24. spec:
    25. containers:
    26. - name: test-container
    27. image: busybox
    28. command: ["/bin/sh", "-c", "echo $(SPECIAL_LEVEL_KEY)"]
    29. env:
    30. # 在命令行参数中使用ConfigMap定义的环境变量
    31. - name: SPECIAL_LEVEL_KEY
    32. valueFrom:
    33. configMapKeyRef:
    34. name: special-config
    35. key: special.how
    36. restartPolicy: Never
    37. # 用ConfigMap挂载配置文件
    38. apiVersion: v1
    39. kind: Pod
    40. metadata:
    41. name: cm-volume-test
    42. spec:
    43. containers:
    44. - name: test-container
    45. image: busybox
    46. # # ConfigMap中指定的内容以文件形式挂载在容器中的/etc/config目录下
    47. command: ["/bin/sh", "-c", "ls /etc/config/"]
    48. volumeMounts:
    49. - name: config-volume
    50. mountPath: /etc/config
    51. volumes:
    52. - name: config-volume
    53. configMap:
    54. name: special-config
    55. restartPolicy: Never

    ConfigMap使用注意点

    1. ConfigMap文件大小限制:1MB (.ETCD的要求)
    2. Pod只能引用相同Namespace中的ConfigMap
    3. Pod引用的ConfigMap不存在时,Pod无法创建成功。即Pod创建前需要先创建好Config Map。
    4. 使用envFrom从ConfigMap来配置环境变量时,如果CongfigMap中的某些key被认为无效(比如key名称中带有数字),该环境变量将不会注入容器,但是Pod可以正常创建。
    5. 只有通过k8s api创建的pod才能使用ConfigMap,其他方式创建的pod(如manifest创建的static pod)不能使用ConfigMap

    Secret介绍

    Secret是在集群中用于存储密码,token等敏感信息用的资源对象。其中的敏感数据采用base-64编码保存,相比存储在明文的ConfigMap中更规范,更安全。

    1. apiVersion: v1
    2. kind: Secret
    3. metadata:
    4. name: mysecret
    5. namespace: kube-system
    6. type: Opaque
    7. data:
    8. username: xxx
    9. password: xxxx

    Secret主要有如下类型:

    • type=Opaque
    • type=kubernetes.io/service-account-token
    • type=kubernetes.io/dockerconfigjson
    • type=bootstrap.kubernetes.io/token

    1、指定文件:

    kubectl create secret generic myregistrykey --from-file=.dockerconfigjson=/root/.docker/config.json --type=kubernetes.io/dockerconfigjson

    命令:

    1. kubectl create secret generic myregistrykey --from-file=.dockerconfigjson=/root/.docker/config.json --type=kubernetes.io/dockerconfigjson
    2. kubectl get secret
    3. kubectl describe secret/myregistrykey
    4. kubectl get secret/myregistrykey -o yaml

    2、指定键值对:

    kubectl create secret generic prod-db-secret --from-literal=username=produser --from-literal=password=Y4nys7f11

    命令:

    1. kubectl create secret generic prod-db-secret --from-literal=username=produser --from-literal=password=Y4nys7f11
    2. kubectl get secret/prod-db-secret -o yaml

    Secret使用

    Secret主要被Pod使用,一般通过volume挂载到指定容器目录,供容器中业务使用。另外在需要访问私有镜像仓库时,也可以引用Secret来实现。

    1. [root@master pod]# cat secret-3.yaml
    2. apiVersion: v1
    3. kind: Pod
    4. metadata:
    5. name: mypod-3
    6. spec:
    7. containers:
    8. - name: mypod
    9. image: busybox
    10. command: ["/bin/sh", "-c", "sleep 120"]
    11. volumeMounts:
    12. - name: chaitc
    13. mountPath: "/etc/chaitc/"
    14. readOnly: true
    15. volumes:
    16. - name: chaitc
    17. secret:
    18. secretName: myregistrykey

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: mypod-123
    5. namespace: default
    6. spec:
    7. containers:
    8. - name: mypod
    9. image: busybox
    10. command: ["/bin/sh", "-c", "sleep 180"]
    11. volumeMounts:
    12. - name: chaitc
    13. mountPath: /var/run/secrets/kubernetes.io/serviceaccount
    14. readOnly: true
    15. serviceAccount: default
    16. serviceAccountName: default
    17. volumes:
    18. - name: chaitc
    19. secret:
    20. defaultMode: 420
    21. secretName: default-token-c9kc7

    Secret使用的注意点

    1、Secret文件大小限制:1MB

    2、Secret虽然采用base-64编码,但是可以简单解码查看原始信息。因此机密信息才用Secret存储仍需要慎重考虑或者Secret访问者进行控制。对Secret加密有较强需求,可以考虑结合Kubernetes + Vault来解决敏感信息的加密和权限管理。

    3、Secret最佳实践:因为list/watch的一般处理将获取到的namespace下所有secret,因此不建议采取list/watch方式获取Secret信息。而推荐使用GET来获取需要的Secret,从而减少更多Secret暴露的可能性。

    ServiceAccount介绍

    ServiceAccount主要用于解决Pod在集群中的身份认证问题。其中认证使用的授权信息,则利用前面讲到Secret(type=kubernetes.io/service-account-token)进行管理。

    命令

    1. kubectl get serviceaccount -o yaml
    2. kubectl get secret/default-token-c9kc7 -o yaml

    举例: Pod里的应用访问它所属的K8S集群

    实现原理:

    1、Pod创建时Admission Controller会根据指定的ServiceAccount(默认为default)把对应的Secret挂载到容器的目录下(/var/run/secrets/kubernetes.io/serviceaccount).(*k8s自动实现)

    2、当Pod访问集群时,可以默认利用Secret其中的token文件来认证Pod的身份。(ca.crt用于校验服务端)(*参考右边代码)

    3、默认token的认证信息为:

            - Group: system:serviceaccounts:[namespace-name]

            - User: system:serviceaccount:[namespace-name]:[pod-name]

    * 同时Pod身份被认证合法后,其权限需要通过RBAC功能来配置。默认具备资源的GET权限。

    kubernetes/config.go at 76277917b9b98bfac79d0e25fe8f45dfc5bec145 · kubernetes/kubernetes · GitHub

    1. // InClusterConfig returns a config object which uses the service account
    2. // kubernetes gives to pods. It's intended for clients that expect to be
    3. // running inside a pod running on kubernetes. It will return ErrNotInCluster
    4. // if called from a process not running in a kubernetes environment.
    5. func InClusterConfig() (*Config, error) {
    6. const (
    7. tokenFile = "/var/run/secrets/kubernetes.io/serviceaccount/token"
    8. rootCAFile = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
    9. )
    10. host, port := os.Getenv("KUBERNETES_SERVICE_HOST"), os.Getenv("KUBERNETES_SERVICE_PORT")
    11. if len(host) == 0 || len(port) == 0 {
    12. return nil, ErrNotInCluster
    13. }
    14. token, err := os.ReadFile(tokenFile)
    15. if err != nil {
    16. return nil, err
    17. }
    18. tlsClientConfig := TLSClientConfig{}
    19. if _, err := certutil.NewPool(rootCAFile); err != nil {
    20. klog.Errorf("Expected to load root CA config from %s, but got err: %v", rootCAFile, err)
    21. } else {
    22. tlsClientConfig.CAFile = rootCAFile
    23. }
    24. return &Config{
    25. // TODO: switch to using cluster DNS.
    26. Host: "https://" + net.JoinHostPort(host, port),
    27. TLSClientConfig: tlsClientConfig,
    28. BearerToken: string(token),
    29. BearerTokenFile: tokenFile,
    30. }, nil
    31. }

    容器资源配置管理

    支持资源类型:

    - CPU:单位:millicore (1 Core=1000millicore)

    - Memory: 单位:Byte

    - ephemeral storage(临时存储):单位:Byte

    - 自定义资源:配置时必须为整数

    配置方法:

    资源配置分为request/limit两种类型

    - CPU:

    spec.containers[].resources.limits.cpu

    spec.containers[].resources.requests.cpu

    - Memory:

    spec.containers[].resources.limits.memory

    spec.containers[].resources.requests.memory

    - ephemeral.storage(临时存储):

    spec.containers[].resources.limits.ephemeral-storage

    spec.containers[].resources.requests.ephemeral-storage

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: frontend
    5. spec:
    6. containers:
    7. - name: wp
    8. image: wordpress
    9. resources:
    10. # 申明需要的资源
    11. requests:
    12. memory: "64Mi"
    13. cpu: "250m"
    14. ephemeral-storage: "2Gi"
    15. # 申明需要资源的边界
    16. limits:
    17. memory: "128Mi"
    18. cpu: "500m"
    19. ephemeral-storage: "4Gi"

    Pod服务质量(QoS)配置

    依据容器对CPU,Memory资源的request/limit需求,Pod服务质量分类:

    • Guaranteed
    • Burstable
    • BestEffort

    Guaranteed定义:

    • Pod里的每个容器都必须有内存限制和请求,而且必须是一样的
    • Pod里的每个容器都必须有CPU限制和请求,而且必须是一样的

    Burstable定义:

    • 非Guaranteed
    • Pod里至少有一个容器有内存或者CPU请求

    BestEffort定义

    • 非Guaranteed
    • 非Burstable

    当节点上Memory资源不足时,将依据BestEffort,Burstable, Buaranteed的优先顺序驱逐Pod

    Security Context介绍

    Security Context主要用于限制容器的行为,从而保障系统和其他容器的安全。

    1、容器级别的Security Context: 仅对指定容器生效

    2、Pod级别的Security Context: 对指定Pod中的所有容器生效

    3、Pod Security Policies(PSP):对集群内所有Pod生效

    权限和访问控制设置项:

    1、Discretionary Access Control:根据用户id和组id来控制文件访问权限

    2、SElinux: 通过SElinux的策略配置控制用户,进程等对文件等访问控制

    3、privileged:容器是否为特权模式

    4、Linux Capabilities:给特定进程配置privileged能力

    5、AppArmor:控制可执行文件的访问控制权限(读写文件/目录,网络端口读写等)

    6、Seccomp:控制进程可以操作的系统调用

    7、AllowPrivilegeEscalation:控制一个进程是否能比其父进程获取更多的权限

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: security-context-demo
    5. spec:
    6. # Pod级别Security Context定义
    7. securityContext:
    8. runAsUser: 1000
    9. runAsGroup: 3000
    10. fsGroup: 2000
    11. volumes:
    12. - name: sec-ctx-vol
    13. emptyDir: {}
    14. containers:
    15. - name: sec-ctx-demo
    16. image: busybox
    17. command: [ "sh", "-c", "sleep 1h" ]
    18. volumeMounts:
    19. - name: sec-ctx-vol
    20. mountPath: /data/demo
    21. # 容器级别定义
    22. securityContext:
    23. allowPrivilegeEscalation: false

    InitContainer介绍

    InitContainer和普通Container的区别:

    1、InitContainer会先于普通Container启动执行,直到所有InitContainer执行成功后,普通Container才会被启动

    2、Pod中多个InitContainer之间是按次序以此启动执行,而Pod中多个普通Container是并行启动

    3、InitContainer执行成功后就结束退出了,而普通容器可能会一直执行或者重启(restartPolicy!=Never)

    InitContainer用途:

    基于InitContainer和普通Container的区别,一般InitContainer用于普通Container启动前的初始化(如配置文件准备)或者普通Container启动的前置条件检查(如网络联通检验)。

  • 相关阅读:
    虹科案例 | 空调故障无冷气,且没有故障码
    Flink学习之flink sql
    gpt批量原创文章生成器,不限制内容的生成器
    1. 云计算简介
    英语写作中“建立”、“构造”build、construct、establish、set up的用法
    Centos7 |Canal Admin搭建Canal Server集群|
    Golang常用语法糖
    C语言assert函数:什么是“assert”函数
    服务器数据恢复—Storwize V3700存储数据恢复案例
    idea默认带的equals和hashcode引起的bug
  • 原文地址:https://blog.csdn.net/chaotingge/article/details/126880538