分类 Linux 下的文章

linux进程突然挂了,怎么找原因

  1. 查看日志,systemctl status
  2. 检查网络情况
  3. top检查内存等信息情况,看看是不是oom
  4. dmesg查看内核信息
  5. lsblk,查看是不是硬件挂了

暂时就想到这么多

概念

docker与虚拟机的区别

avatar

虚拟机

基础设施(Infrastructure)。它可以是你的个人电脑,数据中心的服务器,或者是云主机。

主操作系统(Host Operating System)。你的个人电脑之上,运行的可能是MacOS,Windows或者某个Linux发行版。

虚拟机管理系统(Hypervisor)。利用Hypervisor,可以在主操作系统之上运行多个不同的从操作系统。类型1的Hypervisor有支持MacOS的HyperKit,支持Windows的Hyper-V以及支持Linux的KVM。类型2的Hypervisor有VirtualBox和VMWare。

从操作系统(Guest Operating System)。假设你需要运行3个相互隔离的应用,则需要使用Hypervisor启动3个从操作系统,也就是3个虚拟机。这些虚拟机都非常大,也许有700MB,这就意味着它们将占用2.1GB的磁盘空间。更糟糕的是,它们还会消耗很多CPU和内存。

各种依赖。每一个从操作系统都需要安装许多依赖。如果你的的应用需要连接PostgreSQL的话,则需要安装libpq-dev;如果你使用Ruby的话,应该需要安装gems;如果使用其他编程语言,比如Python或者Node.js,都会需要安装对应的依赖库。

应用。安装依赖之后,就可以在各个从操作系统分别运行应用了,这样各个应用就是相互隔离的。

docker

主操作系统(Host Operating System)。所有主流的Linux发行版都可以运行Docker。对于MacOS和Windows,也有一些办法"运行"Docker。

Docker守护进程(Docker Daemon)。Docker守护进程取代了Hypervisor,它是运行在操作系统之上的后台进程,负责管理Docker容器。

各种依赖。对于Docker,应用的所有依赖都打包在Docker镜像中,Docker容器是基于Docker镜像创建的。

应用。应用的源代码与它的依赖都打包在Docker镜像中,不同的应用需要不同的Docker镜像。不同的应用运行在不同的Docker容器中,它们是相互隔离的。

区别

虚拟机实现资源的隔离的方式是利用独立的Guest OS,以及利用Hypervisor虚拟化CPU、内存、IO等设备来实现的,Docker不需要Hypervisor实现硬件资源的虚拟化,他利用Namespace 实现了系统环境的隔离,利用了cgroup实现了资源的限制,利用镜像实例实现跟环境的隔离。

Linux namespace技术

namespce是linux的底层概念,在内核层实现,每个docker容器运行在一个docker主进程并且共用一个宿主机内核,各自运行在宿主机的用户空间,彼此之间采用一定的措施互相隔离,以保证自己或宿主机内核不受其他进程的干扰。namespace就是实现隔离的措施。所以运行在Docker容器上的程序,直接使用的都是实际物理机的硬件资源。因此在cpu、内存、利用率上,Docker将会在效率上具有更大的优势。docker启动都是秒级,且兼容性强。

namaspcace一共有6种
avatar

MNT

每个容器都有独立的文件系统挂载点,在创建了一个新的mount namespace后,进程系统对文件系统的挂在/写在动作就不会影响到别的namespace

实验

#拉取两个centos镜像
[root@server1 ~]# docker run -d centos:7 ping baidu.com
5c101d7baa31692d63c4036b0570fa8a2dab1d9a4884e4ee65a410de2e23b631

[root@server1 ~]# docker run -d centos:7 ping baidu.com
3edc6c7e7ed70cfc9dbc9605636aa68c47afaff5cfce2ff8de4a93e5199ca310
[root@server1 ~]# docker ps
CONTAINER ID   IMAGE      COMMAND            CREATED          STATUS          PORTS     NAMES
3edc6c7e7ed7   centos:7   "ping baidu.com"   3 seconds ago    Up 2 seconds              crazy_galileo
5c101d7baa31   centos:7   "ping baidu.com"   19 seconds ago   Up 16 seconds             pedantic_moore

登入两个镜像,各自准备一份一模一样的文件
[root@server1 ~]# docker exec -it 3 bash
[root@3edc6c7e7ed7 /]# pwd
/
[root@3edc6c7e7ed7 /]# whoami
root
[root@3edc6c7e7ed7 /]# cd
[root@3edc6c7e7ed7 ~]# ll
total 4
-rw-------. 1 root root 3416 Nov 13  2020 anaconda-ks.cfg
[root@3edc6c7e7ed7 ~]# echo "this is server1" > 123.txt
[root@3edc6c7e7ed7 ~]# ll
total 8
-rw-r--r--. 1 root root   16 Mar 18 03:09 123.txt
-rw-------. 1 root root 3416 Nov 13  2020 anaconda-ks.cfg
[root@3edc6c7e7ed7 ~]# exit
exit
[root@server1 ~]# docker exec -it 5 bash
[root@5c101d7baa31 /]# cd
[root@5c101d7baa31 ~]# echo "this is server2" > 123.txt
[root@5c101d7baa31 ~]# exit
exit


在宿主机寻找文件,diff存放的是差分文件,merged下存放的是运行时的存储文件,docker使用chroot技术把容器锁定到一个指定的运行目录里
[root@server1 ~]# find / -name "123.txt"
/var/lib/docker/overlay2/c1429f6c6bdeb99d56f1710f29a4d705fbaab27f6a7a20e74849cfc5da9fb17e/diff/root/123.txt
/var/lib/docker/overlay2/c1429f6c6bdeb99d56f1710f29a4d705fbaab27f6a7a20e74849cfc5da9fb17e/merged/root/123.txt
/var/lib/docker/overlay2/0ec5a01a65be3e401a09d19d5684c73636738914311a98c126c391bfc6256b49/diff/root/123.txt
/var/lib/docker/overlay2/0ec5a01a65be3e401a09d19d5684c73636738914311a98c126c391bfc6256b49/merged/root/123.txt

[root@server1 ~]# cat /var/lib/docker/overlay2/c1429f6c6bdeb99d56f1710f29a4d705fbaab27f6a7a20e74849cfc5da9fb17e/diff/root/123.txt
this is server2
[root@server1 ~]# cat /var/lib/docker/overlay2/c1429f6c6bdeb99d56f1710f29a4d705fbaab27f6a7a20e74849cfc5da9fb17e/merged/root/123.txt
this is server2
[root@server1 ~]# cat /var/lib/docker/overlay2/0ec5a01a65be3e401a09d19d5684c73636738914311a98c126c391bfc6256b49/diff/root/123.txt
this is server1
[root@server1 ~]# cat /var/lib/docker/overlay2/0ec5a01a65be3e401a09d19d5684c73636738914311a98c126c391bfc6256b49/merged/root/123.txt
this is server1

IPC

IPC隔离的是进程间的通信,其会用标识符表示不同的消息队列,进程间通过找到标识符对应的消息队列来完成通信,IPC namespace做的事情就是相同的标识符在不同namespace上对应不同的消息队列,这样不同namespace的进程无法完成进程间通信。

UTS

UTS Namespace用于对主机名和域名进行隔离,它使得一个容器拥有属于自己hostname标识,这个主机名标识独立于宿主机系统和其上的其他容器。

PID

PID用于隔离进程号,每个容器内部有一个父进程来管理下属进程,当创建一个PID Namespace时,其第一个进程PID号在容器内部会被映射为1,当这个进程不是前台进程的时候容器会直接停止,用docker ps找不到刚开的容器可能是这个原因。你可以在宿主机用pkill或者kill杀死对应容器的containerd-shim进程,相关容器也能被直接杀死

[root@server1 ~]# yum install psmisc.x86_64 -y

[root@server1 ~]# pstree -p
systemd(1)─┬─NetworkManager(6349)─┬─dhclient(6428)
           │                      ├─{NetworkManager}(6398)
           │                      └─{NetworkManager}(6400)
           ├─agetty(6383)
           ├─auditd(5770)───{auditd}(5771)
           ├─chronyd(6385)
           ├─containerd(6660)─┬─{containerd}(6705)
           │                  ├─{containerd}(6706)
           │                  ├─{containerd}(6707)
           │                  ├─{containerd}(6708)
           │                  ├─{containerd}(6709)
           │                  ├─{containerd}(6751)
           │                  ├─{containerd}(6752)
           │                  └─{containerd}(6754)
           ├─containerd-shim(7552)─┬─ping(7571)
           │                       ├─{containerd-shim}(7554)
           │                       ├─{containerd-shim}(7555)
           │                       ├─{containerd-shim}(7556)
           │                       ├─{containerd-shim}(7557)
           │                       ├─{containerd-shim}(7558)
           │                       ├─{containerd-shim}(7559)
           │                       ├─{containerd-shim}(7560)
           │                       ├─{containerd-shim}(7561)
           │                       ├─{containerd-shim}(7596)
           │                       └─{containerd-shim}(7696)
           ├─containerd-shim(7642)─┬─ping(7663)
           │                       ├─{containerd-shim}(7643)
           │                       ├─{containerd-shim}(7644)
           │                       ├─{containerd-shim}(7645)
           │                       ├─{containerd-shim}(7646)
           │                       ├─{containerd-shim}(7647)
           │                       ├─{containerd-shim}(7648)
           │                       ├─{containerd-shim}(7649)
           │                       ├─{containerd-shim}(7651)
           │                       ├─{containerd-shim}(7683)
           │                       └─{containerd-shim}(7698)
           ├─crond(6366)
           ├─dbus-daemon(6232)───{dbus-daemon}(6348)
           ├─dockerd(6755)─┬─{dockerd}(6831)
           │               ├─{dockerd}(6834)
           │               ├─{dockerd}(6835)
           │               ├─{dockerd}(6836)
           │               ├─{dockerd}(6837)
           │               ├─{dockerd}(6915)
           │               ├─{dockerd}(6916)
           │               ├─{dockerd}(7543)
           │               └─{dockerd}(7590)
           ├─irqbalance(6228)
           ├─lvmetad(3167)
           ├─master(6748)─┬─pickup(7426)
           │              └─qmgr(6750)
           ├─polkitd(6350)─┬─{polkitd}(6393)
           │               ├─{polkitd}(6394)
           │               ├─{polkitd}(6395)
           │               ├─{polkitd}(6396)
           │               ├─{polkitd}(6397)
           │               └─{polkitd}(6402)
           ├─rsyslogd(6649)─┬─{rsyslogd}(7143)
           │                └─{rsyslogd}(7146)
           ├─sshd(6651)─┬─sshd(7474)───bash(7480)───pstree(9856)
           │            └─sshd(7478)───sftp-server(7499)
           ├─systemd-journal(3148)
           ├─systemd-logind(6231)
           ├─systemd-udevd(3185)
           └─tuned(6652)─┬─{tuned}(6917)
                         ├─{tuned}(6918)
                         ├─{tuned}(6919)
                         └─{tuned}(6932)

User

User用于隔离用户资源,一个进程在namespace里的用户和组id与它在host里的id不一样,一个host的普通用户可以在该容器下拥有root权限,但是他的特权被限定在这个容器内

docker0网络

Network

network用于隔离网络资源,每一个容器都类似于虚拟机一样有自己的网卡、监听端口、TCP/IP协议栈等,Docker使用networknamespace启动一个vethX接口,这样容器将拥有它自己的桥接IP地址,通常是docker0,而docker0实质就是linux的虚拟网桥

实操

镜像加速

https://cr.console.aliyun.com/cn-hangzhou/instances

avatar

安装部署

安装docker-ce和客户端

yum install wget.x86_64 -y
rm -rf /etc/yum.repos.d/*
wget -O /etc/yum.repos.d/Centos-7.repo http://mirrors.aliyun.com/repo/Centos-7.repo
wget -O /etc/yum.repos.d/epel-7.repo http://mirrors.aliyun.com/repo/epel-7.repo
wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum install docker-ce -y

启动

[root@server1 ~]# systemctl start docker.service
[root@server1 ~]# systemctl enable docker.service
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.

快速案例(nginx)

[root@server1 ~]# docker pull nginx #拉取镜像
Using default tag: latest
latest: Pulling from library/nginx
f7a1c6dad281: Pull complete
4d3e1d15534c: Pull complete
9ebb164bd1d8: Pull complete
59baa8b00c3c: Pull complete
a41ae70ab6b4: Pull complete
e3908122b958: Pull complete
Digest: sha256:9ddd8cf6d01f497638130950769e279e0b669cd07d11e2bbc4ffead528c9e6e2
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest

[root@server1 ~]# docker images #查看现有的镜像
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
nginx        latest    c919045c4c2b   2 weeks ago   142MB
(TAG如不在下载时指定默认为lastest)
[root@server1 ~]# docker run -d -p 80:80 nginx
639cb466a53c05eac9eea4786a446be8504834288988bde30b8e1201306c6a65
# -d后台运行容器并且返回容器ID,-p端口映射

[root@server1 ~]# docker ps #查看当前正在运行的镜像
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                               NAMES
#镜像id         使用的镜像    启动容器运行的命令    创建时间        状态            映射                                容器名  
639cb466a53c   nginx     "/docker-entrypoint.…"   5 minutes ago   Up 5 minutes   0.0.0.0:80->80/tcp, :::80->80/tcp   fervent_clarke

[root@server1 ~]# docker exec -it 639cb466a53c bash #进入这个docker并创建个bash
root@639cb466a53c:/#
root@639cb466a53c:/# exit
exit

[root@server1 ~]# curl 192.168.226.148
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

docker stop 

[root@server1 ~]# docker stop 639cb466a53c # 暂停镜像
639cb466a53c
[root@server1 ~]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

[root@server1 ~]# docker ps -a #显示全部镜像
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS                      PORTS     NAMES
639cb466a53c   nginx     "/docker-entrypoint.…"   17 minutes ago   Exited (0) 29 seconds ago             fervent_clarke
[root@server1 ~]# docker rm 639cb466a53c  #删除
639cb466a53c
[root@server1 ~]# docker ps -a  
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
[root@server1 ~]#

docker信息

[root@server1 ~]# docker info
Client:
 Context:    default
 Debug Mode: false
 Plugins:
  app: Docker App (Docker Inc., v0.9.1-beta3)
  buildx: Docker Buildx (Docker Inc., v0.8.0-docker)
  scan: Docker Scan (Docker Inc., v0.17.0)

Server:
 Containers: 1 #当前容器总数
  Running: 0   #运行种
  Paused: 0    #暂停
  Stopped: 1   #停止
 Images: 2      #镜像数
 Server Version: 20.10.13   #服务器版本
 Storage Driver: overlay2   #存储引擎
  Backing Filesystem: xfs   #后端文件系统
  Supports d_type: true     #是否支持d_type
  Native Overlay Diff: true #是否支持差异数据存储
  userxattr: false
 Logging Driver: json-file  #日志文件类型
 Cgroup Driver: cgroupfs    #cgroup类型
 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      #runtime
 Init Binary: docker-init   #初始化容器的守护进程
 containerd version: 2a1d4dbdb2a1030dc5b01e96fb110a9d9f150ecc
 runc version: v1.0.3-0-gf46b6ba
 init version: de40ad0
 Security Options:          #安全选项
  seccomp
   Profile: default
 Kernel Version: 3.10.0-957.el7.x86_64  #宿主机内核版本
 Operating System: CentOS Linux 7 (Core)    #宿主机操作系统
 OSType: linux                          #宿主机操作系统类型
 Architecture: x86_64                   #宿主机架构
 CPUs: 2                                #宿主机cpu数量
 Total Memory: 972.6MiB                 #宿主机总内存
 Name: server1                          #宿主机名
 ID: SEVK:M4YS:NEBL:SFRQ:72OS:5JDD:HC6Z:NUMM:7MIC:2B3D:KS3Z:4H4G
 Docker Root Dir: /var/lib/docker       #宿主机数据保存目录
 Debug Mode: false
 Registry: https://index.docker.io/v1/  #仓库镜像
 Labels:
 Experimental: false
 Insecure Registries:
  127.0.0.0/8
 Registry Mirrors:
  https://afh2ckya.mirror.aliyuncs.com/ #镜像加速
 Live Restore Enabled: false

WARNING: bridge-nf-call-iptables is disabled
WARNING: bridge-nf-call-ip6tables is disabled

docker目前的默认存储引擎为overlay2,不同存储引擎需要相应的系统支持

https://www.cnblogs.com/youruncloud/p/5736718.html

镜像管理

下载

docker search 镜像名  #搜索镜像
docker pull name:tag  #下载镜像:描述标签,不写默认latest

查看信息


[root@server1 ~]# docker images #列出所有镜像
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
nginx        latest    c919045c4c2b   2 weeks ago    142MB
centos       7         eeb6ee3f44bd   6 months ago   204MB

docker inspect:查看镜像详细信息

[root@server1 ~]# docker inspect centos:1
[
    {
        "Id": "sha256:eeb6ee3f44bd0b5103bb561b4c16bcb82328cfe5809ab675bb17ab3a16c517c9",
        "RepoTags": [
            "centos:1",
            "centos:7"
        ],
        "RepoDigests": [
            "centos@sha256:9d4bcbbb213dfd745b58be38b13b996ebb5ac315fe75711bd618426a630e0987"
        ],
        "Parent": "",
        "Comment": "",
        "Created": "2021-09-15T18:20:23.99863383Z",
        "Container": "5e4c7bfd35862166e9efd7532208300600114f0acff8f82fd537a57bdd523fe2",
        "ContainerConfig": {
            "Hostname": "5e4c7bfd3586",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "#(nop) ",
                "CMD [\"/bin/bash\"]"
            ],
            "Image": "sha256:ba35a4b787c8f11e3b6ed9248c7663b4f27459e9715a1ace09f966259d5ebc3a",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {
                "org.label-schema.build-date": "20201113",
                "org.label-schema.license": "GPLv2",
                "org.label-schema.name": "CentOS Base Image",
                "org.label-schema.schema-version": "1.0",
                "org.label-schema.vendor": "CentOS",
                "org.opencontainers.image.created": "2020-11-13 00:00:00+00:00",
                "org.opencontainers.image.licenses": "GPL-2.0-only",
                "org.opencontainers.image.title": "CentOS Base Image",
                "org.opencontainers.image.vendor": "CentOS"
            }
        },
        "DockerVersion": "20.10.7",
        "Author": "",
        "Config": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/bash"
            ],
            "Image": "sha256:ba35a4b787c8f11e3b6ed9248c7663b4f27459e9715a1ace09f966259d5ebc3a",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {
                "org.label-schema.build-date": "20201113",
                "org.label-schema.license": "GPLv2",
                "org.label-schema.name": "CentOS Base Image",
                "org.label-schema.schema-version": "1.0",
                "org.label-schema.vendor": "CentOS",
                "org.opencontainers.image.created": "2020-11-13 00:00:00+00:00",
                "org.opencontainers.image.licenses": "GPL-2.0-only",
                "org.opencontainers.image.title": "CentOS Base Image",
                "org.opencontainers.image.vendor": "CentOS"
            }
        },
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 203936249,
        "VirtualSize": 203936249,
        "GraphDriver": {
            "Data": {
                "MergedDir": "/var/lib/docker/overlay2/97a00fcfa569398caaea92950c9c34355e757312c712ea042258ecb394873135/merged",
                "UpperDir": "/var/lib/docker/overlay2/97a00fcfa569398caaea92950c9c34355e757312c712ea042258ecb394873135/diff",
                "WorkDir": "/var/lib/docker/overlay2/97a00fcfa569398caaea92950c9c34355e757312c712ea042258ecb394873135/work"
            },
            "Name": "overlay2"
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:174f5685490326fc0a1c0f5570b8663732189b327007e47ff13d2ca59673db02"
            ]
        },
        "Metadata": {
            "LastTagTime": "2022-03-18T20:43:29.8170514+08:00"
        }
    }
]

docker history:查看各层的创建信息

[root@server1 ~]# docker history centos:1
IMAGE          CREATED        CREATED BY                                      SIZE      COMMENT
eeb6ee3f44bd   6 months ago   /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B
<missing>      6 months ago   /bin/sh -c #(nop)  LABEL org.label-schema.sc…   0B
<missing>      6 months ago   /bin/sh -c #(nop) ADD file:b3ebbe8bd304723d4…   204MB

删除镜像

[root@server1 ~]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
nginx         latest    c919045c4c2b   2 weeks ago    142MB
hello-world   latest    feb5d9fea6a5   5 months ago   13.3kB
centos        7         eeb6ee3f44bd   6 months ago   204MB

[root@server1 ~]# docker rmi feb5d9fea6a5
Untagged: hello-world:latest
Untagged: hello-world@sha256:2498fce14358aa50ead0cc6c19990fc6ff866ce72aeb5546e1d59caac3d0d60f
Deleted: sha256:feb5d9fea6a5e9606aa995e879d862b825965ba48de054caab5ef356dc6b3412
Deleted: sha256:e07ee1baac5fae6a26f30cabfe54a36d3402f96afda318fe0a96cec4ca393359
[root@server1 ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
nginx        latest    c919045c4c2b   2 weeks ago    142MB
centos       7         eeb6ee3f44bd   6 months ago   204MB

修改镜像标签


[root@server1 ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
nginx        latest    c919045c4c2b   2 weeks ago    142MB
centos       7         eeb6ee3f44bd   6 months ago   204MB
[root@server1 ~]# docker tag centos:7 centos:1
[root@server1 ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
nginx        latest    c919045c4c2b   2 weeks ago    142MB
centos       1         eeb6ee3f44bd   6 months ago   204MB
centos       7         eeb6ee3f44bd   6 months ago   204MB

镜像导入导出

可以把本地的镜像导出为一个压缩文件,复制到其他服务器导入使用

导出
docker save 镜像:标签 > /path/name.tar.gz

导入
docker load < /path/name.tar.gz

容器管理

docker create

create创建了一个容器但是不启动他,如果想要启动还需要docker start,语法同run

docker run

选项说明
-d后台运行容器
-i保持标准输入打开
-t分配一个终端,常和i一起用
-p指定端口映射
-P通过NAT随机端口映射
-rm容器退出后就自动删除,不能和-d同时使用
-name别名
-h指定容器内的主机名
-e指定容器内的环境变量
-cpu-shares允许使用cpu的相对权重,默认一个容器能用满一个核
-cpuset-cpus限制容器能使用哪些cpu核心
-m限制容器使用的内存

启动一个容器

[root@server1 ~]# docker run -it centos:1 #创建个终端并使用
[root@2bf2fab97e80 /]# exit
exit

[root@server1 ~]# docker ps -a
CONTAINER ID   IMAGE      COMMAND       CREATED          STATUS                     PORTS     NAMES
2bf2fab97e80   centos:1   "/bin/bash"   31 seconds ago   Exited (0) 5 seconds ago             nice_ellis

[root@server1 ~]# docker run -it -d centos:1#创建个终端并放在后台运行(不进入)
90f1f6e5df2ee13cfc76553f5d4aef6ff8afe240dfc54dea2f4b3d827033440a

[root@server1 ~]# docker ps -a
CONTAINER ID   IMAGE      COMMAND       CREATED              STATUS                      PORTS     NAMES
90f1f6e5df2e   centos:1   "/bin/bash"   15 seconds ago       Up 13 seconds                         wizardly_chatelet
2bf2fab97e80   centos:1   "/bin/bash"   About a minute ago   Exited (0) 36 seconds ago             nice_ellis

docker ps 显示

-a :显示所有
-q:只显示容器编号
-n:只显示最近创建的n个容器

端口映射

[root@server1 ~]# docker run -it -d -P nginx #从32768开始随机映射
74880fe87ea549641f40b009a2fa80b989f47492aed4a76b606f52566150608e

[root@server1 ~]# docker run -it -d -p 80:80 nginx #指定映射
b01711c7814987a915b8199de0d77166ac9d2c38643dd23d14a8a1c82440b879

[root@server1 ~]# docker ps -a 
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                                     NAMES
b01711c78149   nginx     "/docker-entrypoint.…"   4 seconds ago    Up 3 seconds    0.0.0.0:80->80/tcp, :::80->80/tcp         hardcore_meitner
74880fe87ea5   nginx     "/docker-entrypoint.…"   12 seconds ago   Up 10 seconds   0.0.0.0:49153->80/tcp, :::49153->80/tcp   nervous_swirles

[root@server1 ~]# docker port b01711c78149
80/tcp -> 0.0.0.0:80
80/tcp -> :::80

传递运行命令

容器需要一个前台进程才能保持运行,启动时的指令可以通过在run时后面添加运行指令,也可以在构建镜像的时候指定容器运行时的前台命令

[root@server1 ~]# docker run -it -d centos:1 ping baidu.com
01a5e3f3e8637b9b6b64c6bf014951911cc87d91c871bd41c9c2256236324397
[root@server1 ~]# docker ps -a
CONTAINER ID   IMAGE      COMMAND            CREATED         STATUS         PORTS     NAMES
01a5e3f3e863   centos:1   "ping baidu.com"   5 seconds ago   Up 4 seconds             flamboyant_bohr

单次运行

单次运行,运行完就退出

[root@server1 ~]# docker run --rm hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

[root@server1 ~]# docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

停止容器

挂起:docker pause

取消挂起:docker unpause

终止:docker stop

进入容器

atach:退出后容器关闭

exec:单次进入,退出后容器仍在运行

-d :分离模式: 在后台运行

-i :即使没有附加也保持STDIN 打开

-t :分配一个伪终端

[root@server1 ~]# docker exec -it d599ed1cfe2f bash #进入容器分配终端并执行bash
[root@d599ed1cfe2f /]#

nsenter:通过pid进入容器内部,可以方便写成脚本操作

#!/bin/bash 
docker_in()
{ 
    DOCKER_ID=$1 
    PID=`docker inspect -f "{{.State.Pid}}" ${DOCKER_ID}`
    nsenter -t ${PID} -m -u -i -n -p 
}
docker_in $1

删除容器

docker rm ID
如需要删掉正在运行的容器,则需要加-r

全部删除
 docker rm -f `docker ps -aq`

指定容器dns

默认采用宿主机,也可以用--dns来指定

docker run -it --rm --dns 8.8.8.8 centos bash

导入导出容器

可以把正在跑的容器导出,但是导入的时候会变成镜像

导出
docker export -o /path/name.tar 容器

导入
docker import /path/name.tar  镜像:tag

镜像制作

手动镜像制作

docker commit -a "作者" -m "提交时是说明文字" ID 镜像名:标签

dockerfile

dockerfile可以当成一种被docker程序解释的脚本,dockerfile由一条条命令组成,每条命令对应linux下的一条命令,docker讲这些指令翻译成真正的linux命令,并更具指令生成镜像,当之后某个镜像有额外的需求时,只需要在之前的dockerfile添加或修改相应的操作就可以重新生成新的docker镜像。

dockerfile指令每一次执行都会在docker上新建一层,过多无意义的层会导致镜像膨胀过大

dockerfile制作一个镜像的流程:

  1. docker从基础镜像运行一个容器
  2. 执行一条指令并对容器做出修改
  3. 提交一个新的镜像层
  4. 基于新的镜像层再执行下一个指令
  5. 直到dockerfile中指令执行完毕为止

参数

配置指令:
ARG 定义创建镜像过程中使用的变量,不区分大小写
FROM 指定所创建镜像的基础镜像
LABEL 为生成的镜像添加元数据标签信息
EXPOSE 声明镜像内服务监听的端口,只做声明,没有实际映射功能
ENV 指定环境变量
ENTRYPOINT 指定镜像的默认入口命令,每个file只有一个entrypoint能起效,写多个时最后一个起效,ENTRYPOINT command param1 param2
VOLUME 创建一个数据卷挂载点
USER 指定运行容器时的用户名或UID
WORKDIR 配置工作目录
ONBUILD 创建子镜像时指定自动执行的操作指令
STOPSIGNAL 指定退出的信号值
HEALTHCHECK 配置所启动容器如何进行健康检查
SHELL 指定默认shell类型

操作指令:
RUN 运行指定命令

CMD 
CMD ["executable","param1","param2"] 相当于执行 executable param1 param2 
CMD command param1 param2 在默认的shell中执行,提供给需要交互的应用
CMD ["param1","param2"] 提供给 ENTRYPOINT 的默认参数

启动容器时指定默认执行的命令,cmd跟entrypoint在跟完整命令时功能相似,但是他们并不互斥,可以采用两者相结合的方式来写file,如ent指定默认的运行命令,cmd指定运行参数。如下
ENTRYPOINT ["/bin/ping","-c","3"]
CMD ["localhost"] 

ADD <src> <dest>添加内容到镜像
COPY <src> <dest>复制内容到镜像

阿里云配置

https://cr.console.aliyun.com/

个人实例--设置密码--命名空间--创建仓库--修改镜像tag--上传镜像

一下命令可以在对应仓库--基本信息里面看到
登录:
docker login --username=阿里云账号全名 registry.cn-hangzhou.aliyuncs.com

从仓库中拉取镜像
docker pull registry.cn-hangzhou.aliyuncs.com/tokugawa/test1:[镜像版本号]

将镜像推送到仓库

$ docker login --username= registry.cn-hangzhou.aliyuncs.com
$ docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/tokugawa/test1:[镜像版本号]
$ docker push registry.cn-hangzhou.aliyuncs.com/tokugawa/test1:[镜像版本号]

请根据实际镜像信息替换示例中的[ImageId]和[镜像版本号]参数

实例

构建nginx镜像

http://nginx.org/download/

[root@server1 tmp]# mkdir nginx
[root@server1 tmp]# cd nginx/
[root@server1 nginx]# wget http://nginx.org/download/nginx-1.2.1.tar.gz
[root@server1 nginx]# ls
nginx-1.2.1.tar.gz

[root@server1 nginx]# vim Dockerfile
#定义基础镜像
FROM centos:7
#维护者信息
MAINTAINER tokugawa 123.qq.com
#编译安装组件
RUN yum install -y vim wget tree lrzsz gcc gcc-c++ automake pcre pcre-devel zlib zlib-devel openssl openssl-devel iproute net-tools iotop
#添加压缩包,一定要处于当前目录下
ADD nginx-1.2.1.tar.gz /usr/local
#配置nginx
RUN cd /usr/local/nginx-1.2.1/ \
&& ./configure --prefix=/usr/local/nginx --with-http_sub_module \
&& make \
&& make install \
&& cd /usr/local/nginx \
&& useradd -s /sbin/nologin nginx \
&& ln -sv /usr/local/nginx/sbin/nginx /usr/sbin/nginx \
&& echo 'test index' > /usr/local/nginx/html/index.html

EXPOSE 80 443
#指定镜像启动进程,让nginx以前台的方式运行
CMD ["nginx", "-g", "daemon off;"]

# 构建镜像,后面有个点不要漏掉!!!!!!!
[root@server1 nginx]# docker build -t nginx:v1 .


如果在构建过程中看docker,会发现有个进程在跑,那个就是新镜像的基地镜像在根据你的设置进行修改
[root@server1 nginx-1.2.1]# docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS          PORTS     NAMES
101702c41092   b845f75491a3   "/bin/sh -c 'yum ins…"   32 seconds ago   Up 30 seconds             gracious_feynman


#弄完看见多了一个镜像
[root@server1 nginx]# docker images
REPOSITORY     TAG       IMAGE ID       CREATED          SIZE
centos-nginx   v1        0b4c25729f54   43 seconds ago   553MB
nginx          latest    c919045c4c2b   2 weeks ago      142MB
hello-world    latest    feb5d9fea6a5   5 months ago     13.3kB
centos         1         eeb6ee3f44bd   6 months ago     204MB
centos         7         eeb6ee3f44bd   6 months ago     204MB


#测试
[root@server1 nginx]# docker run -it -d -p 80:80 centos-nginx:v1
30ccc68e51ca1620b972ab44f0fe79cf9de164d0ea5c04289f70bd19133b30f2
[root@server1 nginx]# curl 192.168.226.148
test index


#传上阿里云
[root@server1 nginx]# docker login --username= registry.cn-hangzhou.aliyuncs.com
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded
[root@server1 nginx]# docker tag 0b4c25729f54 registry.cn-hangzhou.aliyuncs.com/tokugawa/test1:centos-nginx:v1
Error parsing reference: "registry.cn-hangzhou.aliyuncs.com/tokugawa/test1:centos-nginx:v1" is not a valid repository/tag: invalid reference format
[root@server1 nginx]# docker tag 0b4c25729f54 registry.cn-hangzhou.aliyuncs.com/tokugawa/test1:v1
[root@server1 nginx]# docker push registry.cn-hangzhou.aliyuncs.com/tokugawa/test1:v1

avatar

数据卷

https://mp.weixin.qq.com/s?__biz=MzI1OTY2MzMxOQ==&mid=2247495888&idx=1&sn=39ed455b12cc2e3ad18f5f72c8e6cc21&chksm=ea77c468dd004d7e42aa4a9c095822e41fd3fa01a08156181615fb66f724bc0d03ff228a39bd&mpshare=1&scene=23&srcid=0725FohVQp49EcJQS0khWpUC&sharer_sharetime=1635037154550&sharer_shareid=ac5ffb01d260d9cefd367fe5efc4eb13#rd

联合挂载是一种文件系统,他可以在不修改原始源的情况下创建多个目录,并把内容合并为一个文件的错觉,docker就采用了这种技术。docker的镜像是分层涉及的,且镜像层是只读的,通过镜像启动的容器添加了一层可读写的文件系统,用户写入的数据就保存在这一层中。每个容器会分配读写层,不同容器会共享同个镜像的制度曾,我们保存在读写层中的数据会在容器被销毁后丢失,为了防止这种情况,我们可以通过数据卷或者数据卷容器的方式将容器内部的数据挂载都本地宿主机的目录,这样在容器被销毁后数据依然存在。

"Data": {
     "LowerDir": "/var/lib/docker/overlay2/8ceac458023aa93ad2e2fefb6854fed17fa2899710a3593148194286cca6f52c/diff:/var/lib/docker/overlay2/010397015f4f99b4862a0af74065ac93755bff65ccfd7987991e5c544e8255d4/diff:/var/lib/docker/overlay2/01151daf0f2b878a038de5331732e86c0f90da0094197b1fcfd87ae6fc1116c0/diff:/var/lib/docker/overlay2/ee5b6a585a634ebc9f5e18de5d6ee65c2bd370039a766921de149759ed3e0b80/diff:/var/lib/docker/overlay2/1b95802314d82d8b3f9633013e1ef984b28fdbac717c2dc27be59842db4dc06f/diff",

    "MergedDir": "/var/lib/docker/overlay2/0b63610489abe1a4135a80c5f01505a56c3fedd43d37ca2575531c8aa71c1323/merged",

    "UpperDir": "/var/lib/docker/overlay2/0b63610489abe1a4135a80c5f01505a56c3fedd43d37ca2575531c8aa71c1323/diff",

    "WorkDir": "/var/lib/docker/overlay2/0b63610489abe1a4135a80c5f01505a56c3fedd43d37ca2575531c8aa71c1323/work"
            },
LoweDir:image镜像层(只读)
UpperDir:容器上层读写曾
MergeDir:容器文件系统,使用联合文件系统将镜像层和容器曾合并给容器使用
WorkDir:容器在宿主机的工作目录

数据卷挂载

数据卷实际就是宿主机上的目录或者文件,可以直接挂载到容器当中使用

创建目录,创建容器并挂载,验证

[root@server1 ~]# docker run -d -it --name ser1 -v /tmp/web/:/usr/share/nginx/html -p 80:80 nginx
afe02569c5ff5c640004b31ea903b150864492e6acb8a4fc9280b5d7964e8f0a
[root@server1 ~]# docker run -d -it --name ser2 -v /tmp/web/:/usr/share/nginx/html -p 81:80 nginx
eddc33c5b2c76267b50da429b988aec49467d9109dee9f8f9148004b7e6af705
[root@server1 ~]# curl 192.168.226.148
hello nginx!
[root@server1 ~]# curl 192.168.226.148:81
hello nginx!

修改后同步

[root@server1 ~]# docker exec -it ser1 bash
root@afe02569c5ff:/# echo 'hello ser!' > /usr/share/nginx/html/index.html
root@afe02569c5ff:/# exit
exit
[root@server1 ~]# curl 192.168.226.148:81
hello ser!
[root@server1 ~]# curl 192.168.226.148
hello ser!

只读挂载

[root@server1 ~]# docker run -it -d -p 82:80 -v /tmp/web/:/usr/share/nginx/html:ro nginx

[root@server1 ~]# docker exec -it 195364402ff7 bash
root@195364402ff7:/# echo 'hello!' >/usr/share/nginx/html/index.html
bash: /usr/share/nginx/html/index.html: Read-only file system

文件挂载

docker run -d -it --name web2 -v /data/web/index.html:/usr/share/nginx/html/index.html:ro -p 8081:80 nginx

数据卷容器

数据卷容器可以让数据在docker容器之间共享,首先创建一个容器作为server用于卷提供,其他使用这个卷的容器作为客户端

创建卷容器

[root@server1 ~]# docker run -d -it --name web1 -p 8082:80 -v /tmp/web/:/usr/share/nginx/html:ro nginx

启动两个客户端容器

[root@server1 ~]# docker run -d -it --name cli1 -p 8083:80 --volumes-from web1 nginx
78942255bbec92f8fa9473d2b3a56d49a434e534ec152ccb0a5689e595ca6024
[root@server1 ~]# docker run -d -it --name cli2 -p 8084:80 --volumes-from web1 nginx
ddeaff99b9303739d7426ccd3118f3e6cf00acfc5b5a59a26125dac0aef63ffe
[root@server1 ~]# curl 192.168.226.148:8083
hello ser!
[root@server1 ~]# curl 192.168.226.148:8084
hello ser!

卷容器stop后也可以创建新容器,但是卷容器被删除后不可以再创建新容器

docker网络

容器间互联方式

直接联通

用ip进行通信

名称互联

[root@docker-server1 ~]# docker run -d -it --name web1 nginx [root@docker-server1 ~]# docker run -d -it --name web2 --link web1 nginx

web2的hosts文件会对web1进行解析

[root@docker-server1 ~]# docker exec -it web2 bash
root@8a3e9cee9e37:/# cat /etc/hosts 
127.0.0.1 localhost 
::1 localhost ip6-localhost ip6-loopback 
fe00::0 ip6-localnet 
ff00::0 ip6-mcastprefix 
ff02::1 ip6-allnodes 
ff02::2 ip6-allrouters 
172.17.0.2 web1 622eff54876f 
172.17.0.3 8a3e9cee9e37

别名互联

使用别名互联后可以防止出现因为容器改名而无法联通

docker run -d -it --name web3 --link web1:nginx-web1 nginx

[root@docker-server1 ~]# docker exec -it web3 bash 
root@c85c73ebf00b:/# cat /etc/hosts 
127.0.0.1 localhost 
::1 localhost ip6-localhost ip6-loopback 
fe00::0 ip6-localnet 
ff00::0 ip6-mcastprefix 
ff02::1 ip6-allnodes 
ff02::2 ip6-allrouters 
172.17.0.2 nginx-web1 622eff54876f web1 
172.17.0.4 c85c73ebf00b

网络模式

|网络模式|配置|说明|
|host|–net=host|容器和宿主机共享Network namespace|
|container|–net=container:NAME_or_ID|容器和另外一个容器共享Network namespace。|
|none|–net=none|容器有独立的Network namespace,但并没有对其进行任何网络设置,如分配veth pair 和网桥连接,配置IP等。|
|bridge|–net=bridge|默认|

bridge

dockers的默认网络类型。当dockers进程启动时,会再主机上创建一个docker0的虚拟网桥,此时再启动容器就会链接到这个虚拟网桥上,类似于交换机,这个主机上的所有容器就能通过网桥链接再一个二层网络中
dockers0从子网中分配一个ip给容器使用,并把docker0的ip地址作为容器的默认网关,再主机上创建一对veth pair设备,一段放在新创建的容器的,并命名为eth0作为容器的网卡,另一端放在主机中,以vethxx命名,当这个网络设备加入到docker0中,可以通过brctl show查看
avatar

host

容器将跟宿主机共用一个network namespace,容器将不会虚拟出自己的网卡、IP等,而是使用宿主机的IP和端口。host的优点是网络性能好,但是宿主机上已经使用的端口就不能再用了,另外网络的隔离性也不好

[root@docker-server1 ~]# docker run -d -it --name web7 --network host nginx

container

container的容器和已存在的一个容器共享一个network namespace,除此以外其他的文件系统、进程等还是隔离的,两个容器的进程可以通过lo网卡设备进行通信.注意,当新容器需要的端口已经被老容器占用的时候,可能会导致错误

[root@docker-server1 ~]# docker run -d -it --name web5 --network container:web1 nginx

none

在使用none后,docker容器不会进行仍和网络配置

`[root@docker-server1 ~]# docker run -d -it --name web4 --network none nginx1`

自定义网络

创建一个网络

[root@docker-server1 ~]# docker network create -d bridge --subnet 10.10.0.0/16 --gateway 10.10.0.1 testnet 
74ee6ecdfc0382ac0abb1b46a3c90e3c6a39f0b7388aa9ba99fddc6bac72e8ce 
[root@docker-server1 ~]# docker network list 
NETWORK ID NAME DRIVER SCOPE 
787342a0d883 bridge bridge local 
74ee6ecdfc03 testnet bridge local 
9a6d7244e807 host host local 
beace8354cca none null local

使用自定义网络
[root@docker-server1 ~]# docker run -d -it --name web8 --network testnet nginx

资源限制

容器在默认情况下没有资源限制但对于linux主机来说,如果没有足够的内存来执行重要的系统任务,那就会抛出OOM异常(内存溢出、内存泄漏、内存异常),之后系统会杀进程来释放内存,为了防止这种情况出现,可以对容器的内存使用范围进行限制

https://blog.csdn.net/shenzhen_zsw/article/details/90722333

-m,–memory 内存限制,格式是数字加单位,单位可以为 b,k,m,g。最小为 4M

–memory-swap 内存+交换分区大小总限制。格式同上。必须必-m设置的大

–memory-reservation 内存的软性限制。格式同上

–oom-kill-disable 是否阻止 OOM killer 杀死容器,默认没设置

–oom-score-adj 容器被 OOM killer 杀死的优先级,范围是[-1000, 1000],默认为 0

–memory-swappiness 用于设置容器的虚拟内存控制行为。值为 0~100 之间的整数

–kernel-memory 核心内存限制。格式同上,最小为 4M

容器测压镜像

[root@server1 ~]# docker pull lorel/docker-stress-ng

FTP

FTP:文件传输协议,采用两个TCP连接来传输一个文件

  • 控制连接以C/S方式建立,服务器以被动的方式打开21端口等待客户连接,客户以主动方式打开21,控制连接始终等待客户于服务器之间的通信,该连接将命令从客户传到服务器,并传回服务器的应答
  • 当文件开始在客户和服务器之间传输时,创建一个数据连接(20),具体过程如下:

    • 客户发出命令请求建立数据连接,连接在客户的控制下建立
    • 客户在客户端上选择一个临时端口号,从该端口发布
    • 客户通过控制连接把端口号发送给服务器
    • 服务器在控制连接上接收端口信号,并向客户端上的端口发布一个主动的打开,服务器使用的数据连接端口为20

主动模式
avatar

但有时FTP服务器处在的环境不允许直接被外部的主机访问,这时需要采用被动模式,让FTP服务端去连接客户端。具体如下

  • FTP客户端连接到FTP服务器21端口,发送用户名和密码登录,登录成功后要list列表或者读取数据时,发送PASV命令到FTP服务器, 服务器在本地随机开放一个端口(1024以上),然后把开放的端口告诉客户端, 客户端再连接到服务器开放的端口进行数据传输

avatar

实验

匿名

修改配置文件后重启

vi /etc/vsftpd/vsftpd.conf anonymous_enable=YES 
anon_umask=022 
anon_upload_enable=Yes anon_mkdir_write_enable=Yes
anon_other_write_enable=Yes local_enable=YES 
write_enable=YES 
local_umask=022 
dirmessage_enable=YES xferlog_enable=YES connect_from_port_20=YES xferlog_std_format=YES 
listen=NO 
listen_ipv6=YES pam_service_name=vsftpd userlist_enable=YES 
tcp_wrappers=YES

avatar
avatar

系统用户

修改配置文件后重启

vi /etc/vsftpd/vsftpd.conf 

anonymous_enable=NO 
local_enable=YES 
write_enable=YES 
local_umask=022 
dirmessage_enable=YES xferlog_enable=YES connect_from_port_20=YES xferlog_std_format=YES 
listen=NO 
listen_ipv6=YES pam_service_name=vsftpd userlist_enable=YES 
tcp_wrappers=YES

在/etc/vsftpd/ftpuser /etc/vsftpd/user_list这两个文件中的用户被视为黑名单
avatar

虚拟用户

创建FTP用户数据库文件,奇数行用户名,偶数行密码,用db_load命令加密转换成数据库文件,删除明文信息文件

[root@server1 ~]# cd /etc/vsftpd/
[root@server1 vsftpd]# vi vuser.list
[root@server1 vsftpd]# db_load -T -t hash -f vuser.list vuser.db
[root@server1 vsftpd]# file vuser.db
vuser.db: Berkeley DB (Hash, version 9, native byte-order)
[root@server1 vsftpd]# chmod 600 vuser.db
rm -rf vuser.list

创建一个用作代理的本地用户

[root@server1 vsftpd]# useradd -d /var/ftproot -s /sbin/nologin virtual
[root@server1 vsftpd]# ls -ld /var/ftproot/
drwx------. 2 virtual virtual 62 1月  17 18:38 /var/ftproot/
chmod -Rf 777 /var/ftproot

建立一个用于虚拟用户认证的PAM文件

[root@server1 vsftpd]# vi /etc/pam.d/vsftpd.vu

auth required pam_userdb.so db=/etc/vsftpd/vuser account required pam_userdb.so db=/etc/vsftpd/vuser

修改配置文件,注意配置文件每行尾都不能有空格,不然会报错

[root@server1 vsftpd]# cp /etc/vsftpd/vsftpd.conf /etc/vsftpd/vsftpd.conf.bak

[root@server1 vsftpd]# vi /etc/vsftpd/vsftpd.conf

anonymous_enable=NO
local_enable=YES
guest_enable=YES 
guest_username=virtual 
allow_writeable_chroot=YES 
write_enable=YES
local_umask=022
dirmessage_enable=YES 
xferlog_enable=YES
connect_from_port_20=YES 
xferlog_std_format=YES
listen=NO
listen_ipv6=YES 
pam_service_name=vsftpd.vu 
userlist_enable=YES
tcp_wrappers=YES

[root@server1 vsftpd]# systemctl restart vsftpd

[root@server1 var]# ftp 192.168.226.148
Connected to 192.168.226.148 (192.168.226.148).
220 (vsFTPd 3.0.2)
Name (192.168.226.148:root): user1
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.

一个完整的监控应该包括:

  • 数据采集
  • 数据展示
  • 定义问题
  • 通知告警

    zabbix

    zabbix是一个基于web界面提供分布式系统监视以及网络监视功能的开源解决方案

优点

  • 支持多设备,自带多种监控模板
  • 支持分布式集中管理,可以自动发现,可试试自动化监控
  • 开放式接口,扩展性强
  • 当监控的 item 比较多服务器队列比较大时可以采用主动状态,被监控客户端主动 从server 端去下载需要监控的 item 然后取数据上传到 server 端。 这种方式对服务器的负载比较小。

缺点

  • 需要在北监控主机上安装agent,所有数据存放在数据库里,产生的数据很大
  • 项目批量修改不方便
  • 缺乏数据汇总功能,需要二次开发
  • 系统级别报警设置相对比较多,不筛选报警邮件会很多
    zabbix5.0中文手册

zabbix的组件

zabbix server

Zabbix server 是整个 Zabbix 软件的核心程序。

Zabbix Server 负责执行数据的主动轮询和被动获取,计算触发器条件,向用户发送通知。它是 Zabbix Agent 和 Proxy 报告系统可用性和完整性数据的核心组件。Server 自身可以通过简单服务远程检查网络服务(如Web服务器和邮件服务器)。

Zabbix Server是所有配置、统计和操作数据的中央存储中心,也是Zabbix监控系统的告警中心。在监控的系统中出现任何异常,将被发出通知给管理员。

基本的 Zabbix Server 的功能分解成为三个不同的组件。他们是:Zabbix server、Web前端和数据库。

Zabbix 的所有配置信息都存储在 Server 和Web前端进行交互的数据库中。例如,当你通过Web前端(或者API)新增一个监控项时,它会被添加到数据库的监控项表里。然后,Zabbix server 以每分钟一次的频率查询监控项表中的有效项,接着将它存储在 Zabbix server 中的缓存里。这就是为什么 Zabbix 前端所做的任何更改需要花费两分钟左右才能显示在最新的数据段的原因。

agent

Zabbix agent 部署在被监控目标上,以主动监控本地资源和应用程序(硬盘、内存、处理器统计信息等)。

Zabbix agent 收集本地的操作信息并将数据报告给 Zabbix server 用于进一步处理。一旦出现异常 (例如硬盘空间已满或者有崩溃的服务进程),Zabbix server 会主动警告管理员指定机器上的异常。

Zabbix agents 的极高效率缘于它可以利用本地系统调用来完成统计数据的采集。

proxy

Zabbix proxy 是一个可以从一个或多个受监控设备采集监控数据并将信息发送到 Zabbix server 的进程,主要是代表 Zabbix server 工作。 所有收集的数据都在本地缓存,然后传输到 proxy 所属的 Zabbix server。

部署Zabbix proxy 是可选的,但可能非常有利于分担单个 Zabbix server 的负载。 如果只有代理采集数据,则 Zabbix server 上会减少 CPU 和磁盘 I/O 的开销。

Zabbix proxy 是无需本地管理员即可集中监控远程位置、分支机构和网络的理想解决方案。

Zabbix proxy 需要使用独立的数据库

zabbix监控server部署

安装:在官网上选择对应版本https://www.zabbix.com/cn/download?zabbix=5.0&os_distribution=centos&os_version=7&db=mysql&ws=nginx,这里我选择5.0+centos7+mysql+nginx,然后根据他下面给出的提示安装

rpm -Uvh https://repo.zabbix.com/zabbix/5.0/rhel/7/x86_64/zabbix-release-5.0-1.el7.noarch.rpm

yum clean all

yum install zabbix-server-mysql zabbix-agent

yum install centos-release-scl

vim /etc/yum.repos.d/zabbix.repo
[zabbix-frontend]
name=Zabbix Official Repository frontend - $basearch
baseurl=http://repo.zabbix.com/zabbix/5.0/rhel/7/$basearch/frontend
enabled=1


配置数据库
yum install mariadb-server.x86_64 -y

创建用户,完成初始化
MariaDB [(none)]> create database zabbix character set utf8 collate utf8_bin;
Query OK, 1 row affected (0.00 sec)

MariaDB [(none)]> create user zabbix@localhost identified by '123456';
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]>  grant all privileges on zabbix.* to zabbix@localhost;
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> exit

zcat /usr/share/doc/zabbix-server-mysql*/create.sql.gz | mysql -uzabbix -p123456 zabbix


vim /etc/zabbix/zabbix_server.conf
DBUser=zabbix

### Option: DBPassword
#       Database password.
#       Comment this line if no password is used.
#
# Mandatory: no
# Default:
DBPassword=123456


vim  /etc/opt/rh/rh-php72/php-fpm.d/zabbix.conf

server {
        listen          80;
        server_name     192.168.226.148;

vim /etc/opt/rh/rh-php72/php-fpm.d/zabbix.conf
listen.acl_users = apache,nginx
php_value[date.timezone] = Asia/Shanghai


# systemctl restart zabbix-server zabbix-agent rh-nginx116-nginx rh-php72-php-fpm
# systemctl enable zabbix-server zabbix-agent rh-nginx116-nginx rh-php72-php-fpm

访问ip,显示安装成功
avatar

初始账号Admin zabbix,去用户中心换语种,当然,为了安全考虑,最好把密码也换掉。在管理--用户里面可以新增用户
avatar

agent部署


rpm -Uvh https://repo.zabbix.com/zabbix/5.0/rhel/7/x86_64/zabbix-release-5.0-1.el7.noarch.rpm

yum install zabbix-agent  -y

[root@server2 ~]# vim /etc/zabbix/zabbix_agentd.conf 
Server=192.168.80.148 
ServerActive=192.168.80.148 
Hostname=server2


systemctl start zabbix-agent

在server面板上

配置(Configuration) → 主机(Hosts)->点击创建主机(Create host)以添加新的主机

所有必填字段均以红色星标标示。

至少需要填写下列字段:

主机名称(Host name)

输入一个主机名称,可以使用字母数字、空格、点”."、中划线"-"、下划线"_"。

从右边的选择框中,选择一个或者多个组,然后点击 << 移动它们到'所在组(In groups)'选择框;或者输入一个不存在的组名,zabbix会创建这个组。

所有访问权限都分配到主机组,而不是单独的主机。这也是主机需要属于至少一个组的原因。

IP地址

输入主机的IP地址。注意如果这是Zabbix server的IP地址,它必须是Zabbix agent配置文件中‘Server’参数的值。
其他选项将会使用默认值。

当完成后,点击添加(Add)。你可以在主机列表中看到你新添加的主机。

随后我们要添加模板--应用集--监控项,相同的监控项可以放进应用集,相同的应用集可以放进模板

主机--应用集--创建应用集--监控项--创建监控项(添加到对应的应用集)--监控--最新数据--点击刚才的主机选择应用--等待一段时间后可以查看可视化图表

把模板链接到主机:准备一个模版后,将它链接到一个主机。前往配置(Configuration) → 主机(Hosts),点击'新主机(New host)'打开表单,前往模版(Templates)标签页。

在链接新模版(Link new templates)输入我们刚刚新创建的模板名字,我们所创建的模板的名称应该显示在下拉列表中,请向下滚动以进行选择。请查看模版是否出现在链接新模版(Link new templates)文本框。

把一个已有的模板添加到主机的方式:

转到配置→主机
单击所需的主机并切换到模板选项卡
点击链接指示器旁边的选择
在弹出窗口中选择一个或多个模板
单击主机属性窗体中的添加/更新

在客户端上自定义监控项

客户端:

[root@server2 ~]# cat /etc/zabbix/zabbix_agentd.d/userparameter_nginx.conf UserParameter=nginx_process_num,ps -ef | grep -c [n]ginx 
[root@server2 ~]# systemctl restart zabbix-agent.service

去服务器上验证

[root@server1 ~]# yum install zabbix-get.x86_64 -y
#这个能获取别的服务器上的监控数据
[root@server1 ~]# zabbix_get -s 192.168.226.149 -k nginx_process_num
3
#说明配置成功,可以去面板上写了

avatar

avatar

常用nginx监控项

vim /etc/nginx/conf.d/default.conf 
location /nginx-status 
{ 
    stub_status on; 
    access_log off; 
    allow 127.0.0.1; 
    deny all; 
} 


vim /etc/zabbix/zabbix_agentd.d/nginx.conf 

UserParameter=Nginx.active,/usr/bin/curl -s "http://127.0.0.1:80/nginx-status" | awk '/Active/ {print $NF}' 
UserParameter=Nginx.read,/usr/bin/curl -s "http://127.0.0.1:80/nginx-status" | grep 'Reading' | cut -d" " -f2 
UserParameter=Nginx.wrie,/usr/bin/curl -s "http://127.0.0.1:80/nginx-status" | grep 'Writing' | cut -d" " -f4 
UserParameter=Nginx.wait,/usr/bin/curl -s "http://127.0.0.1:80/nginx-status" | grep 'Waiting' | cut -d" " -f6 
UserParameter=Nginx.accepted,/usr/bin/curl -s "http://127.0.0.1:80/nginx-status" | awk '/^[ \t]+[0-9]+[ \t]+[0-9]+[ \t]+[0-9]+/ {print $1}' 
UserParameter=Nginx.handled,/usr/bin/curl -s "http://127.0.0.1:80/nginx-status" | awk '/^[ \t]+[0-9]+[ \t]+[0-9]+[ \t]+[0-9]+/ {print $2}' 
UserParameter=Nginx.requests,/usr/bin/curl -s "http://127.0.0.1:80/nginx-status" | awk '/^[ \t]+[0-9]+[ \t]+[0-9]+[ \t]+[0-9]+/ {print $3}'

邮件报警

  1. 配置Email:管理-》报警媒介类型-》Email-》修改对应Email参数
  2. 修改admin用户的报警媒介Email:管理-》用户-》Admin-》报警媒介-》添加接收报警邮件的邮箱-》
    点击更新
  3. 添加触发器:配置-》主机-》已监控的主机-》触发器-》创建触发器-》填入报警名称-》点击表达式右
    边的添加-》点击监控项右边的选择-》建议选择system uptime(系统启动时间)-》结果选等于0确认插
    入-》更新
  4. 查看触发器状态:配置-》主机-》已监控主机里的触发器,找到新创建的触发器-》可以看到触发器对
    应的值有问题和状态两种,可能需要等几分钟才会更新过来
  5. 配置发送异常报警邮件:配置-》动作-》点击启用Report problems to Zabbix administrators即可
  6. 邮箱收到报警邮件

avatar
如果不行,把这里两个ssl的框勾上
avatar

avatar
avatar

额外的教训

我在自己服务器上安装的时候,我原本就有一个编译安装在别的目录的nginx,zabbix又给我装了一个,但是两个都是默认80端口,导致当一个被拉起来的时候另外一个拉不起来,后来去把属于zabbix的nginx配置文件里面的端口全部改掉restart才ok

nginx负载均衡

ngx_http_upstream_module七层负载均衡

相关参数:

upstream:定义后端服务器组,会引入一个新的上下文
server:在upstream上下文中server成员,以及相关的参数
least_conn;:最少连接调度算法,当server拥有不同的权重时其为wlc
ip_hash;:源地址hash调度方法
hash :基于指定的key的hash表来实现对请求的调度,此处的key可以直接文本、变量或二者的组
合
keepalive connections;:为每个worker进程保留的空闲的长连接数量;
weight=number # 权重,默认为1;
max_fails=number # 失败尝试最大次数;超出此处指定的次数时,server将被标记为不可用;
fail_timeout=time # 设置将服务器标记为不可用状态的超时时长;
max_conns # 当前的服务器的最大并发连接数;
backup # 将服务器标记为“备用”,即所有服务器均不可用时此服务器才启用;
down # 标记为“不可用

负载均衡算法

轮询(默认): 每个请求按时间顺序逐一分配到不同的后端服务,如果后端某台服务器死机,自动剔
除故障系统,使 用户访问不受影响。
weight(轮询权值):weight的值越大分配到的访问概率越高,主要用于后端每台服务器性能不均
衡的情况下。或 者仅仅为在主从的情况下设置不同的权值,达到合理有效的地利用主机资源
ip_hash:每个请求按访问IP的哈希结果分配,使来自同一个IP的访客固定访问一台后端服务器,
并且可以有效解决 动态网页存在的session共享问题。
fair:比 weight、ip_hash更加智能的负载均衡算法,fair算法可以根据页面大小和加载时间长短智
能地进行负载均 衡,也就是根据后端服务器的响应时间 来分配请求,响应时间短的优先分配。
Nginx本身不支持fair,如果需要这 种调度算法,则必须安装upstream_fair模块。
url_hash:按访问的URL的哈希结果来分配请求,使每个URL定向到一台后端服务器,可以进一步
提高后端缓存服 务器的效率。Nginx本身不支持url_hash,如果需要这种调度算法,则必须安装
Nginx的hash软件包。

七层负载均衡

七层负载均衡是基于URL等应用层信息的负载均衡,也被成为“内容交换”,主要是通过报文中真正有意义的应用层内容,再加上负载均衡设备设置的服务器选择方式,决定最终选择的服务器

以TCP为例,负载均衡器需要先跟客户端建立连接,才能接收到客户端应用层内容的报文,然后根据报文中的特定字段,再加上负载均衡设置的服务器选择方式,最终选定内部服务器。负载均衡器和客户端与服务器会分别建立TCP连接,在这种情况下更像一个代理服务器

七层负载对设备的要求更高,但是对内容的处理更为灵活,例如访问一个网站的游客量,可以把图片类的请求转发到特定的图片服务器并使用缓存技术,对文字类的请求可以转发到特定的文字服务器并使用压缩技术,极大提高网络的灵活性。而且七层负载的特性也决定了面对SYN Flood攻击时,会在负载均衡器这一步就被拦下,不会影响到后台服务器的正常运行

server1作为反向代理服务器,server3,4,5作为apache web站点

先在后面三台上面配置完apache,然后再server1进行反向代理服务器配置七层代理

[root@server1 ~]# vim /etc/nginx/conf.d/proxy.conf

upstream webs{
server 192.168.226.149 weight=2; #weight为权重,可加可不加
server 192.168.226.153 weight=2;
server 192.168.226.152 weight=6;


}
server {
listen *:8787;
server_name 192.168.226.148:8787;
location{
proxy_pass http://webs;
}
}

测试访问

[root@server1 ~]# for i in {1..20};do curl 192.168.226.148:8787; done
server3
server2
server3
server2
server3
server3
server4
server3
server3
server2
server3
server4
server4
server3
server3
server2
server3
server3
server3
server4

nginx-mod-stream四层负载均衡

四层负载均衡基于IP+端口,主要通过报文中的目标地址和端口,再加上负载均衡设备设置的服务器选择方式,最终决定内部的服务器,负载均衡器仅作转发功能。

以TCP为例,当负载均衡设备接收到第一个来自客户端的SYN请求时,会通过上述方式选择一个最佳服务器,然后修改报文中目标IP之后直接转发给改服务器,TCP的连接也是客户端跟服务器直接连接,负载均衡设备只起一个类似路由转发的功能

avatar

实验

yum默认没装这个模块,yum install -y nginx-mod-stream

vim /etc/nginx/nginx.conf

events {
    worker_connections 1024;
}
stream{
        upstream sshers{
                server 192.168.226.149:22;
                server 192.168.226.152:22;
                server 192.168.226.153:22;
                least_conn;#请求将被传递给当前拥有最少活跃连接的server,同时考虑权重weight的因素
}
        server{
                listen *:7878;
                proxy_pass sshers;
}
}

这里用ssh 7878端口远程登陆来测试