Kubernetes 笔记

Master组件

master组件包括API Server, Controller Manager, Scheduler, ETCD.

API Server

API Server 提供HTTP/HTTPS 服务, 该服务为Kubernetes主机的所有组件提供RESTFUL API支持. 例如,可以通过GET请求获取资源状态, 通过POST请求创建新的资源或者监控资源. API Server还会读取并更新ETCD

Controller Manager

控制器管理器控制集群中的不同资源.

  • Replication Controller 确保系统中每个对象都按照设定数量的容器运行.
  • Node Controller 在节点宕机是响应, 会疏散运行在节点上的POD.
  • Endpoint Controller 关联服务与POD之间的联系
  • Service Account Controller 为新的命名空间创建默认账户
  • Token Controller 创建API访问令牌

ETCD

ETCD是一个开源的分布式键值存储系统, Kubernetes用他存储所有的RESTful API对象

Scheduler

调度器会根据节点上的资源容量或者资源利用率选择合适POD运行的节点, 还会考虑将同一集合中的POD分散到不同节点

工作节点组件

每个节点上都需要安装和运行以下组件, 记录pod的运行时状态, 并报告给master

kubelet

kubelet是节点中的主要进程,周期性的将节点活动报告给apiserver, 例如pod的健康状态, 节点的健康状态和存活探针,kubelet通过容器运行时运行容器, 例如Docker和rkt

kube-proxy

kube-proxy负责处理Pod负载均衡器(Service)和pod之间的路由。 以及从外部访问服务的路由。 提供两种代理模式,userspace和iptables。 userspace模式切换内核空间和用户空间带来了大量的开销,而iptables模式通过修改linux中的iptables nat以实现跨容器的tcp和udp的数据包路由, 是目前默认的代理模式

docker

docker是容器的一种实现, kubernetes使用docker作为默认的容器引擎

master与节点通信

客户端使用kubectl向api服务器发送请求, api服务器响应该请求, 在etcd中推送和提取对应的对象信息。 调度器决定应该分配哪个节点执行任务。控制器管理器监控正在运行的任务, 当状态异常时做出响应。 另一方面, api服务器通过kubelet从pod获取日志, 并作为master组件之间的转发中心

kubernetes 命令

config

kubectl config get-clusters # 查询所有cluster
kubectl config use-context ${context_name} # 切换不同的context
kubectl config current-context # 查询所有的context
kubectl config view # 查询kubeconfig的配置

explain

# 用法 kubectl explain ${resource}
kubectl explain deployment # 查询deployment的说明

get

kubectl get pods -o wide
kubectl get pods -l key=value # label 选择器

每个pod有一个状态信息PodStatus, 包含一组映射PodConditions, 其中的健可能有PodScheduled, Ready, Initialized 和 Unschedulable, 值可能为TRUE, FALSE和unknown.如果pod没有被创建出来, PodStatus会简要说明失败的原因.

Pod与服务账户关联, 该服务账户为正在运行pod的进程提供标识, 它由API服务器中的服务账户和令牌控制器控制. Pod中的/var/run/secrets/kubernetes.io/serviceaccount目录会挂载一个只读存储卷, 里面包含了具有API访问权限的token, Kubernetes会创建一个默认的服务账户, 可以使用kubectl get serviceaccounts 命令查看.

scale

kubectl scale deployment ${app} --replica 5 # 扩展pod数量

deployment 管理replicaset, replicaset管理pod
deployment 和 replicaset控制器的异同
相似: 确保pod数量, 确保pod健康, 弹性伸缩, 滚动升级
不同: deployment支持replicaset全部特性, 额外功能: 回滚, 版本记录, 暂停和启动

kubernetes 组件

service

service是一个抽象层, 用于把流量路由到一组pod, 不需要跟踪每个pod的ip地址, 服务通常用标签选择器选择需要路由的pod.
service类型有四种, nodeport, clusterip(默认), loadbalancer, externalname

ExternalName 被用来访问外部的资源(即用作正向代理), 需要先创建没有selector的service, 然后创建同名的endpoint, endpoint中指定外部的IP

minikube 下不能直接访问nodeport的服务, 需要使用minikube service [-n ${NameSpace}] ${SVC} --url建立隧道, 才能访问service

secrets

Secrets 以键值对形式创建存储秘钥的对象, 用于向pod提供敏感信息, 可以是密码, 访问秘钥或者token. secrets不会存储到磁盘, 而是存储在每个节点的tmpfs文件系统中. secrets不用来存储大量数据, 大小限制1M

secrets包含三种类型:

  • generic 将要在应用程序中使用的文本
  • docker-registry 存储私有镜像仓库的凭据
  • TLS 存储集群管理的CA证书

docker-registry 类型的secret也被称为image pull secrets, 拉取镜像时通过kubelet传递私有docker registry 的密码, 不需要在每个节点执行docker login

kubectl create secret docker-registry ${REGISTRY_NAME} \
--docker-server=${DOCKER_SERVER} \
--docker-username=${DOCKER_USERNAME} \
--docker-password=${DOCKER_PASS} \
--docker-email=${DOCKER_EMAIL}
# secrets 挂载实例
apiVersion: v1
kind: Pod
metadata:
  name: secret-access
spec:
  containers:
  - name: centos
    image: centos
    command: ["/bin/sh", "-c", "cat /secret/password-example;done"]
    volumeMounts:
      - name: secret-vol
        mountPath: /secret
        readOnly: true
  volumes:
    - name: secret-vol
      secret: 
        secretName: mypassword
        # items  可选
        items:
        - key: mypassword
          path: password-example
# secrets 文件将挂载在/mountPath/secretName中, 如果指定了item, 则为/mountPath/Path


# secrets 挂在到环境变量中
...
spec:
  containers:
  - name: centos
    imagee: centos
    command: ["/bin/sh", "-c", "while:;do echo ${MY_PASSWORD};sleep 10;done;"]
    env:
      - name: MY_PASSWORD
        valueFrom: 
          secretKeyRef:
            name: mypassword
            key: mypassword 

# 创建generic的key
kubectl create secret generic mytest --from-literal=key1=value1 --from-literal=key2=value2

ConfigMap

ConfigMap是一可以将配置保留在Docker镜像之外的方法。配置数据通过键值对的形式注入到pod。 secrets用于存储敏感数据, ConfigMap用于存储不敏感数据。

configmap 与 secret的区别在于describe pod的时候, secret的值不会直接显示出来

Kubernetes存储

emptydir

emptydir 在pod被分配到node的时候创建, pod从节点上移除的时候, emptydir也会永久删除.

容器崩溃并不会影响emptydir

statefulset

sts 部署有状态应用, pod会按顺序启动, 保留IP和存储

Kubernetes的QoS

Gurantee, Brustable, Best Effort
Best Effort 只需要将资源限制设置为0, 或者不指定资源限制, 用于worker进程, 代理或缓存节点
如果namespace有定义资源限制, 如果没有给pod设置限制, 则不会设置Best effort.

Gurantee用于运行关键任务, 如服务主节点或者带持久卷的后端数据库.
配置Guarantee 需要将资源限制和资源请求设置为相同值.

Brustable 资源限制不是强制性的, 会尽可能消耗资源.request 和 limit不一致

如果一个pod中两个容器, 一个是bustable, 一个是gurantee, 则pod是brustable, 因为Kubernetes不知道brustable会消耗多少资源.

网络与安全

kubernetes 的网络要求

  1. 所有的容器之间可以互相访问, 无论在哪个节点上
  2. 所有的节点可以与所有容器互相通信
  3. 容器看自己的IP与其他容器一致

Pod 内部容器的通信:
Kubernetes 同一个pod中的容器彼此视为localhost, 由网络容器实现,该改容器充当为Pod中每个容器流量转发的桥梁. 比如一个Pod声明了两个容器, 在节点上试用docker ps -a 可以看到实际启动的是3个容器, 网络容器包含了其他容器共享的网络命名空间. 统一网络命名空间的容器共享相同的IP和相同的网络配置.

Pod 间通信:
默认情况下, 同一节点内的pod通信会通过网桥, pod1和pod2通信时, 数据包通过pod1的网络命名空间传递到响应的veth pair vethXXX, 然后进入网桥, 网桥广播目标IP帮助数据包找到路径.

跨节点Pod 通信:
Kubernetes通过容器网络接口(CNI)实现这个功能. 用户可以选择不同的实现方式, 如L2,L3, overlay, overlay网络是常见的解决方案之一, 也被称为数据包封装, 在数据包离开数据源之前封装, 导致overlay会增加网络延迟和复杂性

minikube 启动时, 可以用minikube start --network-plugin=cni 来指定CNI插件启动.

Pod的网络策略(Network Policy)

网络策略是Pod的软件防火墙, 默认情况下, 每个pod都可以互相通信, 没有任何边界, 网络策略可以应用于Pod的隔离, 通过命名空间选择器, 定义了谁可以访问哪个Pod的哪个端口. 如果Pod启用了网络策略, 它会拒绝其他任何流量.

kubenertes 持续集成

patch

kubectl patch 会根据输入的json参数部分进行修改, 如果想更新镜像, 命令如下

kubectl patch deployment my-app -p '{"spec": {"template": {"spec": {"containers": [{"name": "app", "image": "alpine:3.6"}]}}}}'

set

kubectl set 对某些属性进行修改

kubectl set image deployment my-app app=alpine:3.6

edit

kubectl edit 打开编辑器以交互方式进行编辑, 保存后立即生效

replace

kubectl replace 用另一个模板文件进行替换, 如果资源尚未创建, 或者包含无法更改的属性, 则会提示报错

apply

kubectl apply 如果资源已经存在, 则会更新, 如果不存在则会创建. 创建资源时, 功能相当于kubectl create --save-config

rollout

kubectl rollout 命令用来管理滚动更新

# 查看更新状态
> kubectl rollout status deployment ${DEPLOYMENT} 
# 查看更新历史
> kubectl rollout history deployment ${DEPLOYMENT}
REVISION  CHANGE-CAUSE
1         <none>
2         <none>
3         <none>
4         <none>
5         <none>
# change cause 为none, 如果要记录更新的命令, 使用kubectl patch的时候, 加上--record.

# 回滚到特定版本, 如果不加revision则回滚到上一个版本
kubectl rollout undo deployment ${DEPLOYMENT} --to-revision=<REVISION #>

特性

探针

探针是容器健康状况的指示器, 通过kubectl定期对容器执行诊断操作来判断其健康状态.

  • liveness 探针, 指示容器是否存活, 如果容器在此探测上失败, 则kubectl会将其终止, 并且根据Pod的restartPolicy重新启动.
  • readiness 探针指示容器是否已经准备好接收流量, 如果服务后端的Pod未准备好, Pod就绪之前不会创建对应的端点.

restartPolicy 告诉Kubernetes在Pod故障或者终止时如何进行处理, 有三种模式, Always, OnFailure和Never, 默认选项为Always.

有三种探针操作可以配置

  • exec: 在容器内执行已定义的命令, 如果退出代码为0 则成功
  • tcpSocket: 通过TCP测试指定端口, 如果端口打开则成功
  • httpGet: 对目标容器的IP地址执行HTTP GET操作, header可以自定义, 如果状态码满足200~400, 则被认为是健康的.

还有五个参数定义探测器的行为:

  • initialDelaySeconds: 第一次探测之前, kubelet应该等待多久
  • successThreshold: 连续探测成功通过该阈值的时候, 容器被认为是健康的
  • failureThreshold: 定义失败的阈值
  • timeoutSeconds: 单个操作的时间限制
  • periodSeconds: 探针操作之间的间隔

初始化容器

init容器是一个或多个容器, 在应用容器启动之前启动, 并按照顺序逐个启动, 如果任何容器发生故障, Pod会根据restartPolicy策略重新开始, 知道所有容器能正常退出.
init容器与应用容器的区别:

  • init容器没有readiness探针
  • init容器的端口不会被服务捕获
  • 如果一个init容器超过了所有普通容器资源限制的总和, Kubernetes会根据init容器的资源限制来调度Pod.

终止Pod

Kubernetes收到删除的调用请求后,发送SIGTERM信号到要删除的Pod,并将Pod的状态变为Terminating。同时,如果Pod作为Service的后端,Kubernetes将删除该Pod的端点以停止进一步的请求。有时候有些Pod不能正常退出,可能是Pod没有处理SIGTERM信号,也可能仅仅因为它们的任务没有完成,这种情况下,Kubernetes会在配置的终止时间后发送SIGKILL强行终止这些Pod,这个时间配置为.spec.terminationGracePeriodSeconds.

SIGTERM信号在ash / dash 的shell中不会转发, 如果想保证应用程序顺利接收SIGTERM信号, 应该使用exec的方式运行程序, 而不是使用shell方式

# exec 方式
CMD ["python", "-u", "app.py"]
# shell 方式
CMD python -u app.py 

某些情况下, SIGTERM不会触发进程的终止处理程序, 例如将SIGTERM发送到nginx实际上会导致快速关闭, 为了优雅地关闭nginx, 必须发送带有nginx -s quit 的SIGQUIT. 为了将SIGTERM以外的信号发送到容器, 可以使用生命周期钩子.

生命周期钩子

生命周期钩子是对容器执行的事件感知的操作, 工作方式类似单个Kubernetes探针操作, 但只会在容器的生命周期内触发事件, 支持以下两类事件.

  • PostStart: 在创建容器后立即执行, 这类钩子与容器的入口点是异步触发的, 无法保证在容器启动之前执行, 一般不用来初始化容器的资源.
  • PreStop: 在将SIGTERM发送到容器之前执行, PreStop是同步调用, SIGTERM在PreStop退出后发送.

钩子的另一个特性是可能以某种方式影响Pod的状态, 除非PostStart钩子成功退出, 否组Pod不会运行, Pod设置为在删除时立即终止, 除非PreStop钩子成功退出, 否则不会发送SIGTERM.

资源配额和默认配额

ResourceQuota限制命名空间内可以消耗的资源, 通过设置资源限制, 避免消耗所有节点的资源.
LimitRange指定命名空间的默认资源请求和限制. 如果Pod 未指定请求和限制则使用默认值.

新建集群用户

添加用户账户认证

root@master-0:~# openssl genrsa -out yun.key 2048
root@master-0:~# openssl req -new -key yun.key -out yun.csr -subj "/CN=yun"
root@master-0:~# openssl x509 -req -in yun.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out yun.crt -days 3650
root@master-0:~# kubectl config set-credentials yun --client-certificate=yun.crt --client-key=yun.key
root@master-0:~# kubectl config set-context yun-context --cluster=kubernetes --user=yun

基于角色的授权

# 把新建的用户绑定到cluster-admin 角色
kubectl create clusterrolebinding user-binding --clusterrole cluster-admin --user yun
posted @ 2022-08-02 17:26  Chinor  阅读(179)  评论(0编辑  收藏  举报