最近学习K8S,从编程角度来看docker以及K8S中Pod中一些原理,总结一下。
水平有限,错误之处欢迎指正。

1. 环境

  • 操作系统ubuntu 22
  • k8s环境minikube v1.26.1 (脚本见https://blog.csdn.net/LeoForBest/article/details/126524892
  • node节点信息
  • 安装好Go(sudo apt install golang
NAMESTATUSROLESIPVERSION
minikubeReadycontrol-plane,master192.168.49.2v1.23.8
minikube-m02Readynone192.168.49.3v1.23.8

2. 从Linux进程角度看Docker

2.1 观测工具源码

保存main.go 和 dockerfile ,编译出测试程序和Docker镜像

2.1.1 main.go

package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
)

func main() {
	hostname, _ := os.Hostname()
	fmt.Println("程序看到的主机名是: ", hostname)
	fmt.Println("程序看到的文件系统是:")
	files, _ := ioutil.ReadDir("/")
	for _, f := range files {
		fmt.Printf("/%-10s\t%s\t%d字节\n", f.Name(), f.ModTime().Format("2006-01-02 15:04:05"), f.Size())
	}
	out, _ := exec.Command("ps", "-e", "-o", "pid,ppid,user,comm").Output()
	fmt.Println("程序看到的进程是:")
	fmt.Println(string(out))
	out, _ = exec.Command("ip", "addr").Output()
	fmt.Println("程序看到的网络是:")
	fmt.Println(string(out))
}

2.1.2 Dockerfile

# docker build -t leo/show-info
FROM busybox:latest

# 先在本机编译生成show-info程序
# GOOS=linux GOARCH=i386 go build -ldflags '-s -w'
COPY ./show-info / 
CMD /show-info
# 容器进程结果
docker run --rm -it leo/show-info
# 本机进程结果
./show-info

2.2 查看本机进程和Docker容器进程中观察结果

容器技术主要利用到内核两个特性namespace(隔离进程PID、文件系统、网络、用户、主机名等)和cgroup(限制CPU、内存、IO资源)
具体细节暂不关注,从应用程序方面来看,Docker容器进程中看到的进程PID文件系统网络主机名用户等不一致

在这里插入图片描述在这里插入图片描述

3. Kubernetes Pod 和 Docker容器关系

官方定义https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/

Pod 是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元。
Pod(就像在鲸鱼荚或者豌豆荚中)是一组(一个或多个) 容器; 这些容器共享存储、网络、以及怎样运行这些容器的声明。 Pod 中的内容总是并置(colocated)的并且一同调度,在共享的上下文中运行。 Pod 所建模的是特定于应用的 “逻辑主机”,其中包含一个或多个应用容器, 这些容器相对紧密地耦合在一起。 在非云环境中,在相同的物理机或虚拟机上运行的应用类似于在同一逻辑主机上运行的云应用。

pause容器先不用深究

3.1 Pod中容器共享相同网络

# 文件名 busybox.yaml
# kubect apply -f busybox.yaml
apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    name: busybox
spec:
  containers:
  - name: busybox
    image: busybox
    command: ["sh", "-c", "echo running on minikube && sleep 36000"]
  # 指定在minikube node上运行,后续ssh到这台机器查看
  nodeSelector:
    "kubernetes.io/hostname": minikube
  # 挂载临时卷
  volumes:
    - name: cache-volume
      emptyDir: {}

操作步骤

kubect apply -f busybox.yaml
# 1. 登录minikube节点
minikube ssh -n minikube
# 2. 查看这个pod下所有容器
docker ps --filter 'Label=io.kubernetes.pod.name=busybox' --format 'table\t{{.ID}}\t{{.Image}}\t{{.Command}}'
# 3. 获取pod容器进程在主机中的Pid
for i in $(docker ps --filter 'Label=io.kubernetes.pod.name=busybox' -q); do docker inspect $i --format '{{.State.Pid}}'; done
# 4. 对比同一个Pod下各个Namespace不同之处
sudo ls -l /proc/5402/ns/
sudo ls -l /proc/5327/ns/

同一个 Pod 中的容器共享资源(挂载的卷)、网络环境(不是所有的namespace都共享)

在这里插入图片描述

3.2 Pod中容器共享相同的存储

# 修改一下,改为多个容器
# 文件名 busybox.yaml
# kubect delete pod busybox
# kubect apply -f busybox.yaml
apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    name: busybox
spec:
  containers:
    - name: busybox
      image: busybox
      command: ["sh", "-c", "echo running on minikube && sleep 36000"]
      volumeMounts:
        - mountPath: /cache
          name: cache-volume
    - name: busybox2
      image: busybox
      command: ["sh", "-c", "echo running on minikube && sleep 36000"]
      volumeMounts:
        - mountPath: /cache
          name: cache-volume
  # 指定在minikube node上运行,后续ssh到这台机器查看
  nodeSelector:
    "kubernetes.io/hostname": minikube
  volumes:
    - name: cache-volume
      emptyDir: {}

操作步骤

# 0. 回到本机重新搭建测试环境
kubect delete pod busybox
kubect apply -f busybox.yaml
# 1. 登录minikube节点
minikube ssh -n minikube
# 2.验证busybox中容器挂载的卷
for i in $(docker ps --filter 'Label=io.kubernetes.pod.name=busybox' -q); do docker inspect $i --format '{{json .Mounts}}'; done

Pod中容器共享相同的存储

在这里插入图片描述

3.3 Pod中其他概念

TODO: 围绕Pod,还有很多概念需要学习实践,如

  • 调度与控制器
  • 配置管理
  • 健康可用性检查
  • 升级回滚
  • 暴露为服务
  • 挂载存储
Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐