最近学习K8S,从编程角度来看docker以及K8S中Pod中一些原理,总结一下。
水平有限,错误之处欢迎指正。
ubuntu 22
minikube v1.26.1
(脚本见https://blog.csdn.net/LeoForBest/article/details/126524892
)sudo apt install golang
)NAME | STATUS | ROLES | IP | VERSION |
---|---|---|---|---|
minikube | Ready | control-plane,master | 192.168.49.2 | v1.23.8 |
minikube-m02 | Ready | none | 192.168.49.3 | v1.23.8 |
保存main.go 和 dockerfile ,编译出测试程序和Docker镜像
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))
}
# 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
容器技术主要利用到内核两个特性
namespace
(隔离进程PID、文件系统、网络、用户、主机名等)和cgroup
(限制CPU、内存、IO资源)
具体细节暂不关注,从应用程序方面来看,Docker容器进程中看到的进程PID
、文件系统
、网络
、主机名
、用户
等不一致
官方定义
https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/
Pod 是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元。
Pod(就像在鲸鱼荚或者豌豆荚中)是一组(一个或多个) 容器; 这些容器共享存储、网络、以及怎样运行这些容器的声明。 Pod 中的内容总是并置(colocated)的并且一同调度,在共享的上下文中运行。 Pod 所建模的是特定于应用的 “逻辑主机”,其中包含一个或多个应用容器, 这些容器相对紧密地耦合在一起。 在非云环境中,在相同的物理机或虚拟机上运行的应用类似于在同一逻辑主机上运行的云应用。
pause容器先不用深究
# 文件名 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都共享)
# 修改一下,改为多个容器
# 文件名 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中容器共享相同的存储
TODO: 围绕Pod,还有很多概念需要学习实践,如