写在前面,好久没写博客了,,,,买了一月五号的机票,要开始新的旅程了。微信动态都想好了,“北京の友達、あなた達の彼女に気を付けてくださいね。俺、超ハンサムな日天様来ました。”大概这个亚子。。。
在BB下pod
容器被设计为每个容器只运行一个进程(除非进程本身产生子进程)。由于不能将多个进程聚集在一个单独的容器中,我们需要一种更高级的结构来将容器绑定在一起,并将它们作为一个单元进行管理,这就是pod背后的根本原理。此时这些进程就好像全部运行于单个容器中一样,同时又保持着一定隔离。(就是说,一个容器只能运行一个进程,来一个pod,一个pod中有多个容器,把一个pod看成一个大的容器,那么就能的得到一个容器里运行多个进程的亚子)
容器之间彼此是完全隔离的,我们期望隔离容器组,而不是单个容器,并让每个容器组内的容器共享一些资源,而不是全部(换句话,就是没有完全隔离)k8s通过配置Docker来让一个pod内的所有容器共享相同的Linux命名空间,而不是每个容器都有自己的一组命名空间。
但当涉及文件系统时,情况就有所不同,由于大多数容器的文件系统来自容器镜像,因此默认情况下,每个容器的文件系统与其他容器完全隔离。
容器共享相同的IP和端口空间(同一pod中的容器之间可以相互通信)
由于一个pod中的容器运行于相同的Network命名空间中,因此它们共享相同的IP地址和端口空间。这意味着在同一个pod中的容器运行多个进程需要注意不能绑定到相同的端口号,否则会导致端口冲突,但这只涉及同一pod中的容器。此外,一个pod中的所有容器也都具有相同的loopback网络接口,因此容器可以通过localhost与同一pod中的其他容器进行通信。(总结就是,一个pod中有多个进程时,注意要绑定不同的端口,否则会发生端口冲突。同一个pod中的容器可以相互通信)
不同的pod可以通过IP地址通信
k8s集群中所有的pod都在同一个共享网络地址空间中,这意味着每个pod都可以通过其他pod的IP地址来实现相互访问。换句话说,这也表示它们之间没有NAT(网络地址转换)网关。
因此,pod之间的通信其实非常简单,不论是将两个pod安排在单一的还是不同的工作节点上,同时不管实际节点间的网络拓扑结构如何,这些pod内的容器动能够像在无NAT的平坦网络中一样相互通信。
通过pod合理管理容器
我们应该将 应用程序组织到多个pod中,而每个pod只包含紧密相关的组件或程序。虽然我们可以在单个pod中同时运行前端服务器和数据库这两个容器,但这种方式并不推荐。另一个不应该应用程序都放到单一pod中的原因就是扩缩容。pod也是扩缩容的基本单位。对于k8s来说,它不能横向扩容,只能扩缩整个pod。这意味着如果你的pod由一个前端和一个后端容器组成,那么当你扩大pod的实例数量时,比如扩大为两个,最终会得到两个前端容器和两个后端容器。
将多个容器添加到单个pod的主要原因时应用可能由一个主进程和一个或多个辅助进程组成。如下。
决定何时在pod中使用多个容器
- 它们需要一起运行还是可以在不同的主机上运行?
- 它们代表的是一个整体还是相互独立的组件?
- 它们必须一起进行扩容还是可以分别进行?
基本上,我们总是应该倾向于在单独的pod中运行容器,除非由特定的原因要求它们是同一pod的一部分。
以YAML描述文件创建pod
kubectl get po kubia-xxxx -o ymal 获取pod整个YMAL定义
获取的是pod完整的ymal文件,里面有很多是k8s自己加的。
主要包括
- metadata 包含名称、命名空间、标签和关于该容器的其他信息
- spec包含pod内容的实际说明,例如pod容器、卷和其他数据。
- status包含运行中的pod的当前信息,例如pod所处的条件,每个容器的描述和状态,以及内部IP和其他基本信息。
自己为pod创建个简单的YAML描述文件
kubia-manual.yaml
apiVersion: v1 # 描述文件遵循v1版本的k8s API
kind: Pod # 描述一个pod
metadata:
name: kubia-manual # pod的名称
spec:
containers:
- image: luksa/kubia # 创建容器所用的镜像
name: kubia # 容器的名字
ports:
- containerPort: 8080 # 应用监听的端口
protocol: TCP
kubectl create -f kubia-manual.yaml 创建pod,-指定文件,kubectl 不只是能创建pod, 也可以创建其他资源
kubectl get po kubia-manual -o yaml -o 查看完整的pod描述文件
kubectl get pods 查看创建pod列表
kubectl explain pods 描述pods
kubectl explain pod.spec 常看pod的指定描述
查看应用程序日志
docker logs <container id> 查看容器日志
kubectl logs kubia-manual 查看pod的日志,kubia-manual是pod的名字,而且这个pod里只有一个容器
kubectl logs kubia-manual -c kubia 如果pod中有多个容器,要-c 后面加指定的容器
要注意的是,我们只能获取仍然存在的pod的日志,当一个pod被删除时,它的日志也会被删除。
向pod发送请求
下面只是一种方法,不通过service的情况下与某个特定的pod进行通信。
kubectl port-forward kubia-manual 8888:8000 将机器的本地端口8888转发到我们的pod的8080,所以直接访问8888端口就行了
使用标签组织pod
标签是一种简单却功能强大的k8s特性,不仅可以组织pod, 也可以组织所有其他的k8s资源。详细来讲,标签是可以附加到资源的任意键值对,用以选择具有该确切标签的资源(通过标签选择器完成的)。只要标签的key在资源内是唯一的,一个资源便可以拥有多个标签,
具有标签的yaml文件
kubia-manual-with-labels.yaml
apiVersion: v1
kind: Pod
metadata:
name: kubia-manual-v2
labels: # 两个标签,被附加到pod上
creation_method: manual
env: prod
spec:
containers:
- image: luksa/kubia
name: kubia
ports:
- containerPort: 8000
protocol: TCP
kubectl create -f kubia-manual-with-labels,yaml 创建pod
kubectl get po --show-labels 显示pod的标签
kubectl get po -L creation_method,env 显示指定的标签
给现有的pod添加或修改标签
kubectl label po kubia-manual create_method=manual 给pod加标签
kubectl label po kubia-manual-v2 env=debug --overwrite 修改标签, 注意要加--overwrite
通过标签选择器列出pod子集
- 包含(或不包含)使用的特定键的标签
- 包含具有特定键和中的标签
- 包含具有特定键的标签,但其值与我们指定的不同
注意:
kubectl get po -L creation_method,env , 这两个参数L和l 是不同的。L是这样指定标签的键,l是标签选择器。
kubectl get po -l creation_method=manual 选择指定标签和值
kubetcl get po -l env 当然也可以选择指定键
kubectl get po -l '!env' 选择键不是env的标签,注意是单引号
- creation_metod != manual 选择带有creation_method标签,并且值不等于manual的值
- env in (prod, devel) 选择带有env标签且值为prod或devel的pod
- env notin (prod, devel) 选择带有env的标签,值不是prod的pod
例子 选择多个标签:
选择器: app=pc,rel=bata
将pod调度到特定的节点
首先给节点加个标签
kubectl label node xxxnode的名字 gpu=true 给xxx节点加个gpu=true 的节点
kubectl get nodes -l gpu=true 使用标签选择器,选择指定的标签
下面就是正经的了,通过yaml指定pod运行在哪个节点。
apiVersion: v1
kind: Pod
metadata:
name: kubia-gpu
spec:
nodeSelector: # 指定标签选择器
gpu: "true"
containers:
- image: luksa/kubia
name: kubia
注解pod
为了查看注解,我们需要获取pod的完整YAML文件或使用kubectl describe命令
kubectl get po kubia-xxx -o ymal
看annotations:的部分
添加和修改注解
kubectl annotate pod kubia-manual mycompany.com/someannotation="foo bar" 添加注释
kubectl describe pod kubia-manual 查看注释
命名空间
资源名称只需在命名空间内保持唯一即可,因此两个不同的命名空间可以包含同名资源。
列出所有命名空间
kubectl get ns 列出所有命名空间
kubectl get po --namespace kubia-system 列出指定命名空间的pod
kubectl get po -n kubia-system 同上
创建命名空间
注意命名空间的命名方式:只能包含字母数字横杠(-),,,,不能有(.)
①通过yaml创建命名空间
apiVersion: v1
kind: Namespace # 定义一个命名空间
metadata:
name: custom-namespace # 指定命名空间的名字
kubectl create -f custom-namespace.yaml
②通过kubectl create namespace 命令 创建命名空间
kubectl create namespace custom-namespace
管理命名空间中的对象
如果想要在刚创建的命名空间中创建资源,可以选择在metadata字段中添加一个namespace: custom-namespace属性,也可以在使用kubectl create 命令时指定命名空间
kubectl create -f kubia-manual.yaml -n custom-namespace -n 指定命名空间
在列出、描述、修改或删除其他命名空间中的对象时,需要给kubectl 命令传递--namespace(或-n)选项。如果不指定命名空间,kubectl将在当前上下文中配置的默认命名空间中执行操作。而当前上下文的命名空间和当前上下文本身都可以通过kubectl config进行更改。
命名空间提供的隔离
尽管命名空间将对象分隔到不同的组,只允许你对属于特定命名空间的对象进行操作,但实际上命名空间之间并不提供对正在运行的对象的任何隔离。
你可能会认为但不同的用户在不同的命名空间中部署pod时,这些pod应该彼此隔离,并且无法通信,当事实并非如此。命名空间之间是否提供网络隔离取决于k8s所使用的网络解决方案。
停止和移除pod
① 按名称删除pod
kubectl delete po kubia-gpu
kubectl delete pod1 pod2
在删除pod的过程中,实际上我们在指示k8s终止该pod中的所有容器。k8s向进程发送一个SIGTERM信号并等待一定秒数(默认30秒),使其正常关闭。如果它没有及时关闭,则通过SIGKILL终止该进程。因此,为了确保你的进程总是正常关闭,进程需要正确处理SIGTERM信号。
② 使用标签选择器删除pod
kubectl delete po -l creation_method=manual
③ 通过删除整个命名空间来删除pod
可以简单地删除整个命名空间(pod将会伴随命名空间自动删除)
kubectl delete na custon-namespace 删除命名空间,里面的pod也随之删除
④删除命名空间中的所有pod,但保留命名空间
kubectl delete po --all
但是,当运行
kubectl get pods 会发现还有可能有pod在运行
这可能因为这个pod是ReplicationController创建的,ReplicationController检测到pod少了,及自动在启动指定的pod。所以删了也白删。所以要先删除ReplicationController。
⑤删除命名空间中的(几乎)所有资源
kubectl delete all --all
命令的第一个all指定在删除所有资源类,而--all 选项指定所有资源实例。
以上です。