云原生(K8s|菜鸟学Kubernetes(K8s)系列——(一)关于Pod和Namespace

Kubernetes(K8s)系列——(一)关于Pod和Namespace 一、关于Pod 1、什么是Pod? 在Kubernetes中,她并不直接处理单个容器,而是直接操作Pod,Pod相当于是Kubernetes中最基本的部署单位。一个Pod中是可以包含多个容器的,容器中运行的是我们的应用程序。
一个Pod中是一组紧密相关的容器,这些容器一定是运行在同一个工作节点上的。每个Pod就像是一个独立的逻辑机器,拥有自己的IP、主机名、进程等。下面看看工作节点、Pod、容器、应用程序之间的关系。
云原生(K8s|菜鸟学Kubernetes(K8s)系列——(一)关于Pod和Namespace
文章图片

1.1 为什么需要Pod?
为什么需要Pod?为什么不直接使用容器?为什么需要同时运行多个容器?为什么不能简单地把所有进程都放在一个单独的容器中?

一个容器中运行一个进程会让水平扩缩容变的简单,如果一个容器中即运行了Tomcat,又运行了MySQL,那在扩缩容的时候就变的复杂了。同时一个容器运行一个进程会让排错变的简单。一个容器中运行一个进程,这样才能够最好地应用容器编排来管理好容器和服务。因此建议一个容器中只运行一个进程。
由于不能将多个进程聚集在一个单独的容器中,所以就需要一种更高级的结构将容器绑定在一起,并将她们作为一个单元进行管理,这就产生了Pod。在一个Pod中,我们可以同时运行一些密切相关的进程,并为他们提供相同的环境,这时这些进程就好像全部运行于单个容器中一样,同时又保持着一定的隔离。
1.2 Pod间的容器是互通的
在Docker中我们知道每个容器之间是相互隔离的,每个容器都有属于自己的一组Namespace(指的是Linux的Namespace)。但是在K8s中,Pod之间是隔离的,而Pod中的一组容器是共享一些资源的。K8s通过配置Docker来让一个Pod内的所有容器共享相同的Namespace,而不是每个容器都有自己的一组Namespace。
由于一个Pod中的所有容器都在相同的Network命名空间下(他们还共享其他的一些Namespace),所以他们都共享相同的IP和端口。这就意味着在同一Pod中的容器运行的多个进程需要注意不能绑定到相同的端口号,否则会导致端口冲突。注意是同一Pod,而不同Pod间的容器是不用担心端口冲突的。此外,一个Pod中的所有容器也都具有相同的loopback网络接口,所以同一个Pod中的多个容器是可以通过localhost进行通信的。
在K8s集群中所有的Pod都在同一共享网络地址空间中,因此,整个集群中的每个Pod都可以通过其他Pod的IP地址实现相互访问。
在通过kubeadm安装Kubernetes集群的时候设置过一个配置:
kubeadm init \ --apiserver-advertise-address=xx.xx.xx.xx \ --image-repository xxx \ --kubernetes-version v1.21.0 \ --service-cidr=10.96.0.0/16 \ --pod-network-cidr=10.244.0.0/16### 这个就是集群中Pod的网络范围

1.3 通过Pod管理容器
我们将Pod视为独立的机器,其中每个机器只托管一个特定的应用。以前我们习惯于将各种应用程序塞进同一台主机,但是Pod不是这么玩的。我们将应用程序组织到多个Pod中,而每个Pod中只包含紧密相关的组件或进程。(注意,Pod是很轻量的,我们可以在几乎不导致任何额外开销的前提下拥有尽可能多的Pod,所以不用担心创建了太多的Pod)
以一个由前端应用和后端服务组成的多层应用程序为例。
虽然我们可以在单个Pod中同时运行前端服务和后端服务这两个容器,但是这种方式并不推荐,前面也提到尽量让一个容器中运行一个进程。对于前端服务和后端服务来说,他们真的需要运行在同一台计算机上吗?答案一定是否定的,如果把前端和后端都部署在同一个Pod中,那么他们两个相当于是共生的,始终会部署在同一台机器上。这时如果我们集群具有多个节点,而整个前后端服务一直都部署在同一节点上,就不能对其他节点的资源进行充分利用。另外,如果我们只想扩容后端服务怎么办?所以说,更合理的做法就是把前后端服务拆分成两个Pod,然后可以部署在不同的节点上,来提高机器的资源利用率,或者更加方便的进行扩缩容等。
何时在Pod中使用多个容器? 将多个容器添加到单个Pod中的主要原因是应用可能由一个主进程和多个辅助进程组成。
在决定是将两个容器放入一个Pod还是两个单独的Pod时,我们需要问自己以下问题:
  • 他们需要一起运行还是可以在不同的主机上运行?
  • 他们代表的是一个整体还是相互独立的组件?
  • 他们必须一起进行扩缩容还是可以分别进行?
一般情况下,我们总是倾向于在单独的Pod中运行单独的容器。
2、Pod的生命周期(可暂时忽略) 每一个Pod中可以有三组容器:初始化容器组、Pod容器组、临时容器组
云原生(K8s|菜鸟学Kubernetes(K8s)系列——(一)关于Pod和Namespace
文章图片

应用容器
  • Pod启动,会先依次执行所有初始化容器,有一个失败,则Pod不能启动
  • 接下来启动所有的应用容器(每一个应用容器都必须能一直运行起来),Pod开始正式工作,只要有一个容器启动失败就会尝试重启Pod内的这个容器,Pod只要是NotReady,Pod就不对外提供服务了
初始化容器
应用容器必须一直运行,与应用容器不同的是,初始化容器必须要有终结的时刻,一般不要用一直启动的镜像
创建一个初始化容器:(初始化容器一般用来准备好一些前置东西,然后其他容器再启动
apiVersion: v1 kind: Pod metadata: name: "pod-life-02" namespace: default labels: app: "pod-life-02" spec: volumes: - name: content-vol emptyDir: {} initContainers:### Pod在启动containers之前,先要【运行完】initContainers的所有容器,所以这些容器必须有终结,不能一直运行 - name: init-c-01 image: alpine### 必须有终结的那个时刻,一般不要用一直启动的镜像,比如nginx command: ["/bin/sh","-c","echo 12222222 > /app/index.html; sleep 30; "] # 这里睡30秒后会自动结束 volumeMounts: - name: content-vol mountPath: /app containers: ### docker run alpine 没有在后台一直启动的程序 - name: pod-life-01 image: "nginx" #默认的启动命令是启动nginx。nginx启动在后台一直有了 volumeMounts: - name: content-vol mountPath: /usr/share/nginx/html - name: pod-life-02 image: "alpine"#pod里面的containers都必须能启动起来 command: ["/bin/sh","-c","sleep 30"] # 这里30秒后会自动结束,Pod的状态会变为NotReady,然后重启这个容器。

初始化容器的状态如下:
云原生(K8s|菜鸟学Kubernetes(K8s)系列——(一)关于Pod和Namespace
文章图片

临时容器
临时容器在当前版本还不太稳定,所以暂时不太用
临时容器用于线上排错。有些容器基础镜像。线上没法排错(比如一些容器里面的基础命令ip a、vim等命令都是没有的)。这时就可以使用临时容器进入这个Pod。临时容器共享了Pod的所有。临时容器 有Debug的一些命令,排错完成以后,只要exit退出容器,临时容器自动删除
3、创建一个Pod 3.1 从一个简单的Yaml开始
apiVersion: v1### 描述文件遵循v1版本的kubernetes API kind: Pod### 表示资源类型 metadata: name: test-pod### pod的名称 namespace: default spec: containers: - name: zaq-containers### 容器的名称 image: nginx ### 创建容器所用的镜像 ports: - containerPort: 80### 应用监听的端口 protocol: TCP

通过kubectl apply -f mypod.yaml 即可部署这个Pod
这个文件表达的含义是:该文件遵循kubernetes API的v1版本,描述的资源类型是Pod类型,名称为test-pod,该Pod由基于nginx镜像的单个容器组成,该容器的名称为zaq-containers,他正在监听8080端口。
在Pod定义中指定的端口纯粹是展示性的,写不写无所谓。但是明确定义端口是有必要的,这样能让每个使用集群的人都可以快速查看每个Pod对外暴露的端口。后面我们还可以为每个端口指定一个名称,方便我们管理。
上面的这些属性我们不用特意去记,我们随时可以通过 kubectl explain 命令去查看每个字段的含义:
  • kubectl explain pods
  • kubectl explain pods.spec
  • kubectl explain pods.spec.containers
以后K8s的所有资源都可以通过一个Yaml文件来进行描述
注意:
我全文中提到的资源大部分指是Pod、Deploymen、Service、Ingress等等等等的统称,后面会一一介绍,小部分资源指的是机器的资源,如CPU、内存等,需要根据上下文环境区分。
3.2 对创建好的Pod进行一些操作
获取所有的Pod kubectl get pod -A
查看Pod的完整定义 kubectl get pod test-pod -o yaml
查看Pod的日志 这里说查看Pod的日志,其实更准确的说应该是查看容器的日志
kubectl logs test-pod
如果Pod中存在多个容器,则只需要在命令后加 -c <容器名称> 参数即可
kubectl logs test-pod -c zaq-containers
注意:Pod被删除那他的日志也会被删除,如果希望在Pod删除之后仍然可以获取其日志,我们需要设置中心化的、集群范围的日志系统,将所有日志存储到中心存储中。
4、使用标签组织Pod
关于标签这个概念新手可能不好理解,如果看不懂可以先往后看,之后再回过头来看可能会醍醐灌顶。
4.1 什么是标签
标签不仅可以组织Pod,还能组织Kubernetes中的其他资源。他的主要功能就是为资源进行分组,方便管理。
标签是可以附加到资源的任意键值对,用来选择具有该确切标签的资源(通过标签选择器来选择)。只要标签的key在资源内是唯一的,一个资源便可以拥有多个标签。通常我们在创建资源时就会将标签附加到资源上。
以Pod资源为例,我们看看当K8s集群中的Pod没有打标签时:
云原生(K8s|菜鸟学Kubernetes(K8s)系列——(一)关于Pod和Namespace
文章图片

这是我们一个微服务项目产生的Pod,他们由的Account服务部署的Pod,有的是Product服务部署的Pod,甚至有的是生产环境的,有的是stable环境的,他们在集群中杂乱无章。
而如果我们为这些Pod加上标签(进行分组),效果大不相同:
云原生(K8s|菜鸟学Kubernetes(K8s)系列——(一)关于Pod和Namespace
文章图片

这是从两位维度上为他们分组:一个是按服务来分,一个是按环境来分。分别为各个Pod上打了两个标签:app和rel。
  • app:指定这个Pod属于哪个应用、组件或微服务。
  • rel:指定该Pod运行的应用程序属于什么环境。
4.2 为Pod指定标签
apiVersion: v1### 描述文件遵循v1版本的kubernetes API kind: Pod### 表示资源类型 metadata: name: test-pod### pod的名称 namespace: default labels: env: prod###为pod指定 env:prod 标签 app: testapp###为pod指定 app:testapp 标签 spec: containers: - name: zaq-containers### 容器的名称 image: nginx ### 创建容器所用的镜像 ports: - containerPort: 80### 应用监听的端口 protocol: TCP

查看所有Pod具有的标签 kubectl get pod --show-labels
查看具有指定标签的Pod kubectl get pod -L env, app
通过命令行为Pod新增标签 kubectl label pod test-pod key1=value1
通过命令行修改Pod原有的标签的值 kubectl label pod test-pod env=debug --overwrite
4.3 标签选择器
单单为Pod创建一个标签并没有什么,他需要和标签选择器配合使用才能展现出强大的威力。标签选择器允许我们选择标记有特定标签的Pod子集,并对这些Pod执行操作。可以把标签选择器当作是我们用来过滤资源的过滤器了。
标签和标签选择器在后面多处都会使用到,到时候也会再做介绍,这里说太多也无法很好的理解,所以就不再赘述。
5、Pod的健康检查机制(Probe探针机制)
引言: 在Kubernetes中有一种自我修复能力。只要将 Pod 调度到某个节点, 该节点上的 Kubelet 就会运行 Pod 的容器,只要该 Pod 存在, 就会保持运行。 如果容器的主进程崩溃, Kubelet 将重启容器。 如果应用程序中有一个导致它每隔一段时间就会崩溃的bug, Kubemetes也会自动重启应用程序, 所以就算应用程序本身没有做任何特殊的处理,只要在Kubemetes 中运行,就能自动获得自我修复的能力。
那么会有一种情况,就算进程没有崩溃,有时一个应用程序也不能正常工作。比如应用发生内存泄漏抛出了OutOfMemoryErrors,但是JVM进程还一直运行。对于这种情况,就不能通过常规的机制判断是否健康,Kubernetes怎么检测这种情况,并重启容器呢?
对于这种问题有一种解决办法就是让应用程序给Kubernetes发送信号,告诉Kubernetes他运行异常并让Kubernetes重启他。但是这种解决办法不能解决所有问题。比如,你的应用因为无限循环或者死锁停止响应。为了保证应用程序在这种情况下也能被重启,必须从外部来检查应用的运行状况,而不是依赖内部检测。
这就引入了Kubernetes的存活探针(liveness probe),它可以用来检测容器是否还在允许。可以为Pod中的每个容器单独指定存货探针。如果探测失败,Kubernetes将定期执行探针并重新启动容器。
5.1 K8s中每个容器都可以都有三种探针
这里将容器中的三种探针拿到一起来了解:
启动探针
启动探针是一个一次性探针。 只要探测启动成功了就不会在探测了
kubelet 使用启动探针,来检测应用是否已经启动完成。(比如有一个大型应用,可能会启动五分钟才算启动,如果只调用了一个docker run是不能认为启动的。对于这些启动时间长的应用就需要有一个启动探针,探测应用什么时候才算真正启动了)如果启动完成就可以进行后续的探测检查。
  • 慢容器一定指定启动探针。如果一直检测到未启动,则会一直在等待启动。
  • 如果提供了启动探针,则所有其他探针都会被 禁用,直到此探针成功为止。如果启动探测失败,kubelet 将杀死容器,而容器依其重启策略进行重启。 如果容器没有提供启动探测,则默认状态为 Success
  • 启动探针成功以后就不用了,剩下存活探针和就绪探针持续运行
存活探针 kubelet 使用存活探针,来检测容器是否正常运行。(有些容器可能产生死锁【应用程序在运行,但是无法继续执行后面的步骤】), 如果检测失败就会重新启动这个容器
  • 对于生产中运行的Pod,一定要定义一个存活探针
  • 如果在容器中运行的是Java应用程序,请确保使用HTTP GET存活探针,而不是启动全新JVM以获取存活信息的Exec探针。任何基于JVM或类似的应用程序也是如此,因为他们的启动过程需要大量的计算资源。
  • 如果容器不提供存活探针, 则默认状态为 Success
  • initialDelaySeconds: 3600(长了导致可能应用一段时间不可用) 5(短了陷入无限启动循环),为此引入启动探针(所以现有的存活探针,才有的启动探针)。
就绪探针 【云原生(K8s|菜鸟学Kubernetes(K8s)系列——(一)关于Pod和Namespace】kubelet 使用就绪探针,来检测容器是否准备好了可以接收客户端的请求(也就是是否能对外提供服务)。当一个Pod内的所有容器都准备好了,才能把这个Pod看作就绪了。
  • 如果容器不提供就绪态探针,则默认状态为 Success
  • 与存活探针不同的是,就绪探针检测,如果容器未通过准备检查,是不会被终止或重新启动的。(这是存活探针和就绪探针之间的重要区别)存活探针通过杀死异常的容器并用新的正常容器代替他们来保持Pod正常工作,而就绪探针确保只有准备好处理请求的Pod才可以接收他们(请求)。
    如图, 如果一个容器的就绪探测失败, 则将该容器从Service负载均衡里面剔除,连接到该服务的客户端不会被重定向到pod,等再次准备就绪才重新添加Pod。 这和pod与服务的标签选择器完全不匹配的效果相同。
    云原生(K8s|菜鸟学Kubernetes(K8s)系列——(一)关于Pod和Namespace
    文章图片

    但是注意:不要用这一特性去实现从Service中移除Pod的功能,如果想要从某个Service中手动添加或删除Pod,请将enabled=true作为标签添加到Pod,以及Service的标签选择器中,当想要从Service中剔除Pod时,删除标签即可。
为什么要有就绪探针?
就绪探针确保客户端只与正常的pod交互, 并且永远不会知道系统存在问题。
如果没有将就绪探针添加到pod 中,它们几乎会立即成为服务端点。 如果应用程序需要很长时间才能开始监听传入连接,则在服务启动但尚未准备好接收传入连接时,客户端请求将被转发到该 pod。 因此,客户端会看到 “连接被拒绝 ” 类型的错误。
实例:
假设有一个订单服务在①号机器部署了一份,在②号机器部署了一份。会在两台机器上分别启动一个Pod,这时StartUp启动探针会探测Pod是否启动起来,如果成功了说明应用已经启动起来了。
应用启动后,可能会出现假死状态,不能提供服务。liveness存活探针会检查Pod在存活过程中是否还正常活着,所以他的检测可能会每隔一段时间去检测一个Pod是否正常活着。
Pod是活着的还不够,还会有Readiness就绪探针检测Pod是否准备就绪。两个Pod上层会由Service来做负载均衡,外部给Service发送请求,Service会将请求负载均衡到Pod①或者Pod②,而负载均衡网络要把请求发给哪个Pod,决定于Pod的就绪探针。如果哪个Pod的就绪探针提示他不能接收请求了,那这个Pod就会从Service的负载均衡网络中剔除,Service不在会给他发送请求。保证线上所有的应用能进行正常服务。
5.2 谁在利用这些探针探测?
  • 答:Kubelet,检测探针状态,重启容器这项任务是由承载Pod的节点上的Kubelet执行的,在Master节点上的Kubenetes Control Plane组件是不会参与此过程的。(Control Plane这一概念会在K8s的运行原理中讲解)
Kubelet检测的全过程:
Pod中会有多个容器,每个容器 都会配置三个探针(StartUp、Liveness、Readiness),这三个探针由Kubelet发起调用。
Kubelet首先会启动Pod,从而启动容器,Kubelet在底层docker run把容器启动起来,如果没有启动探针,只要docker run了kubelet就认为这个容器启动起来了。但是有些容器启动很慢,所以建议配一个启动探针。等容器真正启动完成了,再调用存活探针,不断的打电话问这个容器活着没活着没活着没,只要容器告诉他我活着我活着我活着,Kubelet就不会重启他。如果突然有个容器没反应了(比如三次没反应),这时Kubelet就会认为这个容器炸了,就会重启这个容器。
直到容器一直活着,Kubelet就会调用就绪探针,每隔一段时间问容器有没有就绪,如果就绪,这时候请求流量就能发送到容器。
5.3 三种探针总结
  • 启动探针用来检查应用是否已经启动完成。
  • 存活探针会检查容器是否正常运行,如果不是就会重启他。
  • 就绪探针会检查容器是否能对外提供服务。如果不能,就会在Service负载均衡列表中被移除,客户端的请求就不会被再分配到这个就绪探针检测异常的容器上。
5.4 Kubemetes 对容器探测的三种机制
  • HTTP GET:对容器的 IP 地址(你指定的端口和路径)执行 HTTP GET 请求。
    如果探测器收到响应,并且响应状态码为200到400之间, 则认为探测成功。如果服务器返回错误响应状态码或者根本没有响应,那么探测就被认为是失败的,容器将被重新启动。
  • TCP Socket:TCP套接字探针尝试与容器指定端口建立TCP连接。如果连接成功建立,则探测成功。否则,容器重新启动。
  • Exec:探针在容器内执行任意命令,并检查命令的退出状态码。如果状态码是0, 则探测成功。所有其他状态码都被认为失败。
5.5 每个容器中每种探针Probe的附加功能
  • initialDelaySeconds :延时探测。容器启动后要等待多少秒后,存活和就绪探测器才被初始化,进行探测,默认是 0 秒后,最小值是 0。这是针对以前没有,即Kubelet第一次探测时生效。
    如果没有设置初始延迟,探针将在启动时立即开始探测容器, 这通常会导致探测失败,因为应用程序还没准备好开始接收请求。 如果失败次数超过阈值,在应用程序能正确响应请求之前, 容器就会重启。
    **提示:**务必记得设置一个初始延迟来说明应用程序的启动时间。
  • periodSeconds:执行探测的时间间隔(单位是秒)。默认是 10 秒。最小值是 1。
  • successThreshold:探测器在失败后,被视为探测成功的最小连续成功数。(换句话说:连续几次成功才算成功)默认值是 1。
    • 存活和启动探针的这个值必须是 1。最小值是 1。
  • failureThreshold:当探测失败时,Kubernetes 的重试次数。 (换句话说:连续几次失败才算失败)默认值是 3。最 小值是 1。
    • 存活探测情况下的放弃(失败)就意味着重新启动容器。
    • 就绪探测情况下的放弃(失败),Pod 会被打上未就绪的标签。
  • timeoutSeconds :探测超时。到了超时时间探测还没有返回结果说明失败。默认值是 1 秒。最小值是 1。
  • exechttpGettcpSocket,这三个表示用哪种方式探测
5.6 简单示例
创建一个包含HTTP GET存活探针的新Pod
apiVersion: v1 kind: Pod metadata: labels: test: liveness name: liveness-http spec: containers: - name: liveness image: luksa/kubia-unhealthy### 这是一个测试镜像,在发送第六次请求的时候都会返回一个500异常 livenessProbe: httpGet:### 一个基于HTTP GET机制的存货探针 path: /### HTTP请求的路径 port: 8080### 探针链接的网络端口

该Pod的描述文件定义了一个httpGet存活探针,该探针告诉Kubernetes定期在端口8080路径上执行HTTP GET请求,以确定该容器是否健康。当容器不健康了,K8s会认为探测失败,重启容器。
apiVersion: v1 kind: Pod metadata: labels: test: liveness name: liveness-exec spec: containers: - name: liveness image: busybox args: - /bin/sh - -c - touch /tmp/healthy; sleep 18; rm -rf /tmp/healthy; sleep 600# 创建一个文件;睡30s;文件又删除,睡600秒 livenessProbe: exec: command: - cat - /tmp/healthy initialDelaySeconds: 5#容器启动RUNNING 5秒以后再来探测 periodSeconds: 5 #每隔5秒探测一次

apiVersion: v1 kind: Pod metadata: name: "nginx-start-probe02" namespace: default labels: app: "nginx-start-probe02" spec: volumes: - name: nginx-vol hostPath: path: /app - name: nginx-html hostPath: path: /html containers: - name: nginx image: "nginx" ports: - containerPort: 80volumeMounts: - name: nginx-vol mountPath: /app - name: nginx-html mountPath: /usr/share/nginx/htmlstartupProbe: exec: command: ["/bin/sh","-c","cat /app/abc"] ## 对于Kubectl来说,只要返回不是0,那就是探测失败 # initialDelaySeconds: 20 ## 探测延时,即指定的这个 秒以后才执行探测 periodSeconds: 5 ## 每隔几秒来运行这个探测 timeoutSeconds: 5 ##探测超时,即到了超时时间探测还没返回结果说明失败 successThreshold: 1 ## 成功阈值,连续几次成才算成功 failureThreshold: 3 ## 失败阈值,连续几次失败才算真失败livenessProbe: ## nginx容器有没有 /abc.html,就绪探针 exec: command: ["/bin/sh","-c","cat /usr/share/nginx/html/abc.html"] ## 返回不是0,那就是探测失败 # initialDelaySeconds: 20 ## 指定的这个秒以后才执行探测 periodSeconds: 5 ## 每隔几秒来运行这个 timeoutSeconds: 5 ##探测超时,到了超时时间探测还没返回结果说明失败 successThreshold: 1 ## 成功阈值,连续几次成才算成功 failureThreshold: 3 ## 失败阈值,连续几次失败才算真失败readinessProbe: # #就绪检测,都是http httpGet: # host: 127.0.0.1 ###不行 path: /abc.html ## 给容器发请求 port: 80 scheme: HTTP ## 返回不是0,那就是探测失败 initialDelaySeconds: 2 ## 指定的这个秒以后才执行探测 periodSeconds: 5 ## 每隔几秒来运行这个 timeoutSeconds: 5 ##探测超时,到了超时时间探测还没返回结果说明失败 successThreshold: 3 ## 成功阈值,连续几次成才算成功 failureThreshold: 5 ## 失败阈值,连续几次失败才算真失败

二、关于Namespace(名称空间) 前面提到过通过标签可以将资源进行分组,但是他需要通过标签选择器去选择。在Kubernetes中还有另一种对资源进行分组的方式,就是通过Namespace进行分组。**注意:**这里的Namespace和Docker中提到的基于Linux的Namespace实现资源隔离是不一样的。Kubernetes的Namespace简单地为资源名称提供了一个作用域,我们一定不会将所有的资源都放在同一个命名空间中,而是将她们组织到多个命名空间中,这样就可以允许我们在不同的名称空间中多次使用相同的资源名称。
1、Namespace能做什么? 我们可以通过Namespace将一个包含大量组件的复杂系统拆分为多个不同的组,这些组也可以用于在多租户环境中分配资源,将资源分配为生产、开发和QA环境。
如果有多个用户或用户组正在使用同一个Kubernetes集群,并且他们都各自管理自己独特的资源集合,那么他们就应该分别使用各自的名称空间。这样一来,他们就不用特别担心无意中修改或删除其他用户的资源,也无需关心名称冲突。在不同的用户看来,他们就好像在单独的使用这个Kubernetes集群。
除了隔离资源的作用,Namespace还可以用于仅允许某些用户访问某些特定资源,甚至限制单个用户可用的计算资源数量。后面会详细介绍。
注意,在Kubernetes中还有一些节点资源是不受命名空间的限制的,比如ClusterRole、ClusterRoleBinding等等。
2、Namespace不能做什么? 尽管Namespace将资源分割到不同的组,只允许你对属于特定Namespace的资源进行操作,但实际上Namespace之间并不提供对正在运行的资源的任何隔离。
比如,你可能会认为当不同的用户在不同的Namespace中部署Pod时,这些Pod应该彼此隔离,并且无法通信,但事实却并非如此。Namespace之间是否提供网络隔离取决于Kubernetes所使用的网络解决方案。当该解决方案不提供Namespace间的网络隔离时,那么如果namespaceA中的某个Pod知道namespaceB中Pod的IP地址,这时他就可以将流量发送到另一个Pod中。
3、通过Yaml创建Namespace
apiVersion: v1 kind: Namespace metadata: name: custom-namespace### 指定名称空间的名称

4、通过命令行创建Namespace kubectl create namespace test-ns
未完,待续>>>
参考:Kubernetes in Action

    推荐阅读