MichaelFu

好记性不如烂笔头

为了从外部能够访问到集群中的服务,k8S 提供了多种方式,从 NodePort 类型的 ServiceLoadBalancer 类型的 Service,到 Ingress,一直在改进,NodePort类型的服务流量从单一节点进来,没法在节点之间负载均衡,进而衍生出LoadBalancer类型的服务,该类型的服务虽然解决了前面存在的问题,但是需要云厂商的支持,况且针对每个Service粒度提供一个公网IP地址,未免有点浪费,进而衍生出 Ingress,支持7层代理,能够通过单一的入口,以及域名和Path匹配等机制将流量转发到不同的后端服务中去。Ingress 虽然解决了LoadBalancer存在的问题,但它在实际的使用场景中又遇到了新的问题:

  1. Ingress 仅支持7层,没法对四层的流量进行转发;
  2. Ingress 在设计的时候只考虑一种用户角色,既整个系统的运维人员和管理员,这种模型在许多拥有多个团队的企业中都不适用,包括应用开发人员、平台运维人员、安全管理员等,他们在协作开发和交付应用的过程中需要控制Ingress配置的不同方面;
  3. Ingress 中使用了很多annotion实现自定义功能,对于不同的 ingress controller 没法做到一致性,例如,这里的 nginx annotions,这些在原本的 Ingress 对象中都是不支持的;

在这些问题的促使下,社区又提出了新的概念:Gateway,明确定义并划分不同角色的职责范围有助于简化管理,对三个主要的 Gateway API 资源(GatewayClassGatewayRoute)进行了标准化。具体来说,基础架构提供商负责为 Kubernetes 集群定义 GatewayClasses,集群运维人员则负责在集群中部署和配置 Gateway(包括策略),而应用开发人员可以自由地将 Route 附加到 Gateway,以对外暴露应用。

阅读全文 »

本篇文章主要简单讲解TLS证书的基本知识以及如何在K8S中使用证书提供安全服务。

证书

TLS证书用于证明访问目标的有效性,当访问某个网站时,浏览器会自动验证证书是否有效,并且会通过证书中提供的Server公钥和Server协商出用于接下来安全数据传输的对称加密秘钥。浏览器(或者客户端,例如:curl)验证服务端证书的流程如下:

  1. 浏览器或者客户端在和服务端建立加密通信的流程中,会下载服务端的证书到本地,这个证书中包含了服务端证书的公钥,并且这个证书会使用可信任的CA机构的私钥进行签名;
  2. 浏览器或者操作系统中安装了大多数著名机构的根证书,浏览器或者客户端会使用这些机构根证书的公钥验证收到的证书是否是可信任机构颁发的;
  3. 如果浏览器或者客户端收到的证书是有效的,紧接着会验证证书中包含的服务器或者IP地址是不是和当前打开的地址匹配;
  4. 紧接着浏览器会和服务端协商出用于本次数据加密的对称秘钥,使用对称秘钥一是这个秘钥是在每次数据通信时动态协商出来的,会话结束就是小了,防止公钥泄漏带来的安全问题,而是对称加解密密相比非对称加解密有更好的性能表现;

X.509 公钥证书中有一些常用的扩展名,如下所示是它们的含义:

  • .csr:证书请求文件,是由 RFC 2986定义的PKCS10格式,包含部分/全部的请求证书的信息,比如,主题, 机构,国家等,并且包含了请求证书的公玥,这些被CA中心签名后返回一张证书,返回的证书是公钥证书(只包含公玥不含私钥);
  • .pem:是一种容器格式,可能仅包含公钥证书,也可以包含完整的证书链(包括公玥,私钥,和根证书)。也可能用来编码 CSR文件;
  • .key:就是一个pem格式只包含私玥的文件,.key 作为文件名只是作为一个明显的别名;
  • .pkcs12 .pfx .p12pkcs即 RSA定义的公玥密码学(Public-Key Cryptography Standards)标准,有多个标准pkcs12只是其一,是描述个人信息交换语法标准,有的文件直接使用其作为文件后缀名。这种文件包含公钥和私玥证书对,跟pem文件不同的是,它的内容是完全加密的。用openssl可以把其转换成包含公玥和私玥的.pem文件。命令:openssl pkcs12 -in file-to-convert.p12 -out converted-file.pem -nodes
  • .derderASN.1众多编码方案中的一个,使用der编码方案编码的pem文件。der编码是使用二进制编码,一般pem文件使用的是base64进行编码,所以完全可以把der编码的文件转换成pem文件,命令:openssl x509 -inform der -in to-convert.der -out converted.pem 使用der编码的pem文件,后缀名可以为.der,也可以为 .cert .cer .crt
  • .cert .cer .crtpem或者der编码格式的证书文件,这些文件后缀名都会被windows资源管理器认为是证书文件。有趣的是, .pem 反而不会被认为是证书文件;
阅读全文 »

tun 是一种虚拟的3层虚拟网络设备,同时它也是一个字符设备,字符设备意味着可以把它当做一个文件,可以使用文件API操作这个设备,例如 open/read/write,由于它同时也是一个网络设备,所以它也可以像一个网卡一样,从内核网络协议栈中收发报文。所以从它架构上来看,tun 设备的一端连接着应用程序,一端连接着网络协议栈,如下图所示:

从在系统中的表象来看,字符设备的文件类型是c,没有大小,但是有主次版本号:

1
2
$ ls -alh /dev/net/tun
crw-rw-rw- 1 root root 10, 200 Jan 30 17:00 /dev/net/tun

tun 设备的创建是通过打开/dev/net/tun这个文件,然后使用ioctl系统调用对其进行clone。也可以使用 ip 命令来实现tun设备的创建:

ip tuntap add dev tun1 mod tun

新创建的 tun1 设备位于 /sys/class/net/ 目录中:

1
2
$ ll /sys/class/net/tun1
lrwxrwxrwx 1 root root 0 Feb 4 15:44 /sys/class/net/tun1 -> ../../devices/virtual/net/tun1/

删除使用如下命令:

ip tuntap del dev tun1 mod tun

阅读全文 »

Pod中的容器它里面的文件在磁盘上是临时存放的,当容器崩溃或停止时,kubelet 会以干净的状态重新启动容器,在容器生命周期内创建或修改的所有文件都将丢失。另外Pod在运行期间,需要为它注入一些必要的配置信息,以满足其运行。在这些场景的要求下, 就应需而生,为了持久化存放容器里的数据,为容器运行提供配置。所有这些卷可以分为3类:

  • 持久卷(Persistent Volume):和节点一样,属于集群资源,可以由管理员事先制备,或者使用存储类来动态制备,使用时通过PVC申请,就像其名字表述的一样,为了持久化数据;
  • 投射卷(Projected Volumes):为Pod运行注入必要的配置信息;
  • 临时卷(Ephemeral Volume):应用程序需要额外的存储,但并不关心数据在重启后是否仍然可用,随Pod而生,随Pod而灭。例如,Redis缓存服务经常受限于内存大小,而且可以将不常用的数据转移到比内存慢的存储中,对总体性能的影响并不大;

这些卷以及它们的分类、涉及的概念如下:

mindmap
卷
    投射卷
        Secret
        DownwardAPI
        Configmap
        ServiceAccountToken
    持久卷
        PV
        PVC
        StorageClass
    临时卷
        emptyDir
        CSI 临时卷
        通用临时卷
阅读全文 »

PodK8S中的调度单位,它是一个逻辑概念,用于将一些关系密切的容器部署在一起提供对外服务,这些容器互相之间会发生直接的文件交换、使用localhost或者Socket文件进行本地通信、会发生非常频繁的远程调用、需要共享某些Linux Namespace等等,Pod 中的所有容器都共享同一个Network NamespaceK8S 中为了实现不同的目的,在Pod基础之上衍生出了不同的部署模型,例如,常见的 DeploymentReplicaset、以及StatefulSet等等,本文就来举例并且说明它们之间的区别。

这些对象之间的关系如下图所示:

阅读全文 »

ServiceKubernetes中的资源类型,用来将一组Pod的应用作为网络服务公开。虽然每个Pod都有自己的IP,但是这个IP的生命周期与Pod生命周期一致,也就是说Pod销毁后这个IP也就无效了,而ServiceIP(ClusterIP) 则是在创建之后便不会改变,ServicePod 之前通过iptablesipvs代理等手段关联。k8s一共提供了四种不同目的类型的Service,分别是ClusterIPNodePortLoadBalancer以及ExternalName,本来我们就来探索这四种服务的使用场景以及背后的使用原理。

k8s 集群中的每个节点都是运行一个kube-proxy,它用于实现流量从ServicePod之间的转发。默认在 Linux 平台下,它使用 iptables 作为后端实现,通过监听Kubernetes控制平面,获知对 ServiceEndpointSlice对象的添加和删除操作,对于每个Servicekube-proxy 会添加 iptables 规则,在这些这些规则的加持下,流向Service的流量会被重新路由到Service后端集合中的其中之一。

四种模式的基本工作原理如下图所示:

阅读全文 »

容器网络-跨主机容器通信中,我们使用flannel实现了容器的跨主机通信,在使用kubeadm创建多借点集群时,在集群初始化之后,首先安装了kube-flannel CNI插件,用于k8s集群pod之间互通,这是集群节点Ready的必要条件,因为k8s自身并不能实现pod之间互通,需要借助CNI完成此功能。

单机容器通信是将主上的容器通过连接在docker0网桥实现,然后跨主机容器通信是通过vxlan中的flannel.x设备实现跨主机之间的容器通信,k8sflannel-cni插件处理不同pod之间互通的方式就和跨主机容器通信的方式一样,只不过在k8s集群中将用于单机上容器互通的docker0网桥换成了cni0

k8s之所以要创建一个与docker0功能相同的网桥,是因为k8s并没有使用Docker的网络模型,它并不希望和Docker之间有强依赖,所以不具备配置这样一个网桥的能力。

所以在使用flannel-cni插件的模式下,k8s之间不同pod互通的模式下如下图所示,和容器网络-跨主机容器通信唯一区别是网桥名称的变化:

阅读全文 »

iptablesLinux上重要的防火墙程序,它既是一个用户态的程序,也是一个内核的模块,通过向Linux内核netfilter框架注入钩子函数,以及自定义的规则,实现包过滤,修改,地址转换,日志记录等功能。在k8s生态中,作为kube-proxy的默认后端,实现流量在集群之内的的路由和转发,写这篇文章的最初原有也是想了解k8s是如何将访问到节点上的流量,路由到自定义的Service以及最终的pod内部。

netfilter

在了解iptables之前,先认识下netfilter,它是Linux内核子系统,允许实现各种与网络相关的操作,它是网络相关操作领域的基础设施,基于此可以实现任何大多数网络包的诉求:

  • 包过滤,这可能是大多数场景下的诉求,也是iptables最多的使用场景,可以用来限制某些特征的包进入到本机,例如,指定ip范围,某类协议的;
  • NAT,负责转换网络数据包的源IP和目的IP;
  • 数据包修改,地址转换只是数据包修改的一种,还可以修改数据包的TOS(Type Of Service,服务类型)、TTL指以及为数据包设置Mark标记等;

Netfilter框架在Linux内核中提供了一堆钩子,当网络数据包通过内核中的协议栈时,它会遍历这些钩子。Netfilter允许使用这些钩子编写模块并注册回调函数,当钩子被触发时,回调函数将被调用。这些钩子被用在包处理的以下5个阶段:

  • NF_INET_PRE_ROUTING:当数据包从网卡上收到还有路由之前,这类钩子函数就会被触发,然后内核判断这个数据包是否是发往当前主机的,根据条件,将触发以下两个钩子;
  • NF_INET_LOCAL_IN:当数据包决定路由到本机上的时候,就会触发这类钩子;
  • NF_INET_FORWARD:当数据包决定要继续转发的时候,这类钩子会被触发;
  • NF_INET_LOCAL_OUT:这类钩子函数会在本机生成数据包,发出去之前被调用;
  • NF_INET_POST_ROUTING:这类钩子函数主要用于从本机发出去的数据包,但是在发到网卡之前;
阅读全文 »

容器其实是一种沙盒技术。顾名思义,沙盒就是能够像一个集装箱一样,把你的应用装起来的技术。这样,应用与应用之间,就因为有了边界而不至于相互干扰。对于应用来说,它的静态表现就是程序,平常都安安静静地待在磁盘上;而一旦运行起来,它就变成了计算机里的数据和状态的总和,这就是它的动态表现。容器技术的核心功能,就是通过约束和修改进程的动态表现,从而为其创造出一个边界。对于Docker等大多数Linux容器来说,Cgroups技术是用来制造约束的主要手段,而Namespace技术则是用来修改进程视图的主要方法。本篇文章的主要目标就是手动利用Linux提供的 CgroupNamespace 技术创建出一个容器。

容器镜像

首先我们从容器镜像开始,从我们对容器的认识来说,进入到容器之后,看到了一个独立的文件系统,和宿主机完全隔离,包含了应用程序所需要的数据、文件以及所有依赖,而容器镜像就是用来构建应用程序所需的文件系统,容器镜像有一个更为专业的名字,叫做 rootfs 根文件系统,当我们启动一个进程时,为进程启用Linux Namespace配置,设置Cgroup参数用于资源限制,切换进程的根目录,这样它看起来就像在一个独立的系统中运行。但是需要明确的是,rootfs只是一个操作系统所包含的文件、配置和目录,并不包括操作系统内核。在Linux操作系统中,这两部分是分开存放的,操作系统只有在开机启动时才会加载指定版本的内核镜像。因此同一台机器上的所有容器,都共享宿主机操作系统的内核。

这就意味着,如果我们的应用程序需要配置内核参数、加载额外的内核模块,以及跟内核进行直接的交互,就需要注意了:这些操作和依赖的对象,都是宿主机操作系统的内核,它对于该机器上的所有容器来说是一个“全局变量”,牵一发而动全身。这也是容器相比于虚拟机的主要缺陷之一:毕竟后者不仅有模拟出来的硬件机器充当沙盒,而且每个沙盒里还运行着一个完整的Guest OS给应用随便折腾。

所以,容器启动快是因为本质上就是宿主机上的一个进程而已,启动一个进程的速度当然比启动一个虚拟机的速度快。不过,正是由于rootfs的存在,容器才有了一个被反复宣传至今的重要特性:一致性,rootfs里打包的不只是应用,而是整个操作系统的文件和目录,也就意味着,应用以及它运行所需要的所有依赖,都被封装在了一起。无论在本地、云端,还是在一台任何地方的机器上,用户只需要解压打包好的容器镜像,那么这个应用运行所需要的完整的执行环境就被重现出来了。这种深入到操作系统级别的运行环境一致性,打通了应用在本地开发和远端执行环境之间难以逾越的鸿沟。

阅读全文 »

在使用k8s的过程中,始终绕不开容器运行时这个关键组件,当通过kubectl创建一个应用时,节点上的kubelet组件接收到这个事件,然后调用容器运行时实现的CRI接口创建容器。当我们开始关注这个容器运行时的实现和生态的时候,发现存在很多关键词,例如:dockercontainerdruncOCI 以及 CRI 等等,本篇文章主要记录厘清这些关键词所代表的概念及其出现的背景。

从公众的视野来看,DockerK8S要早得多,2013年,Docker 就凭借着 Build,Ship and Run Any App, Anywhere 这句名满世界的广告语,迅速进入了开发者的视线中,方便、快速使它得到空前的发展,一时间内,容器化、微服务化成了各大公司技术团队主要的技术方向。由于 Docker 大火,有人比较眼红,CoreOS 实现了自己的容器引擎rkt,为了避免容器技术领域分裂和一家独大的场面出现,在2015年,Docker公司联合Linux基金会联合推动发起了OCI(Open Container Initiative)倡议,其内容主要包括OCI Runtime Spec(容器运行时规范)OCI Image Spec(镜像格式规范)OCI Distribution Spec(镜像分发规范)。同时,Docker公司将libcontainer模块捐给社区,作为OCI标准的实现,并改名为 runc,这就是我们常说的runc的由来,后面交由在2015年成立的 CNCF 基金会管理,为其他玩家不依赖于Docker构建自家平台提供了可能性,所以说 OCI 是大家为了避免命脉被别人把住的协商结果。

k8s 和 Docker 的竞争主要是围绕容器编排领域展开,Docker 除了自身的容器引擎,后续还逐步发展出了 docker swarm 容器集群管理管理系统,以及配套的 docker machinedocker compose 等工具,但由于Docker公司始终在Docekr的规划中占据着话语权,让社区以及其他玩家不服,所以开始主推 k8s,由于 k8s 先进的podsidecar 设计理念以及在社区的民主化架构,从API到容器运行时的每一层,Kubernetes项目都为开发者暴露出了可以扩展的插件机制,鼓励用户通过代码的方式介入Kubernetes项目的每一个阶段。Kubernetes项目的这个变革的效果立竿见影,很快在整个容器社区中催生出了大量的、基于Kubernetes API和扩展接口的创新工作,涌现了一大批优秀的项目,比如:IstioRookDocekr发现在和k8s竞争出现劣势的时候,强行将自家的容器编排系统docker swarm 内置到docker中,这种内置容器编排、集群管理和负载均衡能力,固然可以使得Docker项目的边界直接扩大到一个完整的PaaS项目的范畴,但这种变更带来的技术复杂度和维护难度,长远来看对Docker项目是不利的,从外界来看就是一条道走到黑,要保持霸权地位,不开放。

由于 k8s 的茁壮成长,Docker 发现竞争无望,将自己的容器运行时 containerd 从架构上独立出来,并且捐赠给社区维护,放弃和 k8s 的竞争,Docker 项目改名 mobyDocker 全面升级成 PaaS 平台,从此 k8s 一统江湖。

阅读全文 »
0%