K8S 入门实战 (1)

362 阅读3分钟

image-20221001221005496.png

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 内部角色和工作流程

c8116066bdbf295a7c9fc25b87755dfe.jpg

docker 实际上是一个客户端 client ,它会与 Docker Engine 里的后台服务 Docker daemon 通信,而镜像存储在远端的仓库 Registry 里,客户端并不能直接访问镜像仓库。Docker client 通过 build、pull、run等命令向 Docker daemon 发送请求,而 Docker daemon 则是容器和镜像的“大管家”,负责从远端拉取镜像、在本地存储镜像,还有从镜像生成容器、管理容器等所有功能。

与虚拟机的区别

b734f7d91bda055236b3467bc16f6302.jpg

容器和虚拟机的目的都是隔离资源,保证系统安全,然后是尽量提高资源的利用率。

虚拟机创建的时候会在物理机虚拟化出一套完整的计算机硬件,在里面还能够安装任意的操作系统,这内外两个系统也同样是完全隔离,互不干扰。

而在数据中心的服务器上,虚拟机软件(即图中的 Hypervisor)同样可以把一台物理服务器虚拟成多台逻辑服务器,这些逻辑服务器彼此独立,可以按需分隔物理服务器的资源,为不同的用户所使用。

从实现的角度来看,虚拟机虚拟化出来的是硬件,需要在上面再安装一个操作系统后才能够运行应用程序,而硬件虚拟化和操作系统都比较“重”,会消耗大量的 CPU、内存、硬盘等系统资源,但这些消耗其实并没有带来什么价值,属于“重复劳动”和“无用功”,不过好处就是隔离程度非常高,每个虚拟机之间可以做到完全无干扰。

容器(即图中的 Docker),直接利用了下层的计算机硬件和操作系统,因为比虚拟机少了一层,所以自然就会节约 CPU 和内存,显得非常轻量级,能够更高效地利用硬件资源。不过,因为多个容器共用操作系统内核,应用程序的隔离程度就没有虚拟机那么高了。

运行效率是容器相比于虚拟机最大的优势,对比图中可以看到,同样的系统资源,虚拟机只能跑 3 个应用,其他的资源都用来支持虚拟机运行了,而容器则能够把这部分资源释放出来,同时运行 6 个应用。

docker 镜像的本质

从功能上来说,docker 镜像和其他安装包一样,都打包了应用程序。不同的地方在于,docker 镜像包含了程序运行的所有环境配置。使得其具有很好的跨平台便携性和兼容性,做到一次编写,到处运行。

  • 镜像的内部机制

容器镜像内部并不是一个平坦的结构,而是由许多的镜像层组成,当你在执行 docker pull 命令的时候,Docker 会检查是否有从重复的层,如果本地已经存在就不会重复下载,以此节约磁盘和网络成本。

b734f7d91bda055236b3467bc16f6302.jpg

  • 以 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

image-20220929221437253.png

Docker Hub

Docker Hub 是 Docker 公司搭建的官方 Registry 服务,和 GitHub 一样,几乎成为了容器世界的基础设施。

  • 如何在 Docker Hub 上面挑选镜像
  1. 带有 Official image 标记的镜像,表示镜像经过了 Docker 公司的认证,有专门的团队负责审核、发布和更新,质量上绝对可以放心。

  2. 带有 Verified publisher 标记,是认证发行商发布的自己打包的镜像,大厂质量也值得信赖。

  3. 非官方镜像一种是企业官方发布上去的虽然没有经过 Docker 认证(如 openResty)但是可以放心使用,另一种就是存粹的个人上传上去的,质量上没有保证。

在选择 docker 镜像的时候,除了需要参考以上几点,下载量、星数、还有更新历史,也是选择的一个一个重要参考指标,通常可以采用随大流的方法,选择下载数最多的那个镜像。

109fc664da4f5124c4758b0e8f9c95f3.png

576d07439fc85d2bc461953f31a084f2.png

镜像增删改查
# 拉取镜像,镜像完整名字由名字和标签组成
 $ docker pull busybox:1.21-alpine
 
 # 查看 docker 中存储的所有镜像
 $ docker images
 
 # 删除镜像
 $ dcoker rmi busybox
线上上传自己的镜像
  1. 在 Docker Hub 上注册一个用户;

  2. 本机上使用 docker login 命令,用刚才注册的用户名和密码认证身份登录;

  3. 使用 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={id}容器和另外一个容器共享 network namespace,K8S 中的 pod 就是多个容器共享一个 network namespace。
none--net=none容器有独立的 network namespace,但没有对其进行任何网络设置,如分配 veth pair  和网桥连接,配置 IP 等。
bridge--net=bridage默认为该模式,通过 -p 指定端口映射。
  • host

连接到 host 网络的容器会共享宿主机的网络栈,容器内的网络配置与宿主机一致。直接使用host网络好处就是性能,如果容器对网络有较高要求可以直接使用host网络。但是:使用host网络也会牺牲灵活性,host已经使用的端口容器中将无法使用。

image.png

  • 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网络,没有其他网卡,也就不能与外界通信,适合对安全性要求较高且不需要联网的容器。如下所示

image-20221001110521581.png

  • 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@if19veth7d0ac61@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 security.debian.org/debian-secu… 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
参考资料

关注公众号一起学习——无涯的计算机笔记