这篇文章讲解的容器运行时是docker,containerd有些许不一样
pod里的所有容器,共享的是同一个Network Namespace,并且可以声明共享同一个Volume。
1.infra容器
在k8s项目中,Pod只是一个逻辑概念,在具体实现上,还是通过yaml来创建container。
在一个pod中可以创建多个容器,上面说了,pod中的多个容器是共享同一个Network Namespace的,并且pod中定义的多个容器是相同级别的,那多个容器的创建没有先后之分,是怎样共用Network Namespace的呢??
这里就是通过infra中间容器,这个容器永远都是第一个被创建。

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
apiVersionv1
kindPod
metadata
  nametwo-containers
spec
  nodeNametestops #这里我只在这个节点上测试,所以写了一个固定的节点
  containers
nameblue-pod-container
      imagebusybox1.31.1
      command"sleep"
      args"10000"
namegreen-pod-container
      imagebusybox1.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_03.查看每个容器的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删除重建后,会覆盖掉被修改的内容。
---
apiVersionv1
kindPod
metadata
  nametwo-containers
spec
  hostAliases
ip"10.1.2.3"
      hostnames
"foo.remote"
"bar.remote"
  nodeNametestops-k8s03-worker01
  containers
nameblue-pod-container
      imagebusybox1.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的优雅推出。
apiVersionv1
kindPod
metadata
  namelifecycle-demo
spec
  containers
namelifecycle-demo-container
      imagenginx
      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介绍













