Kubernetes-in-action (八)
本节内容: kube 运行原理 & 安全防护 (service account, [cluster] role, [cluster] role binding,)
架构
组成
- kube控制平面
- etcd分布式持久化存储
- API服务器
- 唯一与etcd交互的组件
- 其他组件都与其交互,来获取需要的信息,或执行资源操作
- 主要将资源变更同步到其他控制器,由他们来进行资源变更,自己则只是通知
- 调度器
- 控制pod的调度,默认是default-scheduler
- 控制器管理器
- 每种资源都有对应的控制器,控制器一直观察资源的状态是否与配置的一样,不一样则会请求api server去变更资源的状态以达到与配置一样。
- 更新流程:控制器 -> api server -> kubectl
- 控制器和kubectl之间是互不相关的,都由api server这个中心来控制
- 工作节点
- Kubelet
- 启动node后持续监控pod的资源状态并告诉api服务器
- 接受api 服务器的更新指令来更新pod的状态
- pod探针观测,并执行重启
- Kubelet服务代理(kube-proxy)
- 将工作节点的流量发到指定的pod,通过iptables实现将流量转发到pod上
- 容器运⾏时(Docker、rkt或者其他)
- Kubelet
- 附加组件
- Kubernetes DNS服务器
- 利用 api 服务器的监控机制来订阅service和endpoint的变动,以及dns记录的变更
- 在更新间隙中,可能导致dns无效
- 仪表板
- Ingress控制器
- 类似一个反向代理服务器
- 虽然配置了service,但是流量不会通过service,而是直接连上pod,从而pod可以获取到源的client ip
- Heapster(容器集群监控)
- 容器⽹络接⼜插件(本章后⾯会做讨论
- Kubernetes DNS服务器
kubectl get events --watch
是用来实时查看kubectl接收的事件
pod 运行
- 每个pod在启动时,都会默认有一个基础容器(只执行暂停操作的容器),用于处理pod内所有的容器公用一个linux命名空间。
- 如果基础容器被删除,则kubectl会重建它以及pod的所有容器。
- 例: 一个只声明nginx容器的pod, 生成pod时会有两个容器被创建
kube的网络
- pod间的通讯实现
- 没有时NAT(网络地址转换)来实现pod的通讯,为了简洁
- 集群内部是一个局域网,所以可以通过ip地址直接访问(不同node)
- 同node上:
- 每个pod中基础容器会创建网络命名空间让pod内的所有容器都走同一个网络接口
- pod会通过一个虚拟网络接口来连接到一个网桥: pod A -> veth pair -> bridge -> veth pair -> pod B
service的实现
- service 无法被ping通,因为是个虚拟ip地址
- service相关的事情都是由kube-proxy进程处理,对于service和endpoint的变化,kube-proxy会更新到相应的iptables中,这样在一个请求在来后会被重定向到pod的地址。
安全防护
kube 中由一系列的认证授权插件,在一个请求到达api服务器时,会经过这些插件,如果有一个通过则说明可以请求
ServiceAccount
作用
- 一种kube的资源
- 默认将service account配置的secret加载到pod中
- 每个ServiceAccount只能在自己的ns中使用
实践
- 创建一个sa : sa-> service account 缩写,同样使用kubectl get sa等命令
- pod绑定这个sa
- 查看 sa是否可以拉取pod信息 (容器ambassador默认启动一个kube-proxy,所以可以访问api服务器)
kubectl exec -it curl-custom-sa -c main curl localhost:8001/api/v1/pods
- 检验pod的secret
kubectl get sa -o yaml
# 查看 token secret 名称kubectl describe secret my-sa-token-tc54g
# 查看token,默认是jwt格式kubectl exec -it curl-custom-sa -c main -- cat /var/run/secrets/kubernetes.io/serviceaccount/token
#
容器内挂载的token内容
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-sa
imagePullSecrets:
- name: my-secret
---
apiVersion: v1
kind: Pod
metadata:
name: curl-custom-sa
spec:
serviceAccountName: my-sa
containers:
- name: main
image: curlimages/curl:7.87.0
command: [ "sleep", "9999999" ]
- name: ambassador
image: luksa/kubectl-proxy:1.6.2
RBAC
概念
- RBAC授权插件将⽤户⾓⾊作为决定⽤户能否执⾏操作的关键因素
- 由两组资源控制 (均可用kube get命令)
- Role(⾓⾊)和ClusterRole(集群⾓⾊),它们指定了在资源上可以执⾏哪些动词
- Role只能用于创建或者指定的ns
- 可以用yaml文件或者命令(
kubectl create role service-reader --verb=get --verb=list --resource=services -n bar
)创建
- 可以用yaml文件或者命令(
- Role只能用于创建或者指定的ns
- RoleBinding (⾓⾊绑定) 和 ClusterRoleBinding (集群⾓⾊绑定),它们将上述⾓⾊绑定到特定的⽤户、组或ServiceAccounts上
- RoleBinding:将role绑定到一个或多个 service account 或者 组、用户
- 可以跨命名空间绑定service account
- 命令:
kubectl create rolebinding test --role=service-reader --serviceaccount=foo:default -n foo
- RoleBinding:将role绑定到一个或多个 service account 或者 组、用户
- Role(⾓⾊)和ClusterRole(集群⾓⾊),它们指定了在资源上可以执⾏哪些动词
实践:Role,RoleBinding
- 创建两个ns: foo,bar
kubectl create ns foo
,kubectl create ns bar
- 在两个空间中创建具有kube-proxy和curl工具的pod
kubectl create -f curl-custom-sa.yaml -n bar
kubectl create -f curl-custom-sa.yaml -n foo
apiVersion: v1
kind: Pod
metadata:
name: curl-custom-sa
spec:
serviceAccountName: default
containers:
- name: main
image: curlimages/curl:7.87.0
command: ["sleep", "9999999"]
- name: ambassador
image: luksa/kubectl-proxy:1.6.2
- 创建一个role,并给role赋予访问service的权限
kubectl create -f role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: foo
name: service-reader
rules:
- apiGroups: [ "" ]
verbs: [ "get", "list" ]
resources: [ "services" ]
- 给role绑定 foo,bar两个空间default的serviceaccount
kubectl create rolebinding test --role=service-reader --serviceaccount=foo:default -n foo
kubectl create rolebinding test2 --role=service-reader --serviceaccount=bar:default -n foo
- 通过pod访问api server,查看是否具有访问权限
kubectl exec -it curl-custom-sa -c main -n bar -- curl http://localhost:8001/api/v1/namespaces/foo/services
kubectl exec -it curl-custom-sa -c main -n foo -- curl http://localhost:8001/api/v1/namespaces/bar/services
RoleBinding可以在foo空间中声明, 但是可以将role 绑定到 bar空间的service account,因为role的声明是在foo中,
若是如此配置,则可以让bar空间的pod访问到foo空间的services (如上述实践)
由此得出: RoleBinding、Role都是和命名空间相关的,既这个命名空间的资源可以让谁访问,是这个空间内的谁还是其他的谁(角色)
实践:ClusterRole,ClusterRoleBinding
有些资源不在命名空间中,所以需要用集群范围的角色定义。 如 pv、node、ns
集群资源只能用 ClusterRoleBinding 而不能用 RoleBinding
- 创建一个cluster role, 并赋予访问pv的权限. [不需要指定命名空间]
- 创建cluster role binding, 将role绑定到foo,bar的service account
kubectl create clusterrolebinding pv-test --clusterrole=pv-reader --serviceaccount=foo:default --serviceaccount=bar:default
- 检查名称空间内的pod是否具有访问pv的权限
kubectl exec -it curl-custom-sa -c main -n bar -- curl http://localhost:8001/api/v1/persistentvolumes
kubectl exec -it curl-custom-sa -c main -n foo -- curl http://localhost:8001/api/v1/persistentvolumes
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: pv-reader
rules:
- apiGroups: [""]
verbs: ["get", "list"]
resources: ["persistentvolumes"]
实践:ClusterRole,RoleBinding
使用RoleBinding结合ClusterRole: ClusterRole中配置资源范围只有RoleBinding所在的命名空间
使用ClusterRoleBinding结合ClusterRole: ClusterRole中配置资源范围作用与整个集群。
- 在foo,bar中创建一个rolebinding,将clusterrole view (kube自带的) 绑定他们。
kubectl create rolebinding view-test --clusterrole=view --serviceaccount=foo:default -n foo
kubectl create rolebinding view-test --clusterrole=view --serviceaccount=bar:default -n bar
- 查看foo和bar中的pod是否可以查询命名空间内所有pod
kubectl exec -it curl-custom-sa -c main -n foo -- curl http://localhost:8001/api/v1/namespaces/foo/pods
kubectl exec -it curl-custom-sa -c main -n bar -- curl http://localhost:8001/api/v1/namespaces/bar/pods
- 查看foo和bar中的pod是否可以查询集群内所有pod
kubectl exec -it curl-custom-sa -c main -n bar -- curl http://localhost:8001/api/v1/pods
# 失败, 403
- 删除foo中的role binding,添加一个cluster role binding,再次查看是否可以查询集群内的所有pod
kubectl delete rolebinding view-test -n foo
kubectl create clusterrolebinding view-test --clusterrole=view --serviceaccount=foo:default
kubectl exec -it curl-custom-sa -c main -n foo -- curl http://localhost:8001/api/v1/pods
# 成功
role、cluster role、role binding、 cluster role binding 之间的用法要多试试才能加深理解
- 从书中copy的