K8S 入门实战 (1)
Docker 安装
# 1. 查看机器信息,内核版本要求 3.8 以上 $ uname -a Linux centos8 5.11.12-300.el8.aarch64 #1 SMP Fri Jul 30 12:03:15 CST 2021 aarch64 aarch64 aarch64 GNU/Linux # 2. 关闭 selinux $ setenforce Enforcing $ getenforce Enforcing # 3. 关闭防火墙 $ systemctl stop firewalld # 4. 检查网络,保证系统可以访问外网 $ ping baidu.com 64 bytes from 39.156.66.10 (39.156.66.10): icmp_seq=2 ttl=128 time=40.2 ms # 5. 删除本地源 $ rm /etc/yum.repos.d/local.repo # 6. 下载软件源配置文件 $ curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo # 7. 安装 epel 源 $ yum install epel-release -y # 8. 安装 docker 包 $ yum list docker --show-duplicates $ yum install -y yum-utils $ yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo $ yum list docker-ce --show-duplicates $ sudo yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo # 9. 验证安装结果 $ docker version
- docker version
docker version 会输出 Docker 客户端和服务器各自的版本信息:
[hamming@centos8 ~]$ docker version # docker 客户端信息 Client: Docker Engine - Community Version: 20.10.18 API version: 1.41 Go version: go1.18.6 Git commit: b40c2f6 Built: Thu Sep 8 23:10:56 2022 OS/Arch: linux/arm64 Context: default Experimental: true # docker 引擎信息 Server: Docker Engine - Community Engine: Version: 20.10.18 API version: 1.41 (minimum version 1.12) Go version: go1.18.6 Git commit: e42327a Built: Thu Sep 8 23:09:25 2022 OS/Arch: linux/arm64 Experimental: false containerd: Version: 1.6.8 GitCommit: 9cd3357b7fd7218e4aec3eae239db1f68a5a6ec6 runc: Version: 1.1.4 GitCommit: v1.1.4-0-g5fd4c4d docker-init: Version: 0.19.0 GitCommit: de40ad0
- docker info
docker info 会显示当前 Docker 系统相关的信息,例如 CPU、内存、容器数量、镜像数量、容器运行时、存储文件系统等等。
Client: Context: default Debug Mode: false Plugins: app: Docker App (Docker Inc., v0.9.1-beta3) buildx: Docker Buildx (Docker Inc., v0.9.1-docker) compose: Docker Compose (Docker Inc., v2.10.2) Server: Containers: 0 # 容器信息 Running: 0 Paused: 0 Stopped: 0 Images: 0 Server Version: 20.10.18 Storage Driver: overlay2 # 存储文件系统 Backing Filesystem: xfs Supports d_type: true Native Overlay Diff: true userxattr: false Logging Driver: json-file Cgroup Driver: systemd Cgroup Version: 1 Plugins: Volume: local Network: bridge host ipvlan macvlan null overlay Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog Swarm: inactive Runtimes: io.containerd.runtime.v1.linux runc io.containerd.runc.v2 Default Runtime: runc Init Binary: docker-init containerd version: 9cd3357b7fd7218e4aec3eae239db1f68a5a6ec6 runc version: v1.1.4-0-g5fd4c4d init version: de40ad0 Security Options: seccomp Profile: default Kernel Version: 5.11.12-300.el8.aarch64 # 内核 Operating System: CentOS Linux 8 # 操作系统 OSType: linux Architecture: aarch64 # 系统架构 CPUs: 2 # 核数 Total Memory: 1.419GiB # 内存 Name: centos8 ID: MQ5W:UARY:J7LZ:QZPC:B63Z:4XW5:IUJQ:U63U:JXJD:VNGJ:7HW6:P5DD Docker Root Dir: /data/docker Debug Mode: false Registry: https://index.docker.io/v1/ Labels: Experimental: false Insecure Registries: registry.access.redhat.com quay.io 127.0.0.0/8 Registry Mirrors: https://q2gr04ke.mirror.aliyuncs.com/ Live Restore Enabled: true
容器常用命令
# 查看容器,-a 参数可以查看已退出的容器 $ docker ps [-a] # 运行容器 $ docker run hello-world # 运行简单的 docker 容器 $ docker run -d nginx:alpine # 后台运行Nginx $ docker run -d --name red_srv redis # 后台运行 Redis $ docker run -it --name ubuntu 2e6 sh # 使用IMAGE ID,登录 Ubuntu18.04 # 在指定容器中执行命令 $ docker exec -it red_srv sh # 停止容器运行 $ docker stop red_srv # 开启容器运行 $ docker start red_srv # 删除容器 $ docker rm red_srv # 拷贝文件 # 将 host.txt 文件拷贝到容器中的 tmp 文件夹下面 $ docker cp host.txt 062:/tmp # 将容器内的 container.txt 文件拷贝到本机 $ docker cp 062:/tmp/container.txt ./container.txt # 目录挂载 # 将本机目录 /tmp 挂在到容器目录 /tmp $ docker run -d --rm -v /tmp(host):/tmp(container) redis
docker 内部角色和工作流程
docker 实际上是一个客户端 client ,它会与 Docker Engine 里的后台服务 Docker daemon 通信,而镜像存储在远端的仓库 Registry 里,客户端并不能直接访问镜像仓库。Docker client 通过 build、pull、run等命令向 Docker daemon 发送请求,而 Docker daemon 则是容器和镜像的“大管家”,负责从远端拉取镜像、在本地存储镜像,还有从镜像生成容器、管理容器等所有功能。
与虚拟机的区别
容器和虚拟机的目的都是隔离资源,保证系统安全,然后是尽量提高资源的利用率。
虚拟机创建的时候会在物理机虚拟化出一套完整的计算机硬件,在里面还能够安装任意的操作系统,这内外两个系统也同样是完全隔离,互不干扰。
而在数据中心的服务器上,虚拟机软件(即图中的 Hypervisor)同样可以把一台物理服务器虚拟成多台逻辑服务器,这些逻辑服务器彼此独立,可以按需分隔物理服务器的资源,为不同的用户所使用。
从实现的角度来看,虚拟机虚拟化出来的是硬件,需要在上面再安装一个操作系统后才能够运行应用程序,而硬件虚拟化和操作系统都比较“重”,会消耗大量的 CPU、内存、硬盘等系统资源,但这些消耗其实并没有带来什么价值,属于“重复劳动”和“无用功”,不过好处就是隔离程度非常高,每个虚拟机之间可以做到完全无干扰。
容器(即图中的 Docker),直接利用了下层的计算机硬件和操作系统,因为比虚拟机少了一层,所以自然就会节约 CPU 和内存,显得非常轻量级,能够更高效地利用硬件资源。不过,因为多个容器共用操作系统内核,应用程序的隔离程度就没有虚拟机那么高了。
运行效率是容器相比于虚拟机最大的优势,对比图中可以看到,同样的系统资源,虚拟机只能跑 3 个应用,其他的资源都用来支持虚拟机运行了,而容器则能够把这部分资源释放出来,同时运行 6 个应用。
docker 镜像的本质
从功能上来说,docker 镜像和其他安装包一样,都打包了应用程序。不同的地方在于,docker 镜像包含了程序运行的所有环境配置。使得其具有很好的跨平台便携性和兼容性,做到一次编写,到处运行。
- 镜像的内部机制
容器镜像内部并不是一个平坦的结构,而是由许多的镜像层组成,当你在执行 docker pull 命令的时候,Docker 会检查是否有从重复的层,如果本地已经存在就不会重复下载,以此节约磁盘和网络成本。
- 以 nginx:alpine 镜像为例
[hamming@centos8 ~]$ docker pull nginx:alpine alpine: Pulling from library/nginx 9b3977197b4f: Pull complete 11e00b6b0b40: Pull complete 45812000e2a5: Pull complete 2e3e03d70957: Pull complete bb56ce0340f0: Pull complete a313facfd18d: Pull complete # 说明这个镜像一共有 6 层 Digest: sha256:eb05700fe7baa6890b74278e39b66b2ed1326831f9ec3ed4bdc6361a4ac2f333 Status: Downloaded newer image for nginx:alpine docker.io/library/nginx:alpine # 查看镜像信息 [hamming@centos8 ~]$ docker inspect nginx:alpine
Docker Hub
Docker Hub 是 Docker 公司搭建的官方 Registry 服务,和 GitHub 一样,几乎成为了容器世界的基础设施。
- 如何在 Docker Hub 上面挑选镜像
-
带有
Official image
标记的镜像,表示镜像经过了 Docker 公司的认证,有专门的团队负责审核、发布和更新,质量上绝对可以放心。 -
带有
Verified publisher
标记,是认证发行商发布的自己打包的镜像,大厂质量也值得信赖。 -
非官方镜像一种是企业官方发布上去的虽然没有经过 Docker 认证(如 openResty)但是可以放心使用,另一种就是存粹的个人上传上去的,质量上没有保证。
在选择 docker 镜像的时候,除了需要参考以上几点,下载量、星数、还有更新历史,也是选择的一个一个重要参考指标,通常可以采用随大流的方法,选择下载数最多的那个镜像。
镜像增删改查
# 拉取镜像,镜像完整名字由名字和标签组成 $ docker pull busybox:1.21-alpine # 查看 docker 中存储的所有镜像 $ docker images # 删除镜像 $ dcoker rmi busybox
线上上传自己的镜像
-
在 Docker Hub 上注册一个用户;
-
本机上使用 docker login 命令,用刚才注册的用户名和密码认证身份登录;
-
使用 docker tag 命令,给镜像改成带用户名的完整名字,表示镜像是属于这个用户的。或者简单一点,直接用 docker build -t 在创建镜像的时候就起好名字。
$ docker tag hello-world canghaimingue/hello-world:1.0 $ docker push canghaimingue/hello-world:1.0
离线环境保存自己的镜像
Docker 提供了 save 和 load 这两个镜像归档命令,可以把镜像导出成压缩包,或者从压缩包导入 Docker,而压缩包是非常容易保管和传输的,可以联机拷贝,FTP 共享,甚至存在 U 盘上随身携带。
# 把容器按照自己的需求个性完之后,就可以创建自己的镜像的 # docker commit 容器id 镜像名称:版本号 $ docker commit 07388cf54586 hello-world:1.0 # 保存镜像文件 #docker save 镜像名称:版本号 -o 压缩文件名称 $ docker save hello-world:1.0 -o hello_world.tar # 加载镜像文件 $ docker load -i hello_world.tar
Docker 网络模式
Docker 有 bridge、none、host、container 四种网络模式,提供网络隔离、端口映射、容器间互通网络等各种支持。
网络模式 | 参数 | 备注 |
---|---|---|
host | --net=host | 容器和宿主机共享 network namespace。 |
container | --net= | 容器和另外一个容器共享 network namespace,K8S 中的 pod 就是多个容器共享一个 network namespace。 |
none | --net=none | 容器有独立的 network namespace,但没有对其进行任何网络设置,如分配 veth pair 和网桥连接,配置 IP 等。 |
bridge | --net=bridage | 默认为该模式,通过 -p 指定端口映射。 |
- host
连接到 host 网络的容器会共享宿主机的网络栈,容器内的网络配置与宿主机一致。直接使用host网络好处就是性能,如果容器对网络有较高要求可以直接使用host网络。但是:使用host网络也会牺牲灵活性,host已经使用的端口容器中将无法使用。
- container
创建的容器和已经存在的一个容器共享一个Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过lo网卡设备通信。
$ docker run -itd --network=container:busybox --name busybox_container busybox # 查看两个容器状态 $ docker ps | grep busybox c0131db3ccb3 busybox "sh" 3 hours ago Up 3 hours busybox_container 1283b0f92e91 busybox "sh" 8 hours ago Up 8 hours busybox
查看两个容器的网络配置,发现他们共用的同一个 ip
- none
挂载这个网络下的容器仅有lo网络,没有其他网卡,也就不能与外界通信,适合对安全性要求较高且不需要联网的容器。如下所示
- bridge
默认网络,运行容器时如果不指定网络类型就会使用 bridge 网络。
$ docker run -itd --name busybox busybox $ docker inspect busybox # 查看容器信息,下图可以看到网络模式 bridge
执行命令 ifconfig
可以看到网络设备中多了一个 veth7d0ac61
,这是 busybox 的虚拟网卡。
$ bridge link show | grep docker0 9: veth0f1803c@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master docker0 state forwarding priority 32 cost 2 17: veth2884210@if16: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master docker0 state forwarding priority 32 cost 2 19: veth7d0ac61@if18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master docker0 state forwarding priority 32 cost 2
通过上面的命令可以看到, 这个虚拟网络设备挂在 docker0。我们再看看 busybox 内部的网络设备。
$ docker exec -it busybox ip l 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 18: eth0@if19: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether 02:42:ac:07:05:04 brd ff:ff:ff:ff:ff:ff
实际上, eth0@if19
和 veth7d0ac61@if18
是一对 veto pair 设备,在虚拟网络中充当着桥梁的角色,实现容器件的网络通行。
Dockerfile 的编写
关键字 | 作用 | 备注 |
---|---|---|
FROM | 指定基础镜像 | 指定 dockerfile 基于那个 image 构建 |
MAINTAINER | 作者信息 | 用来标明这个 dockerfile 谁写的 |
LABEL | 标签 | 用来标明 dockerfile 的标签 可以使用 Label 代替 Maintainer 最终都是在 docker image 基本信息中可以查看 |
RUN | 执行命令 | 执行一段命令 默认是 /bin/sh 格式: RUN command 或者 RUN ["command" , "param1","param2"] |
CMD | 容器启动命令 | 提供启动容器时候的默认命令 和 ENTRYPOINT 配合使用.格式 CMD command param1 param2 或者 CMD ["command" , "param1","param2"],只能有一个,有多个的时候最后一个生效。 |
ENTRYPOINT | 入口 | 一般在制作一些执行就关闭的容器中会使用 |
COPY | 复制文件 | build 的时候复制文件到 image 中 |
ADD | 添加文件 | build 的时候添加文件到 image 中 不仅仅局限于当前build上下文 可以来源于远程服务 |
ENV | 环境变量 | 指定 build 时候的环境变量 可以在启动的容器的时候 通过-e覆盖 格式 ENV name=value |
ARG | 构建参数 | 构建参数 只在构建的时候使用的参数 如果有ENV 那么ENV的相同名字的值始终覆盖 arg 的参数 |
VOLUME | 定义外部可以挂载的数据卷 | 指定build的image那些目录可以启动的时候挂载到文件系统中 启动容器的时候使用 -v 绑定 格式 VOLUME ["目录"] |
EXPOSE | 暴露端口 | 定义容器运行的时候监听的端口 启动容器的使用-p来绑定暴露端口 格式: EXPOSE 8080 或者 EXPOSE 8080/udp |
WORKDIR | 工作目录 | 指定容器内部的工作目录 如果没有创建则自动创建 如果指定/ 使用的是绝对地址 如果不是/开头那么是在上一条workdir的路径的相对路径 |
USER | 指定执行用户 | 指定build或者启动的时候 用户 在RUN CMD ENTRYPONT执行的时候的用户 |
HEALTHCHECK | 健康检查 | 指定监测当前容器的健康监测的命令 基本上没用 因为很多时候 应用本身有健康监测机制 |
ONBUILD | 触发器 | 当存在ONBUILD关键字的镜像作为基础镜像的时候 当执行FROM完成之后 会执行 ONBUILD的命令 但是不影响当前镜像 用处也不怎么大 |
STOPSIGNAL | 发送信号量到宿主机 | 该STOPSIGNAL指令设置将发送到容器的系统调用信号以退出。 |
SHELL | 指定执行脚本的shell | 指定RUN CMD ENTRYPOINT 执行命令的时候 使用的shell |
- Dockerfile 样例
# base image FROM centos:7 # MAINTAINER MAINTAINER frost <example@163.com> # put nginx-1.12.2.tar.gz into /usr/local/src and unpack nginx ADD nginx-1.12.2.tar.gz /usr/local/src # install utils RUN yum install -y gcc gcc-c++ glibc make autoconf openssl openssl-devel RUN yum install -y libxslt-devel -y gd gd-devel GeoIP GeoIP-devel pcre pcre-devel RUN useradd -M -s /sbin/nologin nginx # change dir to /usr/local/src/nginx-1.12.2 WORKDIR /usr/local/src/nginx-1.12.2 # execute command to compile nginx RUN ./configure --user=nginx --group=nginx --prefix=/usr/local/nginx \ --with-file-aio --with-http_ssl_module --with-http_realip_module \ --with-http_addition_module --with-http_xslt_module \ --with-http_image_filter_module --with-http_geoip_module \ --with-http_sub_module --with-http_dav_module --with-http_flv_module \ --with-http_mp4_module --with-http_gunzip_module \ --with-http_gzip_static_module --with-http_auth_request_module \ --with-http_random_index_module --with-http_secure_link_module \ --with-http_degradation_module --with-http_stub_status_module && make && make install ENV PATH /usr/local/nginx/sbin:$PATH EXPOSE 80 ENTRYPOINT ["nginx"] CMD ["-g","daemon off;"]
报错问题及解决
问题1:docker 容器修改时间 date -s 报错 date: cannot set date: Operation not permitted
# 原因:在容器中没有操作权限,在容器启动时授权即可 # 解决: $ docker stop 5cf4eb29c8ed # 停止容器 $ docker run -itd --privileged=true -p 8080:80 nginx:latest # 重新启动,授权
问题2:更新 docker 软件失败(apt update 报错)
E: Release file for http://security.debian.org/debian-security/dists/bullseye-security/InRelease is not valid yet (invalid for another 19h 21min 31s). Updates for this repository will not be applied.
# 原因:网络和本机系统时间不一致,所以导致无法更新源 # 解决:更新一下 docker 时间即可 $ tzselect 依次选择4->9->1->1 #Asia->China-> Beijing->yes $ sudo date -s MM/DD/YY //修改日期 $ sudo date -s hh:mm:ss //修改时间 $ sudo hwclock --systohc //修改生效
问题3:无法连接到 docker daemon
# 原因:我的是 docker 没有设置开机自启动 $ systemctl enable docker $ systemctl start docker $ vi /etc/docker/daemon.json # 配置参数参考官方文档 { "graph": "/data/docker", "storage-driver": "overlay2", "insecure-registries": ["registry.access.redhat.com","quay.io"], "registry-mirrors": ["https://q2gr04ke.mirror.aliyuncs.com"], "bip": "172.7.5.1/24", "exec-opts": ["native.cgroupdriver=systemd"], "live-restore": true } # 重启docker让配置生效 $ systemctl reset-failed docker.service $ systemctl start docker.service $ systemctl restart docker # 如果失败了,systemctl status docker查看报错信息 $ docker info # 场景二:https://blog.csdn.net/m0_38088330/article/details/125343432
参考资料
-
Docker in Action
-
Kubernetes 入门实战
-
https://blog.csdn.net/weixin_41831919/article/details/102767618
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统