0
点赞
收藏
分享

微信扫一扫

k8s-pod-共享资源的容器组合

这篇文章讲解的容器运行时是docker,containerd有些许不一样

pod里的所有容器,共享的是同一个Network Namespace,并且可以声明共享同一个Volume。

​1.infra容器

在k8s项目中,Pod只是一个逻辑概念,在具体实现上,还是通过yaml来创建container。

在一个pod中可以创建多个容器,上面说了,pod中的多个容器是共享同一个Network Namespace的,并且pod中定义的多个容器是相同级别的,那多个容器的创建没有先后之分,是怎样共用Network Namespace的呢??

这里就是通过infra中间容器,这个容器永远都是第一个被创建

k8s-pod-共享资源的容器组合_pod


1.1infra容器介绍

infra容器占用很少的资源:所以它使用一个特殊的镜像:k8s.gcr.io/pause,阿里云上创建的容器,使用的镜像是:registry.aliyuncs.com/google_containers/pause:3.1,这个镜像永远处于“暂停”状态。

infra容器第一个被创建:pod中定义的容器与infra容器使用相同的network namespace

即,对于pod中的A、B容器来说:

1.两个容器网络互通,可以使用localhost通信。

2.infra容器和A、B容器的网络设备相同。

3.一个pod只有一个Ip,即是这个共同的Network Namespace的Ip地址。

4.pod的生命周期只和infra容器一致,与A 、B 容器无关。

5.pod中流量的进出,可以认为是通过Infra容器完成的。所以开发网络插件时,只需要考虑如何配置这多个容器共享的network namespace

1.2pod中包含多个容器演示案例

1.准备pod yaml

apiVersion: v1
kind: Pod
metadata:
name: two-containers
spec:
nodeName: testops #这里我只在这个节点上测试,所以写了一个固定的节点
containers:
- name: blue-pod-container
image: busybox:1.31.1
command: ["sleep"]
args: ["10000"]
- name: green-pod-container
image: busybox:1.30.1
command: ["sleep"]
args: ["10000"]

2.查看该pod创建的容器

[root@testops ~]# docker ps -a|grep two-containers
50088eed88a7 busybox "sleep 10000" 5 seconds ago Up 4 seconds k8s_green-pod-container_two-containers_default_51ed090c-5852-425c-8903-60bc88758ba1_0
a2882bdb45aa busybox "sleep 10000" 12 seconds ago Up 11 seconds k8s_blue-pod-container_two-containers_default_51ed090c-5852-425c-8903-60bc88758ba1_0
72ad9f8e2891 registry.aliyuncs.com/google_containers/pause:3.1 "/pause" 19 seconds ago Up 18 seconds k8s_POD_two-containers_default_51ed090c-5852-425c-8903-60bc88758ba1_0

3.查看每个容器的pid和network namespace

测试发现,以下三个namespace相同。

lrwxrwxrwx 1 root root 0 Jan 27 22:25 ipc -> ipc:[4026535040]

lrwxrwxrwx 1 root root 0 Jan 27 22:25 net -> net:[4026535043]

lrwxrwxrwx 1 root root 0 Jan 27 22:26 user -> user:[4026531837]

[root@testops ~]# docker inspect --format '{{ .State.Pid }}' 50088eed88a7
2983
[root@testops ~]# docker inspect --format '{{ .State.Pid }}' a2882bdb45aa
2314
[root@testops ~]# docker inspect --format '{{ .State.Pid }}' 72ad9f8e2891
1729
[root@testops ~]# ll /proc/2983/ns/
total 0
lrwxrwxrwx 1 root root 0 Jan 27 22:26 cgroup -> cgroup:[4026531835]
lrwxrwxrwx 1 root root 0 Jan 27 22:25 ipc -> ipc:[4026535040]
lrwxrwxrwx 1 root root 0 Jan 27 22:25 mnt -> mnt:[4026535121]
lrwxrwxrwx 1 root root 0 Jan 27 22:25 net -> net:[4026535043]
lrwxrwxrwx 1 root root 0 Jan 27 22:25 pid -> pid:[4026535123]
lrwxrwxrwx 1 root root 0 Jan 27 22:26 pid_for_children -> pid:[4026535123]
lrwxrwxrwx 1 root root 0 Jan 27 22:26 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Jan 27 22:25 uts -> uts:[4026535122]
[root@testops ~]# ll /proc/2314/ns/
total 0
lrwxrwxrwx 1 root root 0 Jan 27 22:26 cgroup -> cgroup:[4026531835]
lrwxrwxrwx 1 root root 0 Jan 27 22:25 ipc -> ipc:[4026535040]
lrwxrwxrwx 1 root root 0 Jan 27 22:25 mnt -> mnt:[4026535117]
lrwxrwxrwx 1 root root 0 Jan 27 22:25 net -> net:[4026535043]
lrwxrwxrwx 1 root root 0 Jan 27 22:25 pid -> pid:[4026535120]
lrwxrwxrwx 1 root root 0 Jan 27 22:26 pid_for_children -> pid:[4026535120]
lrwxrwxrwx 1 root root 0 Jan 27 22:26 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Jan 27 22:25 uts -> uts:[4026535118]
[root@testops ~]# ll /proc/1729/ns/
total 0
lrwxrwxrwx 1 root root 0 Jan 27 22:26 cgroup -> cgroup:[4026531835]
lrwxrwxrwx 1 root root 0 Jan 27 22:25 ipc -> ipc:[4026535040]
lrwxrwxrwx 1 root root 0 Jan 27 22:25 mnt -> mnt:[4026535038]
lrwxrwxrwx 1 root root 0 Jan 27 22:25 net -> net:[4026535043]
lrwxrwxrwx 1 root root 0 Jan 27 22:25 pid -> pid:[4026535041]
lrwxrwxrwx 1 root root 0 Jan 27 22:26 pid_for_children -> pid:[4026535041]
lrwxrwxrwx 1 root root 0 Jan 27 22:26 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Jan 27 22:25 uts -> uts:[4026535039]
[root@testops ~]#

2.pod介绍

2.1特殊字段介绍

2.2.1hostAliases设置/etc/hosts文件

在k8s中,如果要设置hosts文件,一定要通过这种方式,否则pod删除重建后,会覆盖掉被修改的内容。

---
apiVersion: v1
kind: Pod
metadata:
name: two-containers
spec:
hostAliases:
- ip: "10.1.2.3"
hostnames:
- "foo.remote"
- "bar.remote"
nodeName: testops-k8s03-worker01
containers:
- name: blue-pod-container
image: busybox:1.31.1
command: ["sleep"]
args: ["10000"]

查看/etc/hosts文件内容

✘ dz0400819@MacBook-Pro  ~/.kube  kubectl exec -it two-containers /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # cat /etc/hosts
# Kubernetes-managed hosts file.
127.0.0.1 localhost
172.29.1.52 two-containers

# Entries added by HostAliases.
10.1.2.3 foo.remote bar.remote
/ #

2.2.2pod lifecycle字段

podtsStart:容器启动后,立刻执行的操作。

postStart的执行是异步的,postStart 定义的操作,虽然是在 Docker 容器 ENTRYPOINT 执行之后,但它并不严格保证顺序。也就是说,在 postStart 启动时,ENTRYPOINT 有可能还没有结束。

preStop:在容器被杀死之前(如:收到SIGKILL信号)。

preStop的执行是同步的,所以会先执行preStop中的操作,操作完成后才会杀死容器。

在这个例子中,在容器被杀死之前,先调用nginx退出命令来实现nginx的优雅推出。

apiVersion: v1
kind: Pod
metadata:
name: lifecycle-demo
spec:
containers:
- name: lifecycle-demo-container
image: nginx
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]
preStop:
exec:
command: ["/usr/sbin/nginx","-s","quit"]

注意:

上面说到了sigKill信号,这里多介绍一下删除pod的过程。

删除pod -> 执行preStop -> done收到KiLL信号 -> server端优雅终止 -> 删除pod

package main

import (
"context"
"flag"
"fmt"
"io"
"math/rand"
"net/http"
_ "net/http/pprof"
"os"
"os/signal"
"strings"
"syscall"
"time"

"github.com/golang/glog"
)

func main() {
flag.Set("v", "4")
glog.V(2).Info("Starting service0")

mux := http.NewServeMux()
mux.HandleFunc("/", healthz)

srv := http.Server{
Addr: ":80",
Handler: mux,
}
done := make(chan os.Signal, 1)
//用于接收Kill信号
signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)

go func() {
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
glog.Fatalf("listen: %s\n", err)
}
}()
glog.Info("Server Started")
<-done
glog.Info("Server Stopped")
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer func() {
// extra handling here
cancel()
}()

if err := srv.Shutdown(ctx); err != nil {
glog.Fatalf("Server Shutdown Failed:%+v", err)
}
glog.Info("Server Exited Properly")
}

func healthz(w http.ResponseWriter, r *http.Request) {
for k, v := range r.Header {
io.WriteString(w, fmt.Sprintf("%s=%s\n", k, v))
}

io.WriteString(w, "ok\n")
}

2.3pod Status介绍

k8s-pod-共享资源的容器组合_podlifeCycle_02

k8s-pod-共享资源的容器组合_podlifeCycle_03

k8s-pod-共享资源的容器组合_podlifeCycle_04


举报

相关推荐

0 条评论