早上起来你有两个选择:
盖上被子做你未完成的梦||掀开被子完成未完成的梦

CentOS和Ubuntu系统Docker环境部署

Kaivi

在Centos上安装

linux内核版本依赖

kernel version >= 3.8

可以使用如下命令查看

[root@centos-7 ~]#uname -a | awk '{split($3, arr, "-"); print arr[1]}'
3.10.0

如果已安装过Docker, 需要移除老版本的Docker

sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine

添加Docker repository yum源

# 国内源, 速度更快, 推荐
sudo yum-config-manager \
    --add-repo \
    https://mirrors.ustc.edu.cn/docker-ce/linux/centos/docker-ce.repo

# 官方源, 服务器在国外, 安装速度慢
# $ sudo yum-config-manager \
#     --add-repo \
#     https://download.docker.com/linux/centos/docker-ce.repo

开始安装Docker Engine

sudo yum makecache fast
sudo yum install docker-ce docker-ce-cli containerd.io

开启Docker

sudo systemctl enable docker
sudo systemctl start docker

验证是否安装成功

 sudo docker run hello-world

如果出现"Hello from Docker.", 则代表运行成功

[root@centos-7 ~]#sudo docker run 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/

如果在每次运行docker命令是, 在前面不添加sudo, 可以执行如下命令:

sudo usermod -aG docker $USER

一般也是root的超级权限也就用不着用sudo了

脚本部署docker

如果嫌上面安装步骤麻烦, 可以运行如下脚本来安装

不能在生产系统中使用

curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh --mirror Aliyun

sudo systemctl enable docker
sudo systemctl start docker

sudo groupadd docker
sudo usermod -aG docker $USER

在Ubuntu上安装

linux内核版本依赖

kernel version >= 3.8
可以使用如下命令查看

uname -a | awk '{split($3, arr, "-"); print arr[1]}'

操作系统依赖, 如下版本都可以

Disco 19.04
Cosmic 18.10
Bionic 18.04 (LTS)
Xenial 16.04 (LTS)

如果已安装过Docker, 需要移除老版本的Docker

sudo apt-get remove docker docker-engine docker.io containerd runc

使用Docker repository 来安装

# 更新apt包索引
sudo apt-get update

# 为支持https
sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common

# 添加Docker GPG秘钥
# 国内源
curl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg | sudo apt-key add -

# 或者国外源
# curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

# 添加安装源
# 推荐国内源
sudo add-apt-repository \
    "deb [arch=amd64] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu \
    $(lsb_release -cs) \
    stable"

# 或者国外源
# sudo add-apt-repository \
#   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
#   $(lsb_release -cs) \
#   stable"

安装Docker

# 更新apt包索引
sudo apt-get update

# 安装docker
sudo apt-get install docker-ce docker-ce-cli containerd.io

开启Docker

sudo systemctl enable docker

sudo systemctl start docker

验证是否安装成功

 sudo docker run hello-world

如果出现"Hello from Docker.", 则代表运行成功

如果在每次运行docker命令是, 在前面不添加sudo, 可以执行如下命令:

sudo usermod -aG docker $USER

使用shell脚本安装Docker

Ubuntu和Centos上安装

vim install_docker_.sh

#!/bin/bash
#install docker in ubuntu and centos

function install_docker_in_ubuntu
{
    sudo  apt-get update -y
    # install some tools
    sudo apt-get install \
        apt-transport-https \
        ca-certificates \
        curl \
        gnupg-agent \
        software-properties-common \
        net-tools \
        wget -y

    # install docker
    curl -fsSL get.docker.com -o get-docker.sh
    sh get-docker.sh

    # start docker service
    sudo groupadd docker &> /dev/null
    sudo gpasswd -a "${USER}" docker
    sudo systemctl start docker

    rm -rf get-docker.sh
}

function install_docker_in_centos
{
    # install some tools
    sudo yum install -y git vim gcc glibc-static telnet bridge-utils

    # install docker
    curl -fsSL get.docker.com -o get-docker.sh
    sh get-docker.sh

    # start docker service
    sudo groupadd docker &> /dev/null
    sudo gpasswd -a "${USER}" docker
    sudo systemctl start docker

    rm -rf get-docker.sh

}

SYSTEM_NAME="$(awk -F= '/^NAME/{print $2}' /etc/os-release)"
if [[ "${SYSTEM_NAME,,}" =~ "ubuntu"  ]] ; then
    echo "Your system is ubuntu."
    echo "Installing Docker in ubuntu..."
    install_docker_in_ubuntu
elif [[ "${SYSTEM_NAME,,}" =~ "centos" ]] ; then
    echo "Your system is centos."
    echo "Installing Docker in centos..."
    install_docker_in_centos
else
    echo "This script can only run in ubuntu and centos system."
    exit 1
fi

Docker部署实验

docker单机部署rabbitmq

更多咨询,关注微信公众号

Docker-Swarm-Consul-RabbitMQ集群

Kaivi

架构介绍

Docker Swarm上基于Consul实现高可用RabbitMQ集群。RabbitMQ是基于高级消息队列协议(AMQP)实现的开源消息代理软件,主要提供消息队列服务。这里介绍用Docker Compose搭建RabbitMQ高可用集群的过程。

Swarm是Docker官方提供的一款集群管理工具,其主要作用是把若干台Docker主机抽象为一个整体,并且通过一个入口统一管理这些Docker主机上的各种Docker资源。

Swarm和Kubernetes比较类似,但是更加轻,具有的功能也较kubernetes更少一些

实验通过Docker swarm建立基于Consul自动发现的高可用性的RabbitMQ集群。通过HAProxy服务器以负载均衡AMQP请求,并提高群集的整体可用性。

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

在这里插入图片描述

环境准备

主机名称和IP

主机名 IP
D-master 192.168.32.11
D-node-1 192.168.32.12
D-node-2 192.168.32.13

Docker 版本

三台主机节点都是一样的docker版本以及操作系统


# docker --version
Docker version 18.09.9, build 039a7df9ba

# cat /etc/issue
Ubuntu 18.04.1 LTS \n \l

部署swarm集群

初始化docker swarm集群

在master上初始化集群

root@D-master:~# docker swarm init --advertise-addr 192.168.32.11
Swarm initialized: current node (nt58bpwl6t31cuncok453d8bv) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-2qdamb060dkj7y7fr080ywgfakxuuyncwjq19nsk14tbacu02l-2ebxvqnsvql3lu3xpybkzcpqu 192.168.32.11:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

把node的两台机器加入到master集群

#node1:
root@D-node-1:~# docker swarm join --token SWMTKN-1-2qdamb060dkj7y7fr080ywgfakxuuyncwjq19nsk14tbacu02l-2ebxvqnsvql3lu3xpybkzcpqu 192.168.32.11:2377
This node joined a swarm as a worker.

#node2:
root@D-node-2:~# docker swarm join --token SWMTKN-1-2qdamb060dkj7y7fr080ywgfakxuuyncwjq19nsk14tbacu02l-2ebxvqnsvql3lu3xpybkzcpqu 192.168.32.11:2377
This node joined a swarm as a worker.

在master主机上查看集群状态

root@D-master:~# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
nt58bpwl6t31cuncok453d8bv *   D-master            Ready               Active              Leader              18.09.9
6e5sj1f8wzi6notn96hz9w3oe     D-node-1            Ready               Active                                  18.09.9
wfnlemwns5y8fv0i67jlx7atl     D-node-2            Ready               Active                                  18.09.9

提升节点为manager

root@D-master:~#  docker node promote D-node-1        #提升node1
Node D-node-1 promoted to a manager in the swarm.

root@D-master:~# docker node promote D-node-2         #提升node2
Node D-node-2 promoted to a manager in the swarm.

#查看各个节点的node角色
root@D-master:~# docker node inspect D-master | less | grep -i role
            "Role": "manager",
root@D-master:~# docker node inspect D-node-1 | less | grep -i role
            "Role": "manager",
root@D-master:~# docker node inspect D-node-2 | less | grep -i role
            "Role": "manager",

root@D-master:~# for i in `docker node ls -q`;do docker node inspect $i | grep -i role ;done
            "Role": "manager",
            "Role": "manager",
            "Role": "manager",

网络创建

root@D-master:~# docker network create --driver=overlay --attachable prod   #创建网络
g7vpwhorx9twyoxsyl1k994vj

root@D-master:~# docker network ls   #查看网络列表
NETWORK ID          NAME                DRIVER              SCOPE
7e60ca1d698e        bridge              bridge              local
dxlvucnscnc7        consul_consul       overlay             swarm
5953313f3a26        docker_gwbridge     bridge              local
1ac0d262e7e3        host                host                local
fy418rdt19f1        ingress             overlay             swarm
2f3907cd86b4        none                null                local
g7vpwhorx9tw        prod                overlay             swarm

部署consul集群

「注意点」
持久化consul的数据,避免数据丢失
在global模式下部署Consul服务,并通过节点标签管理服务调度
使用两个单独的网络,一个用于内部consul的通信,另一个用于RabbitMQ与Consul服务之间的通信

添加节点标签

root@D-master:~# mkdir consul_rabbitmq_docker
root@D-master:~# cd consul_rabbitmq_docker

root@D-master:~/consul_rabbitmq_docker# docker node update --label-add consul=true D-master 
D-master

root@D-master:~# docker node update --label-add consul=true D-node-1
D-node-1

root@D-master:~/consul_rabbitmq_docker# docker node update --label-add consul=true D-node-2 
D-node-2

# for i in `docker node ls -q`;do docker node inspect $i | grep -iA 5 label ;done     #查拉姆节点标签

如果节点标签定义错误,可以先对节点标签删除操作,然后重新创建
#删除节点操作
# docker node update --label-rm  标签名 主机名

consul部署清单

这个部署清单用于通过swarm来编排docker的pod,启动操作:docker stack deploy -c + .yml文件

root@D-master:~/consul_rabbitmq_docker# vim docker-compose_consul.yaml
version: '3.6'
services:
  consul:
    image: consul:1.4.0
    hostname: "{{.Node.Hostname}}"
    networks:
      - consul
      - prod
    ports:
      - 8400:8400
      - 8500:8500
      - 8600:53
    volumes:
      - consul-data:/consul/data
    deploy:
      mode: global
      placement:
        constraints: [node.labels.consul == true]
    command: [ "agent", "-server", "-bootstrap-expect=3", "-retry-max=3", "-retry-interval=10s", "-datacenter=prod", "-join=consul", "-retry-join=consul", "-bind={{ GetInterfaceIP \"eth0\" }}", "-client=0.0.0.0", "-ui"]
networks:
  consul:
  prod:
    external: true
volumes:
  consul-data:

初始化consul集群

root@D-master:~/consul_rabbitmq_docker# docker stack deploy -c docker-compose_consul.yaml consul
Creating network consul_consul
Creating service consul_consul

#查看节点标签
root@D-master:~/consul_rabbitmq_docker# for i in `docker node ls -q`;do docker node inspect $i | grep -iC 5 label ;done      

consul集群检测

root@D-master:~# curl 192.168.32.11:8500/v1/status/leader
"10.0.2.47:8300"

root@D-master:~# curl 192.168.32.12:8500/v1/status/leader
"10.0.2.47:8300"

root@D-master:~# curl 192.168.32.13:8500/v1/status/leader
"10.0.2.47:8300"

root@D-master:~# curl 192.168.32.11:8500/v1/status/peers         #集群
["10.0.2.47:8300","10.0.2.35:8300","10.0.2.49:8300"]

查看是否启动

root@D-master:~# docker ps -a |grep consul

访问网页的consul的dashboard来验证安装是否成功。
http://192.168.32.11:8500/

在这里插入图片描述

部署RabbitMQ集群

「注意点」
持久化数据防止数据丢失
在global模式下部署RabbitMQ服务,并通过节点标签管理服务调度
使用Prod网络进行内部/外部RabbitMQ通信
不要暴露 RABBITMQ_ERLANG_COOKIE and RABBITMQ_DEFAULT_PASS
主机名很重要,因为RabbitMQ使用主机名作为数据目录

RabbitMQ部署清单

root@D-master:~/consul_rabbitmq_docker# vim docker-compose_rabbitmq.yml
root@D-master:~/consul_rabbitmq_docker# cat docker-compose_rabbitmq.yml

version: "3.6"
services:
  rabbitmq-01:
    image: olgac/rabbitmq:3.7.8-management
    hostname: rabbitmq-01
    environment:
      - RABBITMQ_DEFAULT_USER=admin
      - RABBITMQ_DEFAULT_PASS=Passw0rd
      - RABBITMQ_ERLANG_COOKIE="MY-SECRET-KEY-123"
    networks:
      - prod
    volumes:
      - rabbitmq-01-data:/var/lib/rabbitmq
    deploy:
      mode: global
      placement:
        constraints: [node.labels.rabbitmq1 == true]
  rabbitmq-02:
    image: olgac/rabbitmq:3.7.8-management
    hostname: rabbitmq-02
    environment:
      - RABBITMQ_DEFAULT_USER=admin
      - RABBITMQ_DEFAULT_PASS=Passw0rd
      - RABBITMQ_ERLANG_COOKIE="MY-SECRET-KEY-123"
    networks:
      - prod
    volumes:
      - rabbitmq-02-data:/var/lib/rabbitmq
    deploy:
      mode: global
      placement:
        constraints: [node.labels.rabbitmq2 == true]
  rabbitmq-03:
    image: olgac/rabbitmq:3.7.8-management
    hostname: rabbitmq-03
    environment:
      - RABBITMQ_DEFAULT_USER=admin
      - RABBITMQ_DEFAULT_PASS=Passw0rd
      - RABBITMQ_ERLANG_COOKIE="MY-SECRET-KEY-123"
    networks:
      - prod
    volumes:
      - rabbitmq-03-data:/var/lib/rabbitmq
    deploy:
      mode: global
      placement:
        constraints: [node.labels.rabbitmq3 == true]
networks:
  prod:
    external: true
volumes:
  rabbitmq-01-data:
  rabbitmq-02-data:
  rabbitmq-03-data:

RabbitMQ集群初始化

# docker-compose config  用于部署清单.yml文件的语法检测

在定义标签错误的情况下,可以先删除节点标签,然后再创建新的节点标签
#删除节点标签操作:
root@D-master:~/consul_rabbitmq_docker# docker node update --label-rm  rabbitmq1 D-node-1
D-node-1

###自动逸rabbitmq标签

root@D-master:~/consul_rabbitmq_docker# docker node update --label-add rabbitmq1=true D-master 
D-master

root@D-master:~/consul_rabbitmq_docker# docker node update --label-add rabbitmq2=true D-node-1
D-node-1

root@D-master:~/consul_rabbitmq_docker# docker node update --label-add rabbitmq3=true D-node-2
D-node-2

###查看node标签:
root@D-master:~/consul_rabbitmq_docker# for i in `docker node ls -q`;do docker node inspect $i | grep -iA 3 label ;done

部署rabbitmq集群

root@D-master:~/consul_rabbitmq_docker# docker stack deploy -c docker-compose_rabbitmq.yml rabbitmq
Creating service rabbitmq_rabbitmq-01
Creating service rabbitmq_rabbitmq-02
Creating service rabbitmq_rabbitmq-03

查看是否启动

root@D-master:~# docker ps -a |grep rabbitmq

这里会看到docker中依旧把rabbitmq集群已经起来了,但是在配置文件中没有把rabbitmq的端口暴露出来,所以暂时在web端访问不了。为了安全考虑,我们通过和rabbitmq在同一个docker service网段部署一个Haproxy,让Haproxy不仅仅负责访问调度机制,同时service访问的方式暴露rabbitmq的端口,从而进行访问MQ集群。

扩展

root@D-master:~# docker ps #找到对应容器的ID
root@D-master:~# docker exec -it 5f735718d62f /bin/bash #进到对应容器中交互操作

root@rabbitmq-01:/# find / -name "*plugins*"

root@rabbitmq-01:/# cat /etc/rabbitmq/enabled_plugins 
[rabbitmq_management,
rabbitmq_peer_discovery_consul,
rabbitmq_federation,
rabbitmq_federation_management,
rabbitmq_shovel,
rabbitmq_shovel_management].

root@rabbitmq-01:/# find / -name "*rabbitmq.conf*"

root@rabbitmq-01:/# cat /etc/rabbitmq/rabbitmq.conf
loopback_users.sa = false
cluster_formation.peer_discovery_backend = rabbit_peer_discovery_consul
cluster_formation.consul.host = consul
cluster_formation.node_cleanup.only_log_warning = true
cluster_formation.consul.svc_addr_auto = true
cluster_partition_handling = autoheal
vm_memory_high_watermark.relative = 0.8
disk_free_limit.absolute = 5GB
loopback_users.guest = false
listeners.tcp.default = 5672
default_pass = Passw0rd
default_user = admin
hipe_compile = false
management.listener.port = 15672
management.listener.ssl = false

配置haproxy代理端口

haproxy部署清单

root@D-master:~/consul_rabbitmq_docker# vim docker-compose_haproxy.yml

version: "3.6"
services:
  haproxy:
    image: olgac/haproxy-for-rabbitmq:1.8.14-alpine
    ports:
      - 15672:15672
      - 5672:5672
      - 1936:1936
    networks:
      - prod
    deploy:
      mode: global
networks:
  prod:
    external: true

部署haproxy

root@D-master:~/consul_rabbitmq_docker# docker stack deploy -c docker-compose_haproxy.yml haproxy
Creating service haproxy_haproxy

查看是否启动

root@D-master:~/consul_rabbitmq_docker# ss -ntlp |grep 1936

root@D-master:~/consul_rabbitmq_docker# ps -ef |grep haproxy
root      13380  13348  0 14:01 ?        00:00:00 haproxy -W -db -f /usr/local/etc/haproxy/haproxy.cfg
root      13477  13380  0 14:01 ?        00:00:00 haproxy -W -db -f /usr/local/etc/haproxy/haproxy.cfg
root      13574   9914  0 14:01 pts/0    00:00:00 grep --color=auto haproxy

扩展

root@D-master:~# docker ps
root@D-master:~# docker exec -it 23b0dbed70ae /bin/sh
/ #
/ # find / -name "*haproxy.cfg*"
/usr/local/etc/haproxy/haproxy.cfg
/ #
/ # cat /usr/local/etc/haproxy/haproxy.cfg 

global
    log 127.0.0.1   local0
    log 127.0.0.1   local1 notice
    maxconn 4096

defaults
    log     global
    option  tcplog
    option  dontlognull
    timeout connect 6s
    timeout client 60s
    timeout server 60s

listen  stats
    bind *:1936
    mode http
    stats enable
    stats hide-version
    stats realm Haproxy\ Statistics
    stats uri /

listen rabbitmq
    bind   *:5672
    mode   tcp
    server rabbitmq-01 rabbitmq-01:5672 check
    server rabbitmq-02 rabbitmq-02:5672 check
    server rabbitmq-03 rabbitmq-03:5672 check

listen rabbitmq-ui
    bind   *:15672
    mode   http
    server rabbitmq-01 rabbitmq-01:15672 check
    server rabbitmq-02 rabbitmq-02:15672 check
    server rabbitmq-03 rabbitmq-03:15672 check
/ # 

验证集群

验证RabbitMQ集群

访问 http://IP:15672 RabbitMQ的控制后台,密码为:(admin/Passw0rd),密码在前面.yml文件中定义的。

在这里插入图片描述

验证haproxy后台

访问 http://IP:1936, 验证haproxy后台
在这里插入图片描述

更多咨询,关注微信公众号

Docker部署单机Rabbitmq

Kaivi

Docker环境部署准备

1.基础环境

[root@centos-7 ~]#cat /etc/redhat-release 
CentOS Linux release 7.8.2003 (Core)
[root@centos-7 ~]#docker --version
Docker version 19.03.12, build 48a66213fe

2.查看RabbitMQ版本

[root@centos-7 ~]#docker search RabbitMQ
NAME                                        DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
rabbitmq                                    RabbitMQ is an open source multi-protocol me…   3358                [OK]                
bitnami/rabbitmq                            Bitnami Docker Image for RabbitMQ               52                                      [OK]
tutum/rabbitmq                              Base docker image to run a RabbitMQ server      20                                      
kbudde/rabbitmq-exporter                    rabbitmq_exporter for prometheus                13                                      [OK]
frodenas/rabbitmq                           A Docker Image for RabbitMQ                     12                                      [OK]
cyrilix/rabbitmq-mqtt                       RabbitMQ MQTT Adapter                           9                                       [OK]
arm32v7/rabbitmq                            RabbitMQ is an open source multi-protocol me…   7                                       
arm64v8/rabbitmq                            RabbitMQ is an open source multi-protocol me…   5   
······

3.获取RabbitMQ最新镜像

[root@centos-7 ~]#docker pull rabbitmq:latest
latest: Pulling from library/rabbitmq
f08d8e2a3ba1: Downloading  8.584MB
3baa9cb2483b: Download complete 
f08d8e2a3ba1: Pull complete 
3baa9cb2483b: Pull complete 
94e5ff4c0b15: Pull complete 
1860925334f9: Pull complete 
b6e36f28fd4a: Pull complete 
1e6be3541bd4: Pull complete 
2c907953f9c1: Pull complete 
3740eb0c71c7: Pull complete 
295add2887ed: Pull complete 
850ed4d559eb: Pull complete 
b6c0fdc08bf3: Pull complete 
Digest: sha256:11b1b3443e1110591a1ab09ecd229669712161e21e7fdaff98575a4af09c8311
Status: Downloaded newer image for rabbitmq:latest
docker.io/library/rabbitmq:latest

4.查看本地下载镜像

[root@centos-7 ~]#docker images 
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
rabbitmq            latest              ea2a13ef38ba        3 days ago          156MB
hello-world         latest              bf756fb1ae65        8 months ago        13.3kB

5.运行镜像

[root@centos-7 ~]#docker run -d --name rabbitmq -p 5672:5672 -p 15672:15672 -v `pwd`/data:/var/lib/rabbitmq --hostname myRabbit -e RABBITMQ_DEFAULT_VHOST=my_vhost -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=123456 ea2a13ef38ba

参数说明参考:

参数说明:
-d 后台运行容器;
–name 指定容器名;
-p 指定服务运行的端口(5672:应用访问端口;15672:控制台Web端口号);
-v 映射目录或文件;
–hostname 主机名(RabbitMQ的一个重要注意事项是它根据所谓的 “节点名称” 存储数据,默认为主机名);
-e 指定环境变量;(RABBITMQ_DEFAULT_VHOST:默认虚拟机名;RABBITMQ_DEFAULT_USER:默认的用户名;RABBITMQ_DEFAULT_PASS:默认用户名的密码)
ea2a13ef38ba 表示镜像的ID

6.Docker run 后,使用docker ps 查看在运行中也存在RabbitMQ。web界面无法访问,需要进入进行配置

进入RabbitMQ

[root@centos-7 ~]#docker exec -it rabbitmq /bin/bash
root@myRabbit:/# 

开启web管理页面

在容器里面操作:
root@myRabbit:/# rabbitmq-plugins enable rabbitmq_management
root@myRabbit:/# exit            #退出容器

7.rabbitmq设置docker 运行自启动,先找到对应的rabbitmq的镜像ID

[root@centos-7 ~]#docker ps -a 
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                   PORTS                                                                                              NAMES
8513760b75a1        ea2a13ef38ba        "docker-entrypoint.s…"   About an hour ago   Up About an hour         4369/tcp, 0.0.0.0:5672->5672/tcp, 5671/tcp, 15691-15692/tcp, 25672/tcp, 0.0.0.0:15672->15672/tcp   rabbitmq
9e10e2045498        hello-world         "/hello"                 2 hours ago         Exited (0) 2 hours ago                                                                                                      blissful_swartz

8.设置RabbitMQ自启动

[root@centos-7 ~]#docker update 23365f7f39b2 --restart=always

9.重启docker

[root@centos-7 ~]#systemctl restart docker 

10.查看在运行容器

[root@centos-7 ~]#docker ps

11.最后访问rabbitmq的WEB界面
http://IP:15672/

账号为admin 密码为123456
在这里插入图片描述

更多咨询,关注微信公众号

Docker学习(3)-Docker镜像构建和使用

Kaivi

Docker 镜像与制作

Docker 镜像内是否包含内核(bootfs)?

首先,从镜像的体积大小来说,一个比较小的镜像(alpine)只有几 MB,而内核文件需要一百多 MB, 因此镜像里面是没有内核的,镜像在被启动为容器后将直接使用宿主机的内核,而镜像本身则只提供相应的 rootfs,即系统正常运行所必须的用户空间的文件系统,比如/dev/,/proc,/bin,/etc 等目录,所以容器当中基本是没有/boot 目录的,而/boot 当中保存的就是与内核相关的文件和目录。
讨论论坛

Docker 镜像为什么没有提供内核?

若提供了内核,那么每个镜像的体积将至少一百 MB 以上,并且基于同一个基础镜像构建的镜像都有很大一部分冗余,容器的实质就是互相隔离的不同进程,也就是在用户空间运行的程序,而无需各自有自己的内核,共同使用主机的内
核即可。如果使用了内核,那么容器就不再是容器了,而属于虚拟机。

Docker 镜像存在的各个阶段和状态可以从下图看出:
在这里插入图片描述
Docker 镜像构建的过程就是一层一层新增内容的过程,其中每一层及其下面的所有层都可以构建为独立的镜像
构建镜像必须有一个引用的父镜像,一般的基础镜像(父镜像)均使用 Linux 某发行版官方提供的基础镜像,该基础镜像中包含了一个 Linux 操作用户空间所需的所有命令和资源。之后的业务镜像就可以在基础镜像上一层一层的构建。

手动构建 nginx 镜像

Docker 镜像的构建类似于虚拟机的模板制作,即按照公司的实际业务需求将需要安装的软件、相关配置等基础环境配置完成,然后将虚拟机再提交为模板,最后再批量从模板批量创建新的虚拟机,这样可以极大的简化业务中相同环境的虚拟机运行环境的部署工作。Docker的镜像构建分为手动构建和自动构建(基于DockerFile),企业通常都是基于 Dockerfile 构建镜像。

手动构建镜像实际上就是在创建并运行的基础容器中安装相应的软件和配置好相应的环境,并手动提交为新的镜像。大致过程如下:

下载镜像并初始化系统

基于某个基础镜像之上重新制作 因此需要先有一个基础镜像,本次使用 官方提供的 centos 镜像为基础:

root@Docker-1:~# docker pull centos:7.7.1908
root@Docker-1:~# docker run -it centos:7.7.1908 /bin/bash
[root@dc356876188e /]# yum install wget -y
[root@c1d6bea96f0b /]# cd /etc/yum.repos.d/
[root@c1d6bea96f0b yum.repos.d]# wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
[root@c1d6bea96f0b yum.repos.d]# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo

在容器中安装配置 nginx

[root@dc356876188e /]# yum install nginx -y
[root@dc356876188e /]# yum install -y vim pcre pcre-devel zlib zlib-devel openssl openssl-devel iproute net-tools iotop

关闭 nginx 默认的后台运行

[root@c1d6bea96f0b ~]# vim /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
daemon off;  # 添加该行
......

编写测试网页

[root@c1d6bea96f0b ~]# vim /usr/share/nginx/html/index.html
[root@c1d6bea96f0b ~]# cat /usr/share/nginx/html/index.html
NGINX TEST

提交为镜像

# -a 指定镜像构建者信息,-m 指定注释信息,跟上容器ID,指定镜像仓库和标签TAG
root@Docker-1:~# docker commit -a "kaivi<likai.tech>" -m "nginx test image-1" c1d6bea96f0b nginx-1.16.1:manual-conf
sha256:5e2756b81617ad28e51f7c101ca5981594d9d865d1970e0fbca412175db89795

root@Docker-1:~# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx-1.16.1        manual-conf         5e2756b81617        24 seconds ago      459MB

从新构建的 nginx 镜像启动容器

root@Docker-1:~# docker run -it -p 8080:80  5e2756b81617 nginx
。。。 #在后端运行

root@Docker-1:~# tty
/dev/pts/1
root@Docker-1:~# ss -ntl |grep 8080
LISTEN   0         20480                     *:8080                   *:*    

访问测试

访问:http://172.20.32.101:8080/
在这里插入图片描述

基于 Dockerfile 构建编译版 nginx 镜像

DockerFile 是一种可以被 Docker 程序解释的规格文件,DockerFile 由一条条命令组成,每条命令对应 linux 下面的一条命令,Docker 程序将这些 Dockerfile指令再翻译成真正的 linux 命令,其有自己的书写方式和支持的命令,Docker 程序读取 DockerFile 并根据指令生成 Docker 镜像,相比手动制作镜像的方式,DockerFile 更能直观的展示镜像是怎么产生的,有了写好的各种各样 DockerFile文件,当后期某个镜像有额外的需求时,只要在之前的 DockerFile 添加或者修改相应的操作即可重新生成新的 Docke 镜像,避免了重复手动制作镜像的麻烦。使用Dockerfile 构建镜像大体分为后面涉及的步骤。

一般来说,在 Dockerfile 中能够调用的命令在普通的终端中都可以调用。
一般 Dockerfile 包括以下的指令,这些指令都是放在每行的开头:
https://docs.docker.com/engine/reference/builder/#参考文献

FROM
FROM [--platform=<platform>] <image> [AS <name>]
Or
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
Or
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]
# FROM 指令用于引用基础镜像(父镜像),一般该指令位于Dockerfile的第一行(#开头的注释不算),
# 但是ARG指令可以在FROM之前。

ARG
ARG <name>[=<default value>]
# ARG 指令用于声明变量,在使用docker build构建镜像时可以使用--build-arg <var>=<value>
# 来指定所声明的变量

RUN
# 该命令最常使用,用来运行常见的命令(在终端能用的命令其都能解析)。
# RUN 指令有两种形式来运行命令:
  # 1.使用shell运行命令:
RUN <command> :(默认使用/bin/sh -c运行该command,如果在windows则使用cmd /S /C运行该command)
  # 2. 使用可执行文件执行,该情况下不会调用shell,需要指定使用什么可执行文件来执行命令
RUN ["executable", "param1", "param2"] :(exec 形式)需要先指定一个可执行文件,再指定参数

ADD
ADD [--chown=<user>:<group>] <src>... <dest>
# ADD 指令用于向镜像添加文件或者目录,如果是打包和压缩格式(.tar.gz/.tar.xz/.tar.bz2),则
# 该命令会解压,但是(.zip)文件在添加前需要先安装unzip工具。可以指定多个源,ADD 默认将这些
# 源的路径处理为在当前构建镜像的目录中,并且彼此之间是相对路径关系。

COPY
COPY [--chown=<user>:<group>] <src>... <dest>
# COPY 指令用于复制文件到镜像,不会解压。

ENV
ENV <key> <value>
ENV <key>=<value> ...
# ENV 指令用于设置镜像启动为容器时的环境变量。

EXPOSE
EXPOSE <port> [<port>/<protocol>...]
# 该指令用于向主机暴露端口,后面直接接端口,多个用空格分隔。

LABEL
LABEL <key>=<value> <key>=<value> <key>=<value> ...
# LABEL 用于指定该镜像的作者信息。
# 如:
LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates that label-values can span multiple lines."

STOPSIGNAL
STOPSIGNAL signal
# 该指令用来设置使得容器退出的信号

USER
USER <user>[:<group>] or
USER <UID>[:<GID>]
# 用来指定在Dockerfile中的指令随后以什么身份运行,如果没有该用户,默认使用root
# 该指令一般不用

VOLUME
# 该指令用来创建一个挂载点,并标记为其挂载本地主机卷或者其它的容器卷。
VOLUME ["/data"]

WORKDIR
WORKDIR /path/to/workdir
# 为其后的RUN, CMD, ENTRYPOINT, COPY and ADD等指令设置工作文件夹,不存在则创建。

Dockerfile 的格式约定:

# Comment
INSTRUCTION arguments

Dockerfile 使用#号作为注释符,在行中间的#号不视为注释,而视为参数
INSTRUCTION Dockerfile 指令,不区分大小写,约定使用大写
arguments 每个指令的参数,最常见的就是各种常用的 linux 基础命令

另外,第一行指令必须是FROM,指定该镜像时基于哪一个父镜像构建。

# test build
FROM centos:latest
RUN ...
RUN ...

除非使用ARG指令声明的变量,导致FROM指令不在第一行

ARG  CODE_VERSION=latest
FROM base:${CODE_VERSION}
CMD  /code/run-app
...

RUN指令在 Dockerfile 中大量使用,一般用法是直接跟命令

# test build
FROM centos:latest

# 一般像下面这样使用
RUN /usr/bin/mkdir -p /usr/local/nginx/conf.d 
RUN ...

但是也可以使用下面的格式,使用列表将命令和参数传给RUN指令

# test build
FROM centos:latest

# 也可以像下面这样使用
RUN ["/bin/bash", "-c", "/usr/bin/mkdir -p /usr/local/nginx/conf.d"]
RUN ...

更详细的用法参考官方说明:

https://docs.docker.com/engine/reference/builder/#Dockerfile官方说明

https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#编写Dockerfile的最佳实践

下载 centos 基础镜像

~$ docker pull centos:7.5.1804

编辑 Dockerfile

root@Docker-1:~# cd /opt/
root@Docker-1:/opt# mkdir dockerfile/nginx -p
root@Docker-1:/opt# cd dockerfile/nginx/
root@Docker-1:/opt/dockerfile/nginx# vim Dockerfile  #生成的镜像的时候会在执行命令的当前目录查找Dockerfile 文件,所以名称不可写错,而且D必须大写
#Dcoker image for  installation of nginx
#
FROM centos:7.7.1908

LABEL maintainer="kaivi <www.likai.tech>"

ENV password 123456

RUN rpm -ivh http://mirrors.aliyun.com/epel/epel-release-latest-7.noarch.rpm

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 unzip

ADD nginx-1.16.1.tar.gz /usr/local/src

RUN cd /usr/local/src/nginx-1.16.1 && ./configure --prefix=/usr/local/nginx --with-http_sub_module && make && make install

RUN cd /usr/local/nginx

ADD nginx.conf /usr/local/nginx/conf/nginx.conf

RUN useradd nginx -s /sbin/nologin

RUN ln -sv /usr/local/nginx/sbin/nginx  /usr/sbin/nginx
# 用于访问验证是否成功
RUN echo "kaivi Dockerfile test ..." >  /usr/local/nginx/html/index.html

EXPOSE 80 443

CMD ["/usr/local/nginx","-g","daemon off;"]
# 指定基于该镜像启动容器后容器执行的运行的命令,每个Dockerfile只能有一条,
# 如果有多条则只有最后一条被执行                                          

如果在从该镜像启动容器的时候也指定了命令,那么指定的命令会覆盖 Dockerfile构建的镜像里面的 CMD 命令,即指定的命令优先级更高,Dockerfile 的优先级较低一些。

准备源码包和配置文件

把另外编译的nginx配置文件拷贝到当前文件夹以及nginx的二进制安装包

root@Docker-1:/opt/dockerfile/nginx# cp  /etc/nginx/nginx.conf .
root@Docker-1:/opt/dockerfile/nginx# cp  /usr/local/src/nginx-1.16.1.tar.gz .
root@Docker-1:/opt/dockerfile/nginx# ll
total 1028
drwxr-xr-x 2 root root    4096 Apr 18 02:04 ./
drwxr-xr-x 3 root root    4096 Apr 18 00:26 ../
-rw-r--r-- 1 root root     816 Apr 18 01:31 Dockerfile
-rw-r--r-- 1 root root 1032630 Apr 18 01:37 nginx-1.16.1.tar.gz
-rw-r--r-- 1 root root    1482 Apr 18 02:04 nginx.conf

nginx.conf文件可以先二进制编制之后把默认的配置文件拷贝过来

构建镜像

使用docker build命令构建镜像,构建镜像时该命令需要指定 Dockerfile 和构建镜像所需要的上下文(context),这里的上下文就是构建过程需要的各种文件。
构建镜像详细说明参看: Docker-builder

# -t 选项给新镜像指定仓库和标签(REPOSITORY:TAG)
# 该种用法表示dockerd会在当前目录找需要的上下文(文件)和Dockerfile
# 也可以使用-f选项指定Dockerfile文件位置
root@Docker-1:/opt/dockerfile/nginx# docker build -t nginx:v5 .
Sending build context to Docker daemon  1.038MB
Step 1/14 : FROM centos:7.7.1908
 ---> 08d05d1d5859
Step 2/14 : LABEL maintainer="kaivi <www.likai.tech>"
 ---> Using cache
 ---> ece8e70c6653
Step 3/14 : ENV password 123456
 ---> Using cache
 ---> 9ef6fa101697
Step 4/14 : RUN rpm -ivh http://mirrors.aliyun.com/epel/epel-release-latest-7.noarch.rpm
 ---> Using cache
 ---> 71273d2c5cf9
Step 5/14 : 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 unzip
 ---> Using cache
 ---> 6df38382d6f2
Step 6/14 : ADD nginx-1.16.1.tar.gz /usr/local/src
 ---> Using cache
 ---> ecf174bb26f0
Step 7/14 : RUN cd /usr/local/src/nginx-1.16.1 && ./configure --prefix=/usr/local/nginx --with-http_sub_module && make && make install
 ---> Using cache
 ---> 424d883a0282
Step 8/14 : RUN cd /usr/local/nginx
 ---> Using cache
 ---> 512ac72429ae
Step 9/14 : ADD nginx.conf /usr/local/nginx/conf/nginx.conf
 ---> 4bbf57ca373b
Step 10/14 : RUN useradd nginx -s /sbin/nologin
 ---> Running in a78f7495f355
Removing intermediate container a78f7495f355
 ---> 916eacfe2ae2
Step 11/14 : RUN ln -sv /usr/local/nginx/sbin/nginx  /usr/sbin/nginx
 ---> Running in 223b65d849d9
'/usr/sbin/nginx' -> '/usr/local/nginx/sbin/nginx'
Removing intermediate container 223b65d849d9
 ---> c4488baeef5e
Step 12/14 : RUN echo "kaivi Dockerfile test ..." >  /usr/local/nginx/html/index.html
 ---> Running in 640bbdd8905e
Removing intermediate container 640bbdd8905e
 ---> 91d95b58c8e1
Step 13/14 : EXPOSE 80 443
 ---> Running in 52dcea1975d1
Removing intermediate container 52dcea1975d1
 ---> 4f488f04781a
Step 14/14 : CMD ["/usr/local/nginx","-g","daemon off;"]
 ---> Running in 661dc57033ff
Removing intermediate container 661dc57033ff
 ---> 217964547b78
Successfully built 217964547b78
Successfully tagged nginx:v5
# 构建完成

使用 ARG 声明变量,在构建时指定变量值

# 使用ARG声明一个叫base_version的变量
#Dcoker image for installation of nginx
#
ARG base_version
  # 定义变量
#FROM centos:7.5.1804
FROM  ${base_version}
  # 使用变量
# 使用--build-arg 指定变量base_version的值为centos:7.7.1909
root@Docker-1:/opt/dockerfile/nginx#docker build --build-arg base_version=centos:7.7.1909 -t nginx:v5 .

查看已构建镜像

root@Docker-1:/opt/dockerfile/nginx# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               v5                  8b90ac5358a3        20 seconds ago      544MB

从构建的镜像启动容器

root@Docker-1:/opt/dockerfile/nginx# docker run -it --rm nginx:v5 /bin/bash
[root@5a536cb4b109 /]# ls 
anaconda-post.log  bin  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@5a536cb4b109 /]# pwd
/
[root@5a536cb4b109 /]# 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  5a536cb4b109
[root@5a536cb4b109 /]# ss -ntl
State       Recv-Q Send-Q                     Local Address:Port                                    Peer Address:Port              
[root@5a536cb4b109 /]# /usr/local/nginx/sbin/nginx 
[root@5a536cb4b109 /]# ss -ntl
State       Recv-Q Send-Q                     Local Address:Port                                    Peer Address:Port              
LISTEN      0      128                                    *:80                                                 *:*                  
[root@5a536cb4b109 /]# exit

后台启动容器

root@Docker-1:~# docker run -it -d  -p80:80 nginx:v5 /bin/bash
b0b805d0029b35392b23fc3e7803cd72f0a492ed4af01313f2533803d5b10bc2
root@Docker-1:~# ss -ntl |grep 80
LISTEN   0         20480                     *:80                     *:*     
#后面不加/bin/bash会出现container_linux.go:349的报错 

访问测试

root@Docker-1:~# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS                         NAMES
b0b805d0029b        nginx:v5            "/bin/bash"         About a minute ago   Up About a minute   443/tcp, 0.0.0.0:80->80/tcp   elegant_murdock

root@Docker-1:~# docker exec -it b0b805d0029b bash
[root@b0b805d0029b /]# cd /usr/local/nginx/html/
[root@b0b805d0029b html]# vim index.html 
[root@b0b805d0029b html]# cat index.html 
kaivi Dockerfile test ...
[root@b0b805d0029b html]# /usr/local/nginx/sbin/nginx
[root@b0b805d0029b html]# ss -ntl
State       Recv-Q Send-Q                     Local Address:Port                                    Peer Address:Port              
LISTEN      0      128                                    *:80                                                 *:*                  

访问 172.20.32.101:80
在这里插入图片描述

在构建镜像时 Docker 启动了相应的容器

Docker 在构建镜像时,实际上启动了相应的容器,每运行一个 Dockerfile 中的指令就相当于新开了一个镜像(中间层),最后一条指令运行后会将运行的容器提交为镜像。下面就记录了不同的镜像构建时间,镜像的 ID 会不同,也就是每运行一个指令,镜像ID 就变一次。

手动构建编译版 nginx 镜像

过程为在 centos 基础 镜像之上手动编译安装 nginx ,然后再提交为镜像。

下载并初始化系统

root@Docker-1:~# docker pull centos:7.7.1908
root@Docker-1:~# docker run -it docker.io/centos:7.7.1908 /bin/bash
[root@77bb67f4452e /]# yum install wget -y
[root@77bb67f4452e /]# rm /etc/yum.repos.d/*
rm: remove regular file '/etc/yum.repos.d/CentOS-Base.repo'? y
rm: remove regular file '/etc/yum.repos.d/CentOS-CR.repo'? y
rm: remove regular file '/etc/yum.repos.d/CentOS-Debuginfo.repo'? y
rm: remove regular file '/etc/yum.repos.d/CentOS-Media.repo'? y
rm: remove regular file '/etc/yum.repos.d/CentOS-Sources.repo'? y
rm: remove regular file '/etc/yum.repos.d/CentOS-Vault.repo'? y
rm: remove regular file '/etc/yum.repos.d/CentOS-fasttrack.repo'? y
[root@77bb67f4452e /]# wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
[root@77bb67f4452e /]# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo

在容器编译安装 nginx

[root@77bb67f4452e /]# yum install -y unzip vim gcc gcc-c++ automake lrzsz pcre pcre-devel zlib zlib-devel openssl openssl-devel iproute net-tools iotop
[root@77bb67f4452e /]# wget http://nginx.org/download/nginx-1.16.1.tar.gz
[root@77bb67f4452e /]# tar xvf nginx-1.16.1.tar.gz
[root@77bb67f4452e /]# cd nginx-1.16.1
[root@77bb67f4452e nginx-1.16.1]# ./configure  --prefix=/apps/nginx --with-http_sub_module
[root@77bb67f4452e nginx-1.16.1]#  make && make install

nginx 配置

关闭后台运行

[root@77bb67f4452e nginx-1.16.1]# cd /apps/nginx/
[root@77bb67f4452e nginx]# vim conf/nginx.conf
user  nginx;
worker_processes  auto;
daemon off; # 新增该行
...
[root@77bb67f4452e nginx]# ln -sv /apps/nginx/sbin/nginx /usr/sbin/nginx
'/usr/sbin/nginx' -> '/apps/nginx/sbin/nginx'

定义 html 测试界面

[root@77bb67f4452e nginx]# vim html/index.html 
<DOCTYPE html />
<head>
  <h1>Hello World Docker</h1>
</head>
<body>
  <p>This is a test...</p>
</body>       

创建用户和授权

[root@77bb67f4452e nginx]# useradd -u 2020 nginx -s /sbin/nologin 

[root@77bb67f4452e nginx]# chown nginx.nginx /apps/nginx/ -R

新开终端提交为镜像

root@Docker-1:~# tty
/dev/pts/1
root@Docker-1:~# docker commit -a "kaivi<www.likai.tech>" -m "nginx test images" 77bb67f4452e nginx:vv1
sha256:07f3f714d8cb065a0be0af1fa0ca9b70f356a7f23e47bed43166c9fb0033a69f
root@Docker-1:~# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               vv1                 07f3f714d8cb        17 seconds ago      522MB
......

启动镜像

root@Docker-1:~# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               vv1                 07f3f714d8cb        17 seconds ago      522MB
nginx               v1                  66c2720f919d        28 minutes ago      544MB
nginx-1.16.1        manual-conf         5e2756b81617        10 hours ago        459MB
nginx               1.16.1              16af99d71a72        40 hours ago        127MB
alpine              latest              a187dde48cd2        3 weeks ago         5.6MB
centos              latest              470671670cac        3 months ago        237MB
centos              7.7.1908            08d05d1d5859        5 months ago        204MB
root@Docker-1:~# docker run -it -p 82:80 nginx:vv1 nginx
#最后面的 nginx 是运行的命令,即镜像里面要运行一个 nginx 命令,所以才有了前面将 
#/usr/local/nginx/sbin/nginx 软连接到 /usr/sbin/nginx ,目的就是为了让系统可以执行此命令。

访问测试查看日志

root@Docker-1:~# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS                                 NAMES
670ec45ceb99        nginx:vv1           "nginx"             About a minute ago   Up About a minute   0.0.0.0:82->80/tcp                    affectionate_kare
77bb67f4452e        centos:7.7.1908     "/bin/bash"         20 minutes ago       Up 20 minutes                                             festive_mcclintock
ea18f12e6b70        nginx:v1            "/bin/bash"         30 minutes ago       Up 30 minutes       86/tcp, 0.0.0.0:80->80/tcp, 443/tcp   cocky_saha
root@Docker-1:~# docker logs -f  670ec45ceb99
......

访问 172.20.32.101:82
在这里插入图片描述

构建 Tomcat 业务镜像

在构建基于 tomcat 的业务镜像时,首先需要基于官方提供的 centos、debain、ubuntu、alpine 等基础镜像构建 JDK(Java 环境),然后再基于自定义的 JDK 镜像构建出业务需要的 tomcat 镜像。

构建 JDK 镜像

先基于官方提供的基础镜像,制作出安装了常用命令的自定义基础镜像,然后在基础镜像的基础之上,再制作 JDK 镜像、Tomcat 镜像等。业务镜像存放目录规整:

root@Docker-1:~# mkdir -pv /opt/dockerfile/{web/{nginx,tomcat,jdk,apache},system/{centos,ubuntu,redhat}}
mkdir: created directory '/opt/dockerfile/web'
mkdir: created directory '/opt/dockerfile/web/nginx'
mkdir: created directory '/opt/dockerfile/web/tomcat'
mkdir: created directory '/opt/dockerfile/web/jdk'
mkdir: created directory '/opt/dockerfile/web/apache'
mkdir: created directory '/opt/dockerfile/system'
mkdir: created directory '/opt/dockerfile/system/centos'
mkdir: created directory '/opt/dockerfile/system/ubuntu'
mkdir: created directory '/opt/dockerfile/system/redhat'

自定义 Centos 基础镜像

编写 Dockerfile 和构建脚本

root@Docker-1:~# docker pull centos:7.7.1908
root@Docker-1:~# cd /opt/dockerfile/system/centos
root@Docker-1:/opt/dockerfile/system/centos#vim Dockerfile
# CentOS base image , installed tools and created www user.

ARG base_version

FROM centos:7.7.1908

LABEL author="kaivi" \
      personal_site="www.likai.tech"

RUN rpm -ivh http://mirrors.aliyun.com/epel/epel-release-latest-7.noarch.rpm
        # install epel repo from aliyun.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
        # install basic tools for centos

RUN groupadd www -g 2022 && useradd www -u 2022 -g www
        # create www user and www group
# 构建脚本
#!/bin/bash

V="centos:7.7.1908"

docker build -t centos-base:v1 .  # 注意在当前目录构建

构建过程

root@Docker-1:/opt/dockerfile/system/centos# bash docker_build.sh 
......
Complete!
Removing intermediate container bcc5cdd3ac84
 ---> b80b6d13d6c2
Step 6/6 : RUN groupadd www -g 2022 && useradd www -u 2022 -g www
 ---> Running in cac77aefe297
Removing intermediate container cac77aefe297
 ---> 5fc2d6909f65
Successfully built 5fc2d6909f65
Successfully tagged centos-base:v1

查看构建的 centos 基础镜像

root@Docker-1:/opt/dockerfile/system/centos# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos-base         v1                  5fc2d6909f65        30 seconds ago      522MB

基于 Centos 基础镜像构建 JDK 镜像

准备 Dockerfile 文件

# JDK base image , based on centos-base:v1

FROM centos-base:v1

LABEL author="kaivi" \
      personal_site="www.likai.tech"

ADD jdk-8u241-linux-x64.tar.gz /usr/local/src

RUN ln -sv /usr/local/src/jdk1.8.0_241 /usr/local/jdk

ADD profile /etc/profile

ENV JAVA_HOME /usr/local/jdk
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib:$JRE_HOME/lib
ENV PATH $PATH:$JAVA_HOME/bin
    # set java related env var

RUN rm -rf /etc/localtime && ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
     && echo "Asia/Shanghai" > /etc/timezone
    # set time zone to Shanghai                                 

准备 JDK 和 profile 文件

root@Docker-1:/opt/dockerfile/system/centos# cd  /opt/dockerfile/web/jdk/
root@Docker-1:/opt/dockerfile/web/jdk# cp /etc/profile .
root@Docker-1:/opt/dockerfile/web/jdk# vim profile 

# /etc/profile: system-wide .profile file for the Bourne shell (sh(1))
# and Bourne compatible shells (bash(1), ksh(1), ash(1), ...).

if [ "${PS1-}" ]; then
  if [ "${BASH-}" ] && [ "$BASH" != "/bin/sh" ]; then
    # The file bash.bashrc already sets the default PS1.
    # PS1='\h:\w\$ '
    if [ -f /etc/bash.bashrc ]; then
      . /etc/bash.bashrc
    fi
  else
    if [ "`id -u`" -eq 0 ]; then
      PS1='# '
    else
      PS1='$ '
    fi
  fi
fi

if [ -d /etc/profile.d ]; then
  for i in /etc/profile.d/*.sh; do
    if [ -r $i ]; then
      . $i
    fi
  done
  unset i
fi

export JAVA_HOME="/usr/local/jdk"
export JRE_HOME="$JAVA_HOME/jre"
export CLASSPATH="$JAVA_HOME/lib:$JRE_HOME/lib"
export PATH="$PATH:$JAVA_HOME/bin"

准备构建脚本

root@Docker-1:/opt/dockerfile/web/jdk# vim docker_build.sh
\root@Docker-1:/opt/dockerfile/web/jdk# cat docker_build.sh 
#!/bin/bash

docker build -t jdk-base:v8.241 .

构建

root@Docker-1:/opt/dockerfile/web/jdk# ll
total 190008
drwxr-xr-x 2 root root      4096 Apr 18 11:54 ./
drwxr-xr-x 6 root root      4096 Apr 18 10:39 ../
-rw-r--r-- 1 root root        47 Apr 18 11:36 docker_build.sh
-rw-r--r-- 1 root root       581 Apr 18 10:54 Dockerfile
-rw-r--r-- 1 root root 194545143 Apr 18 11:51 jdk-8u241-linux-x64.tar.gz
-rw-r--r-- 1 root root       732 Apr 18 11:35 profile
root@Docker-1:/opt/dockerfile/web/jdk# bash docker_build.sh 
Sending build context to Docker daemon  194.6MB
Step 1/10 : FROM centos-base:v1
 ---> 5fc2d6909f65
Step 2/10 : LABEL author="kaivi"       personal_site="www.likai.tech"
 ---> Running in 8dedfdef43ef
Removing intermediate container 8dedfdef43ef
 ---> 7d14621a9581
Step 3/10 : ADD jdk-8u241-linux-x64.tar.gz /usr/local/src
 ---> e492b88d17af
Step 4/10 : RUN ln -sv /usr/local/src/jdk1.8.0_241 /usr/local/jdk
 ---> Running in d8242b5f8036
'/usr/local/jdk' -> '/usr/local/src/jdk1.8.0_241'
Removing intermediate container d8242b5f8036
 ---> 0d3449d54998
Step 5/10 : ADD profile /etc/profile
 ---> 8ffc5ab1f947
Step 6/10 : ENV JAVA_HOME /usr/local/jdk
 ---> Running in b133b7663668
Removing intermediate container b133b7663668
 ---> 53b3e7c19b91
Step 7/10 : ENV JRE_HOME $JAVA_HOME/jre
 ---> Running in 0fbe0c83238c
Removing intermediate container 0fbe0c83238c
 ---> cee812ece223
Step 8/10 : ENV CLASSPATH $JAVA_HOME/lib:$JRE_HOME/lib
 ---> Running in c1685eccba5d
Removing intermediate container c1685eccba5d
 ---> 407f7a82f638
Step 9/10 : ENV PATH $PATH:$JAVA_HOME/bin
 ---> Running in b92f23603351
Removing intermediate container b92f23603351
 ---> 09cb81e4162a
Step 10/10 : RUN rm -rf /etc/localtime && ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime      && echo "Asia/Shanghai" > /etc/timezone
 ---> Running in 8f2a08bf7875
Removing intermediate container 8f2a08bf7875
 ---> 0bb10498e7d1
Successfully built 0bb10498e7d1
Successfully tagged jdk-base:v8.241
# 构建成功

查看构建的镜像

root@Docker-1:/opt/dockerfile/web/jdk# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
jdk-base            v8.241              0bb10498e7d1        2 minutes ago       926MB
centos-base         v1                  5fc2d6909f65        About an hour ago   522MB

启动容器进入验证 JKD 环境

root@Docker-1:~# docker run -it jdk-base:v8.241 /bin/bash
[root@1453b7367e51 /]# java -version 
java version "1.8.0_241"
Java(TM) SE Runtime Environment (build 1.8.0_241-b07)
Java HotSpot(TM) 64-Bit Server VM (build 25.241-b07, mixed mode)
[root@1453b7367e51 /]# env 
HOSTNAME=1453b7367e51
TERM=xterm
JRE_HOME=/usr/local/jdk/jre
。。。。。。
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/jdk/bin
PWD=/
JAVA_HOME=/usr/local/jdk
SHLVL=1
HOME=/root
CLASSPATH=/usr/local/jdk/lib:/usr/local/jdk/jre/lib
_=/usr/bin/env

[root@1453b7367e51 /]# ll /etc/profile  # 查看profile文件
-rw-r--r-- 1 root root 732 Apr 18 11:35 /etc/profile

[root@1453b7367e51 /]# date   # 验证时间是否同步
Sat Apr 18 11:59:41 CST 2020
[root@1453b7367e51 /]# 

root@Docker-1:~# date
Sat Apr 18 11:59:51 CST 2020

基于 JDK 镜像构建 Tomcat8 镜像

基于前面自定义的 JDK 基础镜像,构建出通用的自定义 Tomcat 基础镜像,此镜像后期会被多个业务的多个服务共同引用(这些业务的运行环境需要相同的 JDK 版本和 相同的 Tomcat 版本)。

编辑 Dockerfile

root@Docker-1:/opt/dockerfile/web/jdk# cd /opt/dockerfile/web/tomcat/
root@Docker-1:/opt/dockerfile/web/tomcat# vim Dockerfile
#  tomcat image 

FROM jdk-base:v8.241

LABEL author="kaivi" \
      personal_site="www.likai.tech"

        # set some env vars
ENV TZ "Asia/Shanghai"
ENV LANG en_US.UTF-8
ENV TOMCAT_MAJOR_VERSION 8
ENV TOMCAT_MINOR_VERSION 5.54
ENV CATALINA_HOME /apps/tomcat
ENV APP_DIR ${CATALINA_HOME}/webapps

        # install tomcat binary package
RUN mkdir /apps
ADD apache-tomcat-8.5.54.tar.gz /apps
RUN ln -sv /apps/apache-tomcat-8.5.54 /apps/tomcat

准备 tomcat 二进制包和构建脚本

# 上传tomcat二进制包
root@Docker-1:/opt/dockerfile/web/tomcat# rz -E
# 构建脚本
root@Docker-1:/opt/dockerfile/web/tomcat# vim docker_build.sh
#!/bin/bash

docker build -t tomcat-base:v8.5.54 .
# 加执行权限
root@Docker-1:/opt/dockerfile/web/tomcat# chmod a+x docker_build.sh 
root@Docker-1:/opt/dockerfile/web/tomcat# ll
total 10088
drwxr-xr-x 2 root root     4096 Apr 18 12:11 ./
drwxr-xr-x 6 root root     4096 Apr 18 10:39 ../
-rw-r--r-- 1 root root 10312541 Apr 18 11:46 apache-tomcat-8.5.54.tar.gz
-rwxr-xr-x 1 root root       51 Apr 18 12:11 docker_build.sh*
-rw-r--r-- 1 root root      444 Apr 18 12:09 Dockerfile

构建镜像

root@Docker-1:/opt/dockerfile/web/tomcat# ./docker_build.sh 
Sending build context to Docker daemon  10.32MB
Step 1/11 : FROM jdk-base:v8.241
 ---> 0bb10498e7d1
Step 2/11 : LABEL author="kaivi"       personal_site="www.likai.tech"
 ---> Running in af58171ff0d9
Removing intermediate container af58171ff0d9
 ---> dc4cca941fb4
Step 3/11 : ENV TZ "Asia/Shanghai"
 ---> Running in 8b745284a1c1
Removing intermediate container 8b745284a1c1
 ---> cd02c205bc5a
Step 4/11 : ENV LANG en_US.UTF-8
 ---> Running in 1b8ddfb3cb76
Removing intermediate container 1b8ddfb3cb76
 ---> 8480e037032f
Step 5/11 : ENV TOMCAT_MAJOR_VERSION 8
 ---> Running in 9147df041bce
Removing intermediate container 9147df041bce
 ---> 259e3c44b36c
Step 6/11 : ENV TOMCAT_MINOR_VERSION 5.54
 ---> Running in fde56402e295
Removing intermediate container fde56402e295
 ---> 04cde29ce6a8
Step 7/11 : ENV CATALINA_HOME /apps/tomcat
 ---> Running in 09a5df706b38
Removing intermediate container 09a5df706b38
 ---> 439b870c4b70
Step 8/11 : ENV APP_DIR ${CATALINA_HOME}/webapps
 ---> Running in 6ec66e1a64ac
Removing intermediate container 6ec66e1a64ac
 ---> 1ba75797abe6
Step 9/11 : RUN mkdir /apps
 ---> Running in 57e980c3e2cb
Removing intermediate container 57e980c3e2cb
 ---> 73000ce8f8fd
Step 10/11 : ADD apache-tomcat-8.5.54.tar.gz /apps
 ---> c5f222f366ee
Step 11/11 : RUN ln -sv /apps/apache-tomcat-8.5.54 /apps/tomcat
 ---> Running in bf3ea7a2e875
‘/apps/tomcat’ -> ‘/apps/apache-tomcat-8.5.54’
Removing intermediate container bf3ea7a2e875
 ---> ec58914afd67
Successfully built ec58914afd67
Successfully tagged tomcat-base:v8.5.54
# 构建成功

验证
查看镜像和启动为容器

root@Docker-1:/opt/dockerfile/web/tomcat# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
tomcat-base         v8.5.54             ec58914afd67        47 seconds ago      940MB
jdk-base            v8.241              0bb10498e7d1        18 minutes ago      926MB
centos-base         v1                  5fc2d6909f65        About an hour ago   522MB

root@Docker-1:/opt/dockerfile/web/tomcat# docker run -it --rm tomcat-base:v8.5.54 /bin/bash

[root@1a2873f7fc4b /]# ll /apps/tomcat/bin/catalina.sh 
-rwxr-x--- 1 root root 24397 Apr  3 22:07 /apps/tomcat/bin/catalina.sh

[root@1a2873f7fc4b /]# cd /apps/tomcat/bin/

[root@1a2873f7fc4b bin]# ./catalina.sh start
Using CATALINA_BASE:   /apps/tomcat
Using CATALINA_HOME:   /apps/tomcat
Using CATALINA_TMPDIR: /apps/tomcat/temp
Using JRE_HOME:        /usr/local/jdk/jre
Using CLASSPATH:       /apps/tomcat/bin/bootstrap.jar:/apps/tomcat/bin/tomcat-juli.jar
Tomcat started.

[root@1a2873f7fc4b bin]# ss -ntl
State       Recv-Q Send-Q             Local Address:Port                            Peer Address:Port              
LISTEN      0      1                      127.0.0.1:8005                                       *:*                  
LISTEN      0      100                            *:8080                                       *:*                  

构建业务镜像

基于前面构建的 tomcat-base 镜像构建业务镜像。分别创建 app1 和 app2 两个目录表示不同的业务项目。

业务镜像 1
准备 Dockerfile

root@Docker-1:/opt/dockerfile/web/tomcat# mkdir tomcat-{app1,app2} -pv
mkdir: created directory 'tomcat-app1'
mkdir: created directory 'tomcat-app2'
root@Docker-1:/opt/dockerfile/web/tomcat# cd tomcat-app1/
root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app1# pwd
/opt/dockerfile/web/tomcat/tomcat-app1
root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app1# vim Dockerfile

# Tomcat webapp deploy image

FROM tomcat-base:v8.5.54

LABEL author="kaivi" \
      personal_site="www.likai.tech"

        # add a script to /tomcat/bin to start tomcat when container start
ADD run_tomcat.sh /apps/tomcat/bin/run_tomcat.sh

        # add business code to /tomcat/webapps/
ADD app1/* /apps/tomcat/webapps/app1/

RUN chown www.www /apps/ -R

        # expose ports
EXPOSE 8080 8005 8009

        # run tomcat when container start
CMD ["/apps/tomcat/bin/run_tomcat.sh"]

准备容器启动时启动 tomcat 的脚本

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app1#  vim run_tomcat.sh
#!/bin/bash

echo "172.20.32.101 duanxin.io" >> /etc/hosts
echo "nameserver 223.6.6.6" >> /etc/resolv.conf

su - www -c "/apps/tomcat/bin/catalina.sh start"
su - www -c "tail -f /etc/hosts"

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app1# chmod a+x run_tomcat.sh 

编写 app1 测试页面

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app1# mkdir app1
root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app1# vim app1/index.html
<DOCTYPE HTML/>
<head>
        <h1>A TEST for Tomcat app1 <h1/>
<head/>
<body>
        <p>Tomcat app1 test...<span>NICE!<span/><p/>
<body/>

准备容器构建脚本

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app1# vim docker_build.sh
#!/bin/bash

docker build -t tomcat:app1 .

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app1# chmod a+x docker_build.sh 

构建

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app1# ll
total 24
drwxr-xr-x 3 root root 4096 Apr 18 12:28 ./
drwxr-xr-x 4 root root 4096 Apr 18 12:17 ../
drwxr-xr-x 2 root root 4096 Apr 18 12:26 app1/
-rwxr-xr-x 1 root root   44 Apr 18 12:28 docker_build.sh*
-rw-r--r-- 1 root root  485 Apr 18 12:20 Dockerfile
-rwxr-xr-x 1 root root  281 Apr 18 12:23 run_tomcat.sh*
root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app1# ./docker_build.sh 
Sending build context to Docker daemon  5.632kB
Step 1/7 : FROM tomcat-base:v8.5.54
 ---> ec58914afd67
Step 2/7 : LABEL author="kaivi"       personal_site="www.likai.tech"
 ---> Running in 44260dc1d930
Removing intermediate container 44260dc1d930
 ---> 8509c73764ec
Step 3/7 : ADD run_tomcat.sh /apps/tomcat/bin/run_tomcat.sh
 ---> 7abca622da74
Step 4/7 : ADD app1/* /apps/tomcat/webapps/app1/
 ---> d8480dca21ac
Step 5/7 : RUN chown www.www /apps/ -R
 ---> Running in 9b07147f8ddd
Removing intermediate container 9b07147f8ddd
 ---> 4024c3d41a24
Step 6/7 : EXPOSE 8080 8005 8009
 ---> Running in 21f89a17a3c0
Removing intermediate container 21f89a17a3c0
 ---> 8b0cd44d07dc
Step 7/7 : CMD ["/apps/tomcat/bin/run_tomcat.sh"]
 ---> Running in 381e94d0d825
Removing intermediate container 381e94d0d825
 ---> ca80466f5f71
Successfully built ca80466f5f71
Successfully tagged tomcat:app1
# 构建成功

从镜像启动容器

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app1# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
tomcat              app1                ca80466f5f71        33 seconds ago      954MB
tomcat-base         v8.5.54             ec58914afd67        16 minutes ago      940MB
jdk-base            v8.241              0bb10498e7d1        34 minutes ago      926MB
root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app1# docker run -it -d -p8080:8080 tomcat:app1 
1d3b8cbb284dd808b183e07c4f55f5c3000f7b222005d5268e4812edc9a3e497

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app1# ss -ntl |grep 8080
LISTEN   0         20480                     *:8080                   *:*       

访问测试

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app1# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                        NAMES
1d3b8cbb284d        tomcat:app1         "/apps/tomcat/bin/ru…"   2 minutes ago       Up 2 minutes        8005/tcp, 8009/tcp, 0.0.0.0:8080->8080/tcp   trusting_ptolemy
1453b7367e51        jdk-base:v8.241     "/bin/bash"              34 minutes ago      Up 34 minutes                                                    adoring_sutherland
ea18f12e6b70        nginx:v1            "/bin/bash"              3 hours ago         Up 3 hours          86/tcp, 0.0.0.0:80->80/tcp, 443/tcp          cocky_saha
root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app1# docker exec -it 1d3b8cbb284d /bin/bash

[root@1d3b8cbb284d /]# ss -ntl
State       Recv-Q Send-Q             Local Address:Port                            Peer Address:Port              
LISTEN      0      1                      127.0.0.1:8005                                       *:*                  
LISTEN      0      100                            *:8080                                       *:*           

在这里插入图片描述
在这里插入图片描述
业务镜像 2
准备 Dockerfile

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app2# pwd
/opt/dockerfile/web/tomcat/tomcat-app2
root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app2# vim Dockerfile 
# Tomcat webapp deploy image

FROM tomcat-base:v8.5.54

LABEL author="kaivi" \
      personal_site="www.likai.tech"

        # add a script to /tomcat/bin to start tomcat when container start
ADD run_tomcat.sh /apps/tomcat/bin/run_tomcat.sh

        # add business code to /tomcat/webapps/
ADD app2/* /apps/tomcat/webapps/app2/

RUN chown www.www /apps/ -R #不修改权限 后面无法写入日志导致服务启动失败

        # expose ports
EXPOSE 8080 8005 8009

        # run tomcat when container start
CMD ["/apps/tomcat/bin/run_tomcat.sh"]                                         

server.xml文件部署的时候注意关闭自动部署以及自动解压
准备容器启动时启动 tomcat 的脚本

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app2# vim run_tomcat.sh
#!/bin/bash

echo "172.20.32.101 duanxin.io" >> /etc/hosts
echo "nameserver 223.6.6.6" >> /etc/resolv.conf

su - www -c "/apps/tomcat/bin/catalina.sh start"
su - www -c "tail -f /etc/hosts" #创建一个守护进程,监听一个变化不大的文件

编写 app2 测试页面

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app2# mkdir app2
root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app2# vim app2/index.html
<DOCTYPE HTML/>
<head>
        <h1>A TEST for Tomcat app2 <h1/>
<head/>
<body>
        <p>Tomcat app2 test...<span>NICE!<span/><p/>
<body/>

主备容器构建脚本

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app2# vim docker_build.sh
#!/bin/bash

docker build -t tomcat:app2 .

构建

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app2# ./docker_build.sh 
Sending build context to Docker daemon  6.144kB
Step 1/7 : FROM tomcat-base:v8.5.54
 ---> ec58914afd67
Step 2/7 : LABEL author="kaivi"       personal_site="www.likai.tech"
 ---> Using cache
 ---> 8509c73764ec
Step 3/7 : ADD run_tomcat.sh /apps/tomcat/bin/run_tomcat.sh
 ---> b2ea0fadebfe
Step 4/7 : ADD app2/* /apps/tomcat/webapps/app2/
 ---> 2eb6ac24beae
Step 5/7 : RUN chown www.www /apps/ -R
 ---> Running in 7becf466e6a8
Removing intermediate container 7becf466e6a8
 ---> 7de7462dea98
Step 6/7 : EXPOSE 8080 8005 8009
 ---> Running in f54eeaee6b75
Removing intermediate container f54eeaee6b75
 ---> 08e605894757
Step 7/7 : CMD ["/apps/tomcat/bin/run_tomcat.sh"]
 ---> Running in 76ff5d601d03
Removing intermediate container 76ff5d601d03
 ---> 6ad29a04f9a9
Successfully built 6ad29a04f9a9
Successfully tagged tomcat:app2
# 构建成功

从镜像启动

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app2# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
tomcat              app2                6ad29a04f9a9        40 seconds ago      954MB
tomcat              app1                ca80466f5f71        3 hours ago         954MB
tomcat-base         v8.5.54             ec58914afd67        4 hours ago         940MB
jdk-base            v8.241              0bb10498e7d1        4 hours ago         926MB
centos-base         v1                  5fc2d6909f65        5 hours ago         522MB
......
root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app2# docker run -it -d -p 8081:8080 tomcat:app2
155eab9eafc871ece2b177a190077397f3744c8528ce3241e11022b52672d384
root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app2#  ss -ntl | grep 8081
LISTEN   0         20480                     *:8081                   *:*       

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app2# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                        NAMES
155eab9eafc8        tomcat:app2         "/apps/tomcat/bin/ru…"   21 seconds ago      Up 20 seconds       8005/tcp, 8009/tcp, 0.0.0.0:8081->8080/tcp   sleepy_cori
1d3b8cbb284d        tomcat:app1         "/apps/tomcat/bin/ru…"   3 hours ago         Up 3 hours          

root@Docker-1:/opt/dockerfile/web/tomcat/tomcat-app2# docker exec -it 155eab9eafc8 /bin/bash
[root@155eab9eafc8 /]# ss -ntl
State       Recv-Q Send-Q             Local Address:Port                            Peer Address:Port              
LISTEN      0      1                      127.0.0.1:8005                                       *:*                  
LISTEN      0      100                            *:8080                                       *:*    

访问测试
访问 http://172.20.32.101:8081/
在这里插入图片描述
访问 http://172.20.32.101:8081/app2/
在这里插入图片描述

基于 alpine 和 ubuntu 构建镜像

基于 alpine 构建镜像

在基于 alpine 构建镜像时,需要注意 alpine 的一些基础命令不同于 centos 或者ubuntu 系统,主要用到的是安装软件命令apk update和apk add命令,添加用户和组的adduser和addgroup命令。

构建 alpine 基础镜像
Dockerfile

root@Docker-1:~# cd /opt/dockerfile/system/
root@Docker-1:/opt/dockerfile/system# ll
total 20
drwxr-xr-x 5 root root 4096 Apr 18 10:39 ./
drwxr-xr-x 5 root root 4096 Apr 18 10:39 ../
drwxr-xr-x 2 root root 4096 Apr 18 10:47 centos/
drwxr-xr-x 2 root root 4096 Apr 18 10:39 redhat/
drwxr-xr-x 2 root root 4096 Apr 18 10:39 ubuntu/
root@Docker-1:/opt/dockerfile/system# mkdir alpine
root@Docker-1:/opt/dockerfile/system# cd alpine/
root@Docker-1:/opt/dockerfile/system/alpine# vim Dockerfile
# A alpine base image with some tools installed

FROM alpine:latest

LABEL author="kaivi" \
      personal_site="www.likai.tech"
          # change the pkg source to aliyun
          # http://mirrors.aliyun.com/alpine/v3.11/main
          # http://mirrors.aliyun.com/alpine/v3.11/community
COPY repositories /etc/apk/repositories

          # install basic tools and cmd
RUN apk update && apk add iotop gcc libgcc libc-dev libcurl \
    libc-utils pcre-dev zlib-dev libnfs make pcre pcre2 zip \
    unzip net-tools pstree wget libevent libevent-dev iproute2

更改 alpine 包源为阿里云的源
在这里插入图片描述

root@Docker-1:/opt/dockerfile/system/alpine# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
alpine              latest              a187dde48cd2        3 weeks ago         5.6MB
......
root@Docker-1:/opt/dockerfile/system/alpine# docker run -it --rm alpine:latest sh
/ # cat /etc/apk/repositories 
http://dl-cdn.alpinelinux.org/alpine/v3.11/main
http://dl-cdn.alpinelinux.org/alpine/v3.11/community

# 替换上面的 dl-cdn.alpinelinux.org 改成 mirrors.aliyun.com

/ # vi /etc/apk/repositories 
/ # cat /etc/apk/repositories 
#http://dl-cdn.alpinelinux.org/alpine/v3.11/main
#http://dl-cdn.alpinelinux.org/alpine/v3.11/community

http://mirrors.aliyun.com/alpine/v3.11/main
http://mirrors.aliyun.com/alpine/v3.11/community

构建脚本

root@Docker-1:/opt/dockerfile/system/alpine# vim docker_build.sh 
#!/bin/bash
docker build -t alpine-base:v1 .
root@Docker-1:/opt/dockerfile/system/alpine# chmod u+x docker_build.sh 

构建和查看
构建

root@Docker-1:/opt/dockerfile/system/alpine# ./docker_build.sh 
Sending build context to Docker daemon  1.038MB
Step 1/4 : FROM alpine:latest
 ---> a187dde48cd2
Step 2/4 : LABEL author="kaivi"       personal_site="www.likai.tech"
 ---> Using cache
 ---> 0580a9d9e882
Step 3/4 : COPY repositories /etc/apk/repositories
 ---> Using cache
 ---> 9fc2e55e1e26
Step 4/4 : RUN apk update && apk add iotop gcc libgcc libc-dev libcurl     libc-utils pcre-dev zlib-dev libnfs make pcre pcre2 zip     unzip net-tools pstree wget libevent libevent-dev iproute2
 ---> Running in d2b8e2724ac2
fetch http://mirrors.aliyun.com/alpine/v3.11/main/x86_64/APKINDEX.tar.gz
fetch http://mirrors.aliyun.com/alpine/v3.11/community/x86_64/APKINDEX.tar.gz
v3.11.5-56-gd94bd50429 [http://mirrors.aliyun.com/alpine/v3.11/main]
v3.11.5-54-g70c5111c08 [http://mirrors.aliyun.com/alpine/v3.11/community]
OK: 11271 distinct packages available
(1/48) Installing libgcc (9.2.0-r4)
(2/48) Installing libstdc++ (9.2.0-r4)
(3/48) Installing binutils (2.33.1-r0)
......
(47/48) Installing zip (3.0-r7)
(48/48) Installing zlib-dev (1.2.11-r3)
Executing busybox-1.31.1-r9.trigger
Executing ca-certificates-20191127-r1.trigger
OK: 183 MiB in 62 packages
Removing intermediate container d2b8e2724ac2
 ---> 644eb1be20b8
Successfully built 644eb1be20b8
Successfully tagged alpine-base:v1
# 构建完成
root@Docker-1:/opt/dockerfile/system/alpine# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
alpine-base         v1                  644eb1be20b8        24 seconds ago      180MB
......

root@Docker-1:/opt/dockerfile/system/alpine# docker run --rm -it alpine-base:v1 /bin/sh
/ # ping 114.114.114.114
PING 114.114.114.114 (114.114.114.114): 56 data bytes
64 bytes from 114.114.114.114: seq=0 ttl=127 time=15.745 ms
64 bytes from 114.114.114.114: seq=1 ttl=127 time=16.932 ms
^C
--- 114.114.114.114 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 15.745/16.338/16.932 ms
/ # ping www.baidu.com
PING www.baidu.com (61.135.169.121): 56 data bytes
64 bytes from 61.135.169.121: seq=0 ttl=127 time=3.724 ms
^C
--- www.baidu.com ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 3.724/3.724/3.724 ms
/ # ifconfig 
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:06  
          inet addr:172.17.0.6  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:18 errors:0 dropped:0 overruns:0 frame:0
          TX packets:19 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:1708 (1.6 KiB)  TX bytes:1625 (1.5 KiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
/ # apk update # 查看阿里云的源是否成功生效
fetch http://mirrors.aliyun.com/alpine/v3.11/main/x86_64/APKINDEX.tar.gz`在这里插入代码片`
fetch http://mirrors.aliyun.com/alpine/v3.11/community/x86_64/APKINDEX.tar.gz
v3.11.5-56-gd94bd50429 [http://mirrors.aliyun.com/alpine/v3.11/main]
v3.11.5-54-g70c5111c08 [http://mirrors.aliyun.com/alpine/v3.11/community]
OK: 11271 distinct packages available

基于 alpine 基础镜像构建 nginx 镜像

Dockerfile

root@Docker-1:/opt/dockerfile/system/alpine# mkdir nginx
root@Docker-1:/opt/dockerfile/system/alpine# vim nginx/Dockerfile 
#nginx base image , based on alpine-base:v1
FROM alpine-base:v1

ADD nginx-1.16.1.tar.gz /opt/

RUN cd /opt/nginx-1.16.1 && ./configure --prefix=/apps/nginx && make && make install && ln -sv /apps/nginx/sbin/nginx /usr/bin/nginx

RUN addgroup -g 2020 -S nginx && adduser -s /sbin/nologin -S -D -u 2020 -G nginx nginx

COPY nginx.conf /apps/nginx/conf/nginx.conf

ADD Development_code.tar.gz /data/nginx/html

RUN chown nginx.nginx /data/nginx/ /apps/nginx/ -R

EXPOSE 80 443

CMD ["/apps/nginx"]

构建脚本

root@Docker-1:/opt/dockerfile/system/alpine# cd nginx/
root@Docker-1:/opt/dockerfile/system/alpine/nginx# vim docker_build.sh 
#!/bin/bash
docker build -t nginx-alpine:v1 .

root@Docker-1:/opt/dockerfile/system/alpine/nginx# chmod u+x docker_build.sh 

构建上下文准备

root@Docker-1:/opt/dockerfile/system/alpine/nginx# rz -E #上传nginx二进制安装包
root@Docker-1:/opt/dockerfile/system/alpine/nginx# mkdir Development_code

# 测试界面
root@Docker-1:/opt/dockerfile/system/alpine/nginx# vim Development_code/index.html
<DOCTYPE HTML/>
<head>
        <h1>A TEST for alpine... <h1/>
<head/>
<body>
        <p>Based alpine\'s nginx deployment.<span>wa...<span/><p/>
<body/>
root@Docker-1:/opt/dockerfile/system/alpine/nginx# tar -cvf Development_code.tar.gz Development_code/*
Development_code/index.html

root@Docker-1:/opt/dockerfile/system/alpine/nginx# cp /usr/local/src/nginx-1.16.1/conf/nginx.conf .

root@Docker-1:/opt/dockerfile/system/alpine/nginx# ll
total 1048
drwxr-xr-x 3 root root    4096 Apr 18 16:47 ./
drwxr-xr-x 3 root root    4096 Apr 18 16:36 ../
drwxr-xr-x 2 root root    4096 Apr 18 16:43 Development_code/
-rw-r--r-- 1 root root   10240 Apr 18 16:46 Development_code.tar.gz
-rwxr--r-- 1 root root      46 Apr 18 16:38 docker_build.sh*
-rw-r--r-- 1 root root     504 Apr 18 16:36 Dockerfile
-rw-r--r-- 1 root root 1032630 Apr 18 01:37 nginx-1.16.1.tar.gz
-rw-r--r-- 1 root root    2656 Apr 18 16:47 nginx.conf

nginx 配置

root@Docker-1:/opt/dockerfile/system/alpine/nginx# vim nginx.conf 
...
user  nginx;
daemon off;
...
http {
  ...
    server {
        listen       80;
        server_name  localhost;
        access_log  logs/host.access.log  main;
        location / {
            root   /data/nginx/html;
            index  index.html index.htm;
        }
        ...
    }
    ...
}

构建

root@Docker-1:/opt/dockerfile/system/alpine/nginx# ./docker_build.sh 
Sending build context to Docker daemon  1.052MB
Step 1/9 : FROM alpine-base:v1
 ---> 644eb1be20b8
Step 2/9 : ADD nginx-1.16.1.tar.gz /opt/
 ---> Using cache
 ---> 02a9d885ce4a
Step 3/9 : RUN cd /opt/nginx-1.16.1 && ./configure --prefix=/apps/nginx && make && make install && ln -sv /apps/nginx/sbin/nginx /usr/bin/nginx
 ---> Using cache
 ---> 8d2e969ada82
Step 4/9 : RUN addgroup -g 2020 -S nginx && adduser -s /sbin/nologin -S -D -u 2020 -G nginx nginx
 ---> Using cache
 ---> 8f1bde17d483
Step 5/9 : COPY nginx.conf /apps/nginx/conf/nginx.conf
 ---> Using cache
 ---> 8ad0f6605500
Step 6/9 : ADD Development_code.tar.gz /data/nginx/html
 ---> Using cache
 ---> 47d4407df50c
Step 7/9 : RUN chown nginx.nginx /data/nginx/ /apps/nginx/ -R
 ---> Using cache
 ---> d5ec7aceeb8e
Step 8/9 : EXPOSE 80 443
 ---> Using cache
 ---> 51233e047af8
Step 9/9 : CMD ["/apps/nginx"]
 ---> Using cache
 ---> 3fc77202b016
Successfully built 3fc77202b016
Successfully tagged nginx-alpine:v1

访问测试

root@Docker-1:~# cd /opt/dockerfile/system/alpine/nginx/
root@Docker-1:/opt/dockerfile/system/alpine/nginx# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx-alpine        v1                  3fc77202b016        45 seconds ago      209MB
alpine-base         v1                  644eb1be20b8        22 minutes ago      180MB

root@Docker-1:/opt/dockerfile/system/alpine/nginx# docker run -it -p 80:80 nginx-alpine:v1 tail -f /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  83c8c4f7ee36
root@Docker-1:/opt/dockerfile/system/alpine/nginx# docker ps
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS                         NAMES
83c8c4f7ee36        nginx-alpine:v1     "tail -f /etc/hosts"   About an hour ago   Up About an hour    0.0.0.0:80->80/tcp, 443/tcp   practical_tereshkova
root@Docker-1:/opt/dockerfile/system/alpine/nginx# docker exec -it 83c8c4f7ee36 sh
/ # /apps/nginx/sbin/nginx  #在容器中启动nginx
......

访问http://172.20.32.101/,由于根下没有 index.html 所以无法访问
在这里插入图片描述
访问http://172.20.32.101/Development_code/ 成功访问
在这里插入图片描述

基于 ubuntu 构建镜像

基于 ubuntu 构建镜像与其他系统大同小异

构建 ubuntu 基础镜像
Dockerfile

root@Docker-1:/opt/dockerfile/system/ubuntu# pwd
/opt/dockerfile/system/ubuntu
root@Docker-1:/opt/dockerfile/system/ubuntu# vim Dockerfile
# ubuntu base image with some tools installed

FROM ubuntu:latest

LABEL author="kaivi" \
      personal_site="www.likai.tech"

COPY sources.list /etc/apt/sources.list

RUN apt update && \
    apt install -y iproute2  ntpdate  tcpdump telnet traceroute \
    nfs-kernel-server nfs-common  lrzsz tree  openssl libssl-dev \
    libpcre3 libpcre3-dev zlib1g-dev ntpdate tcpdump telnet traceroute \
    gcc openssh-server lrzsz tree openssl libssl-dev libpcre3 libpcre3-dev \
    zlib1g-dev ntpdate tcpdump telnet traceroute iotop unzip zip make && \
    touch /tmp/linux.txt

sources.list

root@Docker-1:/opt/dockerfile/system/ubuntu# vim sources.list 

deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse

构建

root@Docker-1:/opt/dockerfile/system/ubuntu# vim docker_build.sh 

#!/bin/bash
docker build -t ubuntu-base:v1 .

root@Docker-1:/opt/dockerfile/system/ubuntu# chmod u+x docker_build.sh 

root@Docker-1:/opt/dockerfile/system/ubuntu# ll
total 20
drwxr-xr-x 2 root root 4096 Apr 18 18:29 ./
drwxr-xr-x 6 root root 4096 Apr 18 16:11 ../
-rwxr--r-- 1 root root   45 Apr 18 18:24 docker_build.sh*
-rw-r--r-- 1 root root  573 Apr 18 18:21 Dockerfile
-rw-r--r-- 1 root root  907 Apr 18 18:23 sources.list

#构建镜像
root@Docker-1:/opt/dockerfile/system/ubuntu# ./docker_build.sh 
Sending build context to Docker daemon   5.12kB
Step 1/4 : FROM ubuntu:latest
 ---> 4e5021d210f6
Step 2/4 : LABEL author="kaivi"       personal_site="www.likai.tech"
 ---> Using cache
 ---> a127319deb66
Step 3/4 : COPY sources.list /etc/apt/sources.list
 ---> Using cache
 ---> e6180393cf90
Step 4/4 : RUN apt update &&     apt install -y iproute2  ntpdate  tcpdump telnet traceroute     nfs-kernel-server nfs-common  lrzsz tree  openssl libssl-dev     libpcre3 libpcre3-dev zlib1g-dev ntpdate tcpdump telnet traceroute     gcc openssh-server lrzsz tree openssl libssl-dev libpcre3 libpcre3-dev     zlib1g-dev ntpdate tcpdump telnet traceroute iotop unzip zip make &&     touch /tmp/linux.txt
 ---> Using cache
 ---> 060ffdc4bf27
Successfully built 060ffdc4bf27
Successfully tagged ubuntu-base:v1
# 构建完成
注意:
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
  # 该警告意思是apt的命令行接口不稳定,慎用

#查看构建完成的镜像
root@Docker-1:/opt/dockerfile/system/ubuntu# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu-base         v1                  060ffdc4bf27        5 minutes ago       366MB
......

基于 ubuntu 基础镜像构建 nginx 镜像

Dockerfile

root@Docker-1:/opt/dockerfile/system/ubuntu# mkdir nginx
root@Docker-1:/opt/dockerfile/system/ubuntu# cd nginx/

root@Docker-1:/opt/dockerfile/system/ubuntu/nginx# vim Dockerfile
# A nginx image based on ubuntu

FROM ubuntu-base:v1

ADD nginx-1.16.1.tar.gz /usr/local/src

RUN cd /usr/local/src/nginx-1.16.1 && \
    ./configure --prefix=/apps/nginx && \
    make && make install && \
    ln -sv /apps/nginx/sbin/nginx /usr/bin && \
    rm -rf /usr/local/src/nginx-1.16.1 && \
    rm -rf /usr/local/src/nginx-1.16.1.tar.gz

ADD nginx.conf /apps/nginx/conf/nginx.conf

ADD Development_code.tar.gz /data/nginx/html

RUN groupadd -g 2021 nginx && \
    useradd -g nginx -s /usr/sbin/nologin -u 2021 nginx && \
    chown -R nginx.nginx /apps/nginx /data/nginx

EXPOSE 80 443

CMD ["/apps/nginx"]

构建

root@Docker-1:/opt/dockerfile/system/ubuntu/nginx# vim docker_build.sh
#!/bin/bash
docker build -t nginx-ubuntu:v1 .

root@Docker-1:/opt/dockerfile/system/ubuntu/nginx# chmod u+x docker_build.sh 

由于和之前的alpine的nginx构建基本差不多。直接复用即可

root@Docker-1:/opt/dockerfile/system/ubuntu/nginx# cp /opt/dockerfile/system/alpine/nginx/nginx.conf .
root@Docker-1:/opt/dockerfile/system/ubuntu/nginx# cp /opt/dockerfile/system/alpine/nginx/nginx-1.16.1.tar.gz .
root@Docker-1:/opt/dockerfile/system/ubuntu/nginx# cp /opt/dockerfile/system/alpine/nginx/Development_code.tar.gz .

修改测试界面

root@Docker-1:/opt/dockerfile/system/ubuntu/nginx# tar xf Development_code.tar.gz 
root@Docker-1:/opt/dockerfile/system/ubuntu/nginx# vim Development_code/index.html 
#
<DOCTYPE HTML/>
<head>
        <h1>A TEST for Ubuntu... <h1/>
<head/>
<body>
        <p>Based ubuntu\'s nginx deployment.<span>wa o ...<span/><p/>
<body/>
#
root@Docker-1:/opt/dockerfile/system/ubuntu/nginx# tar cvf Development_code.tar.gz Development_code/*
Development_code/index.html

root@Docker-1:/opt/dockerfile/system/ubuntu/nginx# rm -rf Development_code*
root@Docker-1:/opt/dockerfile/system/ubuntu/nginx# ll
total 1044
drwxr-xr-x 2 root root    4096 Apr 18 18:49 ./
drwxr-xr-x 3 root root    4096 Apr 18 18:33 ../
-rwxr--r-- 1 root root      45 Apr 18 18:37 docker_build.sh*
-rw-r--r-- 1 root root     606 Apr 18 18:36 Dockerfile
-rw-r--r-- 1 root root 1032630 Apr 18 18:40 nginx-1.16.1.tar.gz
-rw-r--r-- 1 root root    2664 Apr 18 18:39 nginx.conf
-rw-r--r-- 1 root root   10240 Apr 18 18:49 Development_code.tar.gz

# 构建
root@Docker-1:/opt/dockerfile/system/ubuntu/nginx# ./docker_build.sh 
Sending build context to Docker daemon  1.051MB
Step 1/8 : FROM ubuntu-base:v1
 ---> 060ffdc4bf27
Step 2/8 : ADD nginx-1.16.1.tar.gz /usr/local/src
 ---> Using cache
 ---> 4fdc3572f0e4
Step 3/8 : RUN cd /usr/local/src/nginx-1.16.1 &&     ./configure --prefix=/apps/nginx &&     make && make install &&     ln -sv /apps/nginx/sbin/nginx /usr/bin &&     rm -rf /usr/local/src/nginx-1.16.1 &&     rm -rf /usr/local/src/nginx-1.16.1.tar.gz
 ---> Using cache
 ---> aa96d2e91820
Step 4/8 : ADD nginx.conf /apps/nginx/conf/nginx.conf
 ---> Using cache
 ---> b55a1aca5867
Step 5/8 : ADD Development_code.tar.gz /data/nginx/html
 ---> Using cache
 ---> 7d3df02bae55
Step 6/8 : RUN groupadd -g 2021 nginx &&     useradd -g nginx -s /usr/sbin/nologin -u 2021 nginx &&     chown -R nginx.nginx /apps/nginx /data/nginx
 ---> Using cache
 ---> 4c09408b97e5
Step 7/8 : EXPOSE 80 443
 ---> Using cache
 ---> 41c1567c685e
Step 8/8 : CMD ["/apps/nginx"]
 ---> Using cache
 ---> d42a1310db5e
Successfully built d42a1310db5e
Successfully tagged nginx-ubuntu:v1
# 构建完成   

访问测试

root@Docker-1:/opt/dockerfile/system/ubuntu/nginx# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
nginx-ubuntu         v1                  d42a1310db5e        About a minute ago   382MB
ubuntu-base         v1                  060ffdc4bf27        26 minutes ago       366MB

root@Docker-1:/opt/dockerfile/system/ubuntu/nginx# docker run -it -d -p 80:80 nginx-ubuntu:v1 /bin/bash
c0a7a0b31bf6d50f59860ad189f8ebfc297d69bbbc1f56ed40ed476e65eb9ff3

root@Docker-1:/opt/dockerfile/system/ubuntu/nginx# lsof -i:80
COMMAND     PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
docker-pr 49074 root    4u  IPv6 458003      0t0  TCP *:http (LISTEN)

访问http://172.20.32.101/
访问现象和基于 alpine 时一样,由于根下没有 index.html 所以无法访问
在这里插入图片描述
在这里插入图片描述

构建 HAProxy 镜像

基于 centos-base 镜像构建 haproxy 镜像,将 haproxy 通过容器的方式运行
http://download.openpkg.org/components/cache/haproxy/#haproxy下载

准备 Dockerfile

root@Docker-1:~# cd /opt/dockerfile/system/centos/
root@Docker-1:/opt/dockerfile/system/centos# mkdir haproxy
root@Docker-1:/opt/dockerfile/system/centos# cd haproxy/

root@Docker-1:/opt/dockerfile/system/centos/haproxy# vim Dockerfile
# A HAProxy image based on centos-base:v1 with some tools installed
FROM centos-base:v1         

RUN yum install -y yum install gcc gcc-c++ glibc glibc-devel \
    pcre pcre-devel openssl openssl-devel systemd-devel net-tools \
    vim iotop bc zip unzip zlib-devel lrzsz tree screen lsof tcpdump \
    wget ntpdate

ADD haproxy-2.0.5.tar.gz /usr/local/src/

RUN cd /usr/local/src/haproxy-2.0.5 && \
    make ARCH=x86_64 TARGET=linux-glibc USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 \
    USE_SYSTEMD=1 USE_CPU_AFFINITY=1 PREFIX=/usr/local/haproxy && \
    make install PREFIX=/usr/local/haproxy && \
    cp haproxy /usr/sbin/ && \
    mkdir /usr/local/haproxy/run

ADD haproxy.cfg /etc/haproxy/

ADD run_haproxy.sh /usr/bin

EXPOSE 80 9999 #80用于访问 9999用于监听

CMD ["/usr/bin/run_haproxy.sh"]

准备 HAProxy 源码和配置

http://www.haproxy.org/download/2.0/src/haproxy-2.0.5.tar.gz#国外下载地址 需要科学上网

root@Docker-1:/opt/dockerfile/system/centos/haproxy# rz -E

# 编辑haproxy配置文件
root@Docker-1:/opt/dockerfile/system/centos/haproxy# vim haproxy.cfg

global
chroot /usr/local/haproxy
#stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin
uid 99
gid 99
daemon
nbproc 1
pidfile /usr/local/haproxy/run/haproxy.pid
log 127.0.0.1 local3 info

defaults
option http-keep-alive
option  forwardfor
mode http
timeout connect 300000ms
timeout client  300000ms
timeout server  300000ms

listen stats
 mode http
 bind 0.0.0.0:9999
 stats enable
 log global
 stats uri     /haproxy-status
 stats auth    haadmin:123456

listen  docker_test_run
 bind 0.0.0.0:80
 mode http
 log global
 balance roundrobin
 server web1  172.20.32.101:8080  check inter 3000 fall 2 rise 5
 server web2  172.20.32.102:8080  check inter 3000 fall 2 rise 5

准备镜像构建脚本

root@Docker-1:/opt/dockerfile/system/centos/haproxy# vim run_haproxy.sh
#!/bin/bash
/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg
tail -f /etc/hosts

# 加执行权限
root@Docker-1:/opt/dockerfile/system/centos/haproxy# chmod u+x run_haproxy.sh 

# 编辑构建脚本
root@Docker-1:/opt/dockerfile/system/centos/haproxy# vim docker_build.sh
#!/bin/bash
docker build -t haproxy-ubuntu:v1 .

# 加执行权限
root@Docker-1:/opt/dockerfile/system/centos/haproxy# chmod u+x docker_build.sh 

root@Docker-1:/opt/dockerfile/system/centos/haproxy# ll
total 2504
drwxr-xr-x 2 root root    4096 Apr 18 20:24 ./
drwxr-xr-x 3 root root    4096 Apr 18 19:19 ../
-rwxr--r-- 1 root root      48 Apr 18 20:24 docker_build.sh*
-rw-r--r-- 1 root root     760 Apr 18 20:15 Dockerfile
-rw-r--r-- 1 root root 2539226 Apr 18 20:13 haproxy-2.0.5.tar.gz
-rw-r--r-- 1 root root     680 Apr 18 20:20 haproxy.cfg
-rwxr--r-- 1 root root      77 Apr 18 20:22 run_haproxy.sh*

#构建
root@Docker-1:/opt/dockerfile/system/centos/haproxy# ./docker_build.sh 
Sending build context to Docker daemon  2.546MB
Step 1/8 : FROM centos-base:v1
 ---> 5fc2d6909f65
Step 2/8 : RUN yum install -y yum install gcc gcc-c++ glibc glibc-devel     pcre pcre-devel openssl openssl-devel systemd-devel net-tools     vim iotop bc zip unzip zlib-devel lrzsz tree screen lsof tcpdump     wget ntpdate
 ---> Using cache
 ---> 57ffe53d1e8c
Step 3/8 : ADD haproxy-2.0.5.tar.gz /usr/local/src/
 ---> Using cache
 ---> 482118c25cb7
Step 4/8 : RUN cd /usr/local/src/haproxy-2.0.5 &&     make ARCH=x86_64 TARGET=linux-glibc USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1     USE_SYSTEMD=1 USE_CPU_AFFINITY=1 PREFIX=/usr/local/haproxy &&     make install PREFIX=/usr/local/haproxy &&     cp haproxy /usr/sbin/ &&     mkdir /usr/local/haproxy/run
 ---> Using cache
 ---> de502b965fdd
Step 5/8 : ADD haproxy.cfg /etc/haproxy/
 ---> Using cache
 ---> 336162d98639
Step 6/8 : ADD run_haproxy.sh /usr/bin
 ---> Using cache
 ---> 8c2012534b01
Step 7/8 : EXPOSE 80 9999
 ---> Using cache
 ---> 6c59694b7da0
Step 8/8 : CMD ["/usr/bin/run_haproxy.sh"]
 ---> Using cache
 ---> 47b597b9cb7c
Successfully built 47b597b9cb7c
Successfully tagged haproxy-ubuntu:v1

从镜像启动容器

root@Docker-1:/opt/dockerfile/system/centos/haproxy# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
haproxy-ubuntu      v1                  47b597b9cb7c        55 seconds ago      787MB
......
root@Docker-1:/opt/dockerfile/system/centos/haproxy# docker run -it -p 80:80 -p 9999:9999 haproxy-ubuntu:v1 bash
[root@e5e34e1bf06a /]# haproxy -f /etc/haproxy/haproxy.cfg 
[root@e5e34e1bf06a /]# 
[root@e5e34e1bf06a /]# ss -ntl
State       Recv-Q Send-Q             Local Address:Port                            Peer Address:Port              
LISTEN      0      128                            *:9999                                       *:*                  
LISTEN      0      128                            *:80                                         *:*                  
[root@e5e34e1bf06a /]# 

在这里插入图片描述
后端的web1和web2现在处于down状态:
在这里插入图片描述

由于在Dockerfile配置中有ADD haproxy.cfg /etc/haproxy/ 会自动起来这个haproxy服务 所以在最后面不需要加bash也可以

root@Docker-1:/opt/dockerfile/system/centos/haproxy# docker run -it -p 80:80 -p 9999:9999 haproxy-ubuntu:v1 
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  79ce10f0b3c8

启动后端服务

在后端服务器172.20.32.101机器部署(本机)

root@Docker-1:~# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
haproxy-ubuntu      v1                  47b597b9cb7c        2 hours ago         787MB
nginx-ubuntu        v1                  d42a1310db5e        4 hours ago         382MB
ubuntu-base         v1                  060ffdc4bf27        4 hours ago         366MB
tomcat              app2                6ad29a04f9a9        7 hours ago         954MB
tomcat              app1                ca80466f5f71        10 hours ago        954MB

root@Docker-1:~# docker run -d -it -p 8080:8080 tomcat:app1  
180b61179821490e795d9300135003a73dfc87b0fa3d69ae3a638aaad7753ed8
root@Docker-1:~# ss -ntl
......
LISTEN        0              20480                                *:9999                              *:*            
LISTEN        0              20480                                *:8080                              *:*            
LISTEN        0              20480                                *:80                                *:*      
......

在这里插入图片描述
将 tomcat:app2部署到 172.20.32.102
172.20.32.101上面导出tomcat业务镜像,拷贝到172.20.32.102使用

root@Docker-1:~# docker save tomcat:app2 > /opt/tomcat:app2.tar.gz  

root@Docker-1:~# scp /opt/tomcat\:app2.tar.gz 172.20.32.102:/opt/tomcat\:app2.tar.gz
#这里可能需要一些时间

在172.20.32.102导入镜像

root@Docker-2:~# docker load < /opt/tomcat\:app2.tar.gz 
51505ea32d5f: Loading layer [==================================================>]  24.27MB/24.27MB
0c747fb19e38: Loading layer [==================================================>]  299.4MB/299.4MB
27853411f83c: Loading layer [==================================================>]  742.9kB/742.9kB
8ee048c0d621: Loading layer [==================================================>]  404.9MB/404.9MB
9866565c322a: Loading layer [==================================================>]   2.56kB/2.56kB
15567403b930: Loading layer [==================================================>]  3.072kB/3.072kB
4032e44635ce: Loading layer [==================================================>]  3.072kB/3.072kB
30dc82522c0e: Loading layer [==================================================>]  2.048kB/2.048kB
8eeeba765392: Loading layer [==================================================>]     15MB/15MB
3b202fd39753: Loading layer [==================================================>]  2.048kB/2.048kB
cd65936fedb7: Loading layer [==================================================>]  3.584kB/3.584kB
8e94fe36ca9f: Loading layer [==================================================>]  4.608kB/4.608kB
f7afa4a062d8: Loading layer [==================================================>]     15MB/15MB
Loaded image: tomcat:app2

root@Docker-2:~# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
tomcat              app2                6ad29a04f9a9        7 hours ago         954MB
nginx               1.16.1              16af99d71a72        2 days ago          127MB
centos              7.7.1908            08d05d1d5859        5 months ago        204MB
root@Docker-2:~# docker run -d -it -p 8080:8080 tomcat:app2  
4e6ebc86b7b51d6ab8c87aaf8a669dc5f6edd2c94d2470451389ca3ed840b84a
root@Docker-2:~# ss -ntl
State         Recv-Q         Send-Q                   Local Address:Port                   Peer Address:Port         
LISTEN        0              511                            0.0.0.0:80                          0.0.0.0:*            
LISTEN        0              128                      127.0.0.53%lo:53                          0.0.0.0:*            
LISTEN        0              128                            0.0.0.0:22                          0.0.0.0:*            
LISTEN        0              128                          127.0.0.1:6010                        0.0.0.0:*            
LISTEN        0              128                          127.0.0.1:6011                        0.0.0.0:*            
LISTEN        0              20480                                *:8080                              *:*            
LISTEN        0              511                               [::]:80                             [::]:*            
LISTEN        0              128                               [::]:22                             [::]:*            
LISTEN        0              128                              [::1]:6010                           [::]:*            
LISTEN        0              128                              [::1]:6011                           [::]:*   

两台后端服务都启动后,控制界面 web1 和 web2 都是 UP 状态
访问:http://172.20.32.101:9999/haproxy-status
在这里插入图片描述

访问验证

访问web
单独访问:http://172.20.32.101:8080/app1/
在这里插入图片描述
单独访问:http://172.20.32.102:8080/app2/
在这里插入图片描述
访问 haproxy
1.访问:http://172.20.32.101/
在这里插入图片描述

2.访问:http://172.20.32.101/app1/
在这里插入图片描述
3.访问:http://172.20.32.101/app1/
在这里插入图片描述
4.访问:http://172.20.32.101/app2/
在这里插入图片描述
5.同理,刷新之后调度到另外一台tomcat上面,但是另外一台上面没有/app2/的数据
在这里插入图片描述
访问控制端
在这里插入图片描述

更多咨询,关注微信公众号

Docker学习(2)-Docker基础

Kaivi

Docker安装及基础命令介绍

https://www.docker.com/#Docker官网

Docker 运行系统 OS 版本选择:
Docker 目前已经支持多种操作系统的安装运行,比如 Ubuntu、CentOS、Redhat、Debian、Fedora,甚至是还支持了 Mac 和 Windows,在 linux 系统上需要内核版本在 3.10 或以上,docker 版本号之前一直是 0.X 版本或 1.X 版本,但是从 2017年 3 月 1 号开始改为每个季度发布一次稳版,其版本号规则也统一变更为 YY.MM,例如 17.09 表示是 2017 年 9 月份发布的。

Docker 版本选择:
Docker 之前没有区分版本(社区版还是企业版),但是 2017 年初推出的新项目 Moby则是 Docker 的完全更名版,Moby 项目是属于 Docker 项目的全新母项目,Docker将是一个隶属于的 Moby 的子产品,而且之后的版本之后开始区分为 CE 版本(社区版本)和 EE(企业收费版),CE 社区版本和 EE 企业版本都是每个季度发布一个新版本,但是 EE 版本提供后期安全维护 1 年,而 CE 版本是 4 个月。Moby 项目的地址:https://github.com/moby/moby
https://github.com/moby/moby#官方博客原文版本细节

下图为 Docker CE 和 Docker EE 的生命周期图示
在这里插入图片描述
注意事项
Docker 与 kubernetes 结合使用的时候,要安装经过 kubernetes 官方测试通过的docker 版本,避免出现不兼容等未知的及不可预估的问题发生,kubernetes 测试过的 docker 版本可以在 github 项目地址中的开发更新日志查询,具体如下:
https://github.com/kubernetes/kubernetes/#GitHub开源K8S项目
在这里插入图片描述
在这里插入图片描述

下载 rpm 包安装

下载内容 下载地址
官方rpm包下载地址 https://download.docker.com/linux/centos/7/x86_64/stable/Packages/
aliyunrpm包下载地址 https://mirrors.aliyun.com/docker-ce/linux/centos/7/x86_64/stable/Packages/
二进制下载地址-docker https://download.docker.com/linux/centos/7/x86_64/stable/Packages/
二进制下载地址-aliyun https://mirrors.aliyun.com/docker-ce/linux/static/stable/x86_64/

通过修改 yum 源安装

yum 仓库配置:http://mirrors.aliyun.com/repo/Centos-7.repo
aliyun-epel:http://mirrors.aliyun.com/repo/epel-7.repo

CentOS 7(使用 yum 进行安装)
https://developer.aliyun.com/mirror/docker-ce#参考链接

# step 1: 安装必要的一些系统工具
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
# Step 2: 添加软件源信息
sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# Step 3: 更新并安装Docker-CE
sudo yum makecache fast
sudo yum -y install docker-ce
# Step 4: 开启Docker服务
sudo service docker start

# 注意:
# 官方软件源默认启用了最新的软件,您可以通过编辑软件源的方式获取各个版本的软件包。
例如官方并没有将测试版本的软件源置为可用,您可以通过以下方式开启。同理可以开启各种测试版本等。
# vim /etc/yum.repos.d/docker-ee.repo
#   将[docker-ce-test]下方的enabled=0修改为enabled=1
#
# 安装指定版本的Docker-CE:
# Step 1: 查找Docker-CE的版本:
# yum list docker-ce.x86_64 --showduplicates | sort -r
#   Loading mirror speeds from cached hostfile
#   Loaded plugins: branch, fastestmirror, langpacks
#   docker-ce.x86_64            17.03.1.ce-1.el7.centos            docker-ce-stable
#   docker-ce.x86_64            17.03.1.ce-1.el7.centos            @docker-ce-stable
#   docker-ce.x86_64            17.03.0.ce-1.el7.centos            docker-ce-stable
#   Available Packages
# Step2: 安装指定版本的Docker-CE: (VERSION例如上面的17.03.0.ce.1-1.el7.centos)
# sudo yum -y install docker-ce-[VERSION]

Ubuntu 安装 docker 、 启动并验证服务

https://docs.docker.com/engine/install/ubuntu/#官网参考

https://developer.aliyun.com/mirror/docker-ce#阿里云Docker CE 镜像

root@Docker-1:~# sudo apt-get remove docker docker-engine docker.io containerd runc
root@Docker-1:~#  sudo apt-get update
root@Docker-1:~# sudo apt-get install \
>     apt-transport-https \
>     ca-certificates \
>     curl \
>     gnupg-agent \
>     software-properties-common
root@Docker-1:~# sudo apt-get -y install apt-transport-https ca-certificates curl software-properties-common
root@Docker-1:~# curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
OK
root@Docker-1:~# sudo add-apt-repository "deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
root@Docker-1:~# sudo apt-get -y update
root@Docker-1:~# apt-cache madison docker-ce # 查看可获取的版本
 docker-ce | 5:19.03.8~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 5:19.03.7~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 5:19.03.6~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 5:19.03.5~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 5:19.03.4~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 5:19.03.3~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 5:19.03.2~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 5:19.03.1~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 5:19.03.0~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 5:18.09.9~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 5:18.09.8~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 5:18.09.7~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 5:18.09.6~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 5:18.09.5~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 5:18.09.4~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 5:18.09.3~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 5:18.09.2~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 5:18.09.1~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 5:18.09.0~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 18.06.3~ce~3-0~ubuntu | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 18.06.2~ce~3-0~ubuntu | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 18.06.1~ce~3-0~ubuntu | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 18.06.0~ce~3-0~ubuntu | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 18.03.1~ce~3-0~ubuntu | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages

root@Docker-1:~# apt-cache madison docker-ce-cli #查看客户端能安装版本
docker-ce-cli | 5:19.03.8~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
docker-ce-cli | 5:19.03.7~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
docker-ce-cli | 5:19.03.6~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
docker-ce-cli | 5:19.03.5~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
docker-ce-cli | 5:19.03.4~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
docker-ce-cli | 5:19.03.3~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
docker-ce-cli | 5:19.03.2~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
docker-ce-cli | 5:19.03.1~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
docker-ce-cli | 5:19.03.0~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
docker-ce-cli | 5:18.09.9~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
docker-ce-cli | 5:18.09.8~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
docker-ce-cli | 5:18.09.7~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
docker-ce-cli | 5:18.09.6~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
docker-ce-cli | 5:18.09.5~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
docker-ce-cli | 5:18.09.4~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
docker-ce-cli | 5:18.09.3~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
docker-ce-cli | 5:18.09.2~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
docker-ce-cli | 5:18.09.1~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
docker-ce-cli | 5:18.09.0~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages
root@Docker-1:~# apt install docker-ce=5:18.09.9~3-0~ubuntu-bionic docker-ce-cli=5:18.09.9~3-0~ubuntu-bionic  #安装对应的版本
root@Docker-1:~# systemctl restart docker
root@Docker-1:~# systemctl enable docker

root@Docker-1:~# docker version
Client:                                  #客户端版本
 Version:           18.09.9
 API version:       1.39
 Go version:        go1.11.13
 Git commit:        039a7df9ba
 Built:             Wed Sep  4 16:57:28 2019
 OS/Arch:           linux/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:                                 #服务端版本
  Version:          18.09.9
  API version:      1.39 (minimum version 1.12)
  Go version:       go1.11.13
  Git commit:       039a7df
  Built:            Wed Sep  4 16:19:38 2019
  OS/Arch:          linux/amd64
  Experimental:     false

查看 docker0 虚拟网卡信息
在 docker 安装启动之后,默认会生成一个名称为 docker0 的虚拟网卡,其默认
IP 地址为 172.17.0.1

root@Docker-1:~# ifconfig docker0
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:15ff:fe21:6ca8  prefixlen 64  scopeid 0x20<link>
        ether 02:42:15:21:6c:a8  txqueuelen 0  (Ethernet)
        RX packets 4836  bytes 196448 (196.4 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 5993  bytes 8677150 (8.6 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

docker info 信息解读

root@Docker-1:~# docker info 
Containers: 1                       # 当前主机运行的容器总数
 Running: 1                         # 正在运行的容器数
 Paused: 0                          # 暂停的容器
 Stopped: 0                         # 停止的容器数
Images: 1                           # 当前系统所有的镜像
Server Version: 18.09.9
Storage Driver: overlay2            # 存储驱动(存储引擎)
 Backing Filesystem: extfs          # 后端文件系统,OS使用的文件系统
 Supports d_type: true              # 是否支持d_type
 Native Overlay Diff: true          # 是否支持差异数据存储
Logging Driver: json-file           # 日志驱动
Cgroup Driver: cgroupfs             # cgroups 驱动
Plugins:
 Volume: local                      # 卷
 Network: bridge host macvlan null overlay  # overlay夸主机通
 Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog   # 支持的日志类型
Swarm: inactive                     # 是否支持docker swarm
Runtimes: runc                      # 容器运行时类型为runc
Default Runtime: runc               # 默认的容器运行时为runc
Init Binary: docker-init            # 初始化容器的守护进程,即pid为1的进程
containerd version: 7ad184331fa3e55e52b890ea95e65ba581ae3429   # containerd版本
runc version: dc9208a3303feef5b3839f4323d9beb36df0a9dd    # runc版本
init version: fec3683
Security Options:
 apparmor   #安全模块, https://docs.docker.com/engine/security/apparmor/
 seccomp    # 审计(操作)模块,https://docs.docker.com/engine/security/seccomp/
  Profile: default  # 配置文件,默认的配置文件
Kernel Version: 4.15.0-29-generic
Operating System: Ubuntu 18.04.1 LTS
OSType: linux
Architecture: x86_64
CPUs: 1
Total Memory: 1.861GiB
Name: Docker-1       # 主机名
ID: U2KA:7DNC:OET5:EWRE:SMZ6:BZRY:NEHL:TR5T:Q6HI:FMTY:MFRF:QMOE
Docker Root Dir: /var/lib/docker      # 宿主机数据保存目录
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
Labels:
Experimental: false    # 是否是测试版
Insecure Registries:
 127.0.0.0/8
Registry Mirrors:
 https://9916w1ow.mirror.aliyuncs.com/
Live Restore Enabled: false  # 是否开启活动重启(重启docker-daemon不关闭容器)
Product License: Community Engine

WARNING: No swap limit support   # 不支持swap限制的警告

解决不支持 swap 限制的警告

root@Docker-1:~# vim /etc/default/grub 
GRUB_DEFAULT=0
GRUB_TIMEOUT_STYLE=hidden
GRUB_TIMEOUT=2
GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
GRUB_CMDLINE_LINUX_DEFAULT=""
GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0 cgroup_enable=memory swapaccount=1" #修改处

root@Docker-1:~# update-grub
Sourcing file `/etc/default/grub'
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-4.15.0-29-generic
Found initrd image: /boot/initrd.img-4.15.0-29-generic
done
root@Docker-1:~# reboot

docker 存储引擎

目前 docker 的默认存储引擎为 overlay2,不同的存储引擎需要相应的系统支持,如需要磁盘分区的时候传递 d-type 文件分层功能,即需要传递内核参数开启格式化磁盘的时候的指定功能。

https://docs.docker.com/storage/storagedriver/overlayfs-driver/#OverlayFS存储驱动程序

https://docs.docker.com/storage/storagedriver/overlayfs-driver/#how-the-overlay2-driver-works#how-the-overlay2-driver-works#How the overlay2 driver works

https://docs.docker.com/storage/storagedriver/select-storage-driver/#存储引擎选择文档

存储引擎驱动类型

AUFS
AUFS:AUFS(AnotherUnionFS)是一种 Union FS 实现,是文件级的存储驱动。UnionFS 支持将不同目录挂载到同一个虚拟文件系统下的文件系统。也就是说支持把不同物理位置的目录合并 mount 到同一个目录中。这种文件系统可以一层一层地叠加修改文件。无论底下有多少层都是只读的,只有最上层的文件系统是可写的。当需要修改一个文件时,AUFS 创建该文件的一个副本,使用copy-on-write 机制将文件从只读层复制到可写层进行修改,结果也保存在可写层。在 Docker 中,底层的只读层就是 image,可写层就是 Container。

Overlay
一种 Union FS 文件系统,Linux 内核 3.18 后支持。

overlay2
Overlay2 文件系统是 Overlay 的升级版,到目前为止,overlay2 位所有 Linux 发行版推荐使用的存储类型。

devicemapper
devicemapper 是 CentOS 和 RHEL 的推荐存储驱动程序,因为之前的内核版本不支持overlay2,但是当前较新版本的 CentOS 和 RHEL 现在已经支持 overlay2,因此推荐使用 overlay2。实际上 devicemapper 只是一个过渡性技术,现在 Docker 生态已经没人使用 devicemapper。

vfs
用于测试环境,适用于无法使用 copy-on-write 文件系统的情况。 此存储驱动程序的性能很差,通常不建议用于生产。

Docker 首选存储引擎

Docker 官方推荐首选 存储 引擎 为 overlay2 devicemapper 存在使用空间方面的一些限制, 虽然可以通过后期配置解决,但是官方依然推荐使用 overlay2 ,以下是网上查到的部分资料:https://www.cnblogs.com/youruncloud/p/5736718.html#容器运行异常,同时宿主机内核报磁盘I/O错误

[root@centos8 ~]#xfs_info /
meta-data=/dev/nvme0n1p2         isize=512    agcount=4, agsize=6553600 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1
data     =                       bsize=4096   blocks=26214400, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1 # ftype=1表示文件系统支持d_type
log      =internal log           bsize=4096   blocks=12800, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

root@Docker-1:~# docker info |grep type
 Supports d_type: true             # 不支持d_type则docker无法启动

如果 docker 数据目录是一块单独的磁盘分区而且是 xfs 格式的,那么需要在格式化的时候加上参数-n ftype=1,否则后期在启动容器的时候会报错不支持 d_type。

docker 服务进程

在这里插入图片描述
如上图所示在基于镜像创建和运行容器的整个过程中主要涉及的进程有:Docker engine 中的docker daemon、负责配置运行时的containerd、负责运行容器的containerd-shim、及运行在最底层的 runC 库。另外,图中未画的 docker-proxy进程为实现容器通信的,其父进程为 dockerd。
在这里插入图片描述

root@Docker-1:~# pstree -lpsT |grep containerd
           |-containerd(843)---containerd-shim(1672)---nginx(1696)---nginx(1734)
#containerd(843):设置运行时
#containerd-shim(1672):运行容器
#nginx(1696)---nginx(1734):具体容器进程

containerd-shim进程实现一下功能:
1.允许允许非守护类容器
2.当container、docker进程故障后容器的STDIO和FDs保持打开
3.报告容器的退出状态给containerd

如上图,一个容器从镜像的创建过程可以大致分为以下步骤:

  1. docker run命令根据命令行指定的参数创建一个 JSON 对象,并将该对象传给 dockerd。
  2. dockerd 会检查本地是否有 alpine(不指定版本默认为最新版)镜像,如果没有就去Docker Hub 拉取。
  3. alpine 镜像拉取后,dockerd 会通过 gRPC API 发送 gRPC 请求与 containerd交互,containerd 会负责配置和准备容器运行时。
  4. containerd 配置好运行时后调用 containerd-shim 来运行容器的运行时。
  5. container-shim 被调用后,使用 create 选项调用 runC 进程来运行容器, containerd-shim可以通过 exit、control 文件和 containerd 通信,通过父子进程 关系和 SIGCHLD(信号)监控容器中进程状态。
  6. 在整个容器生命周期中,containerd 通过 epoll 监控容器文件,监控容器事件。

可以使用 UML 图来表达各进程大致的信息交互:
在这里插入图片描述

grpc 简介

https://www.grpc.io/#gRPC-官网
gRPC 是 Google 开发的一款高性能、开源和通用的 RPC 框架,支持众多语言客户端。

gRPC (gRPC 远程过程调用)是一个开源远程过程调用(RPC)系统,最初在 2015 年由谷歌开发。它使用 HTTP/2 进行传输,协议缓冲区作为接口描述语言,并提供诸如身份验证、双向流和流控制、阻塞或非阻塞绑定、取消和超时等功能。它为多种语言生成跨平台的客户机和服务器绑定。最常见的使用场景包括在微服务风格的架构中连接服务,并将移动设备、浏览器客户端连接到后端服务。

docker 镜像加速配置

使用 Docker 时,在国内网络环境下载国外的镜像有时候会很慢,因此可以更改 docker配置文件来添加一个加速网址,可以通过加速器达到加速下载镜像的目的。

获取加速地址
首先注册一个阿里云账户:https://account.aliyun.com/login/login.htm
在这里插入图片描述
在这里插入图片描述

root@Docker-1:~# sudo mkdir -p /etc/docker
root@Docker-1:~# sudo tee /etc/docker/daemon.json <<-'EOF'
> {
>   "registry-mirrors": ["https://jcmwo9z2.mirror.aliyuncs.com"]
> }
> EOF #需要手动输入
{
  "registry-mirrors": ["https://jcmwo9z2.mirror.aliyuncs.com"]
}
root@Docker-1:~# sudo systemctl daemon-reload
root@Docker-1:~# sudo systemctl restart docker

https://jcmwo9z2.mirror.aliyuncs.com#加速器地址
这个加速地址谁都可以用,Ubuntu 和 Centos 配置过程相同。

检查加速器是否生效配置加速器之后,如果拉取镜像仍然十分缓慢,请手动检查加速器配置是否生效,在命令行执行 docker info,如果从结果中看到了如下内容,说明配置成功。

root@Docker-1:~# sudo docker info
 Registry Mirrors:
  https://jcmwo9z2.mirror.aliyuncs.com/

Docker 镜像管理

Docker 镜像含有启动容器所需要的文件系统及所需要的内容,因此镜像主要用于创建并启动 docker 容器。Docker 镜像里面是一层层文件系统,叫做 Union FS(联合文件系统),联合文件系统,可以将几层目录挂载到一起,形成一个虚拟文件系统,虚拟文件系统的目录结构就像普通 linux 的目录结构一样,docker 通过这些文件再加上宿主机的内核提供了一个 linux 的虚拟环境,每一层文件系统我们叫做一层 layer,联合文件系统可以对每一层文件系统设置三种权限,只读(readonly)、读写(readwrite)
和写出(whiteout-able),但是 docker 镜像中每一层文件系统都是只读的,构建镜像的时候,从一个最基本的操作系统开始,每个构建的操作都相当于做一层的修改,增加了一层文件系统,一层层往上叠加,上层的修改会覆盖底层该位置的可见性,这也很容易理解,就像上层把底层遮住了一样,当使用镜像的时候,我们只会看到一个完全的整体,不知道里面有几层也不需要知道里面有几层,结构如下:
在这里插入图片描述
一个典型的 Linux 文件系统由 bootfs 和 rootfs 两部分组成,bootfs(boot filesystem) 主要包含 bootloader 和 kernel,bootloader 主要用于引导加载 kernel,当 kernel 被加载到内存中后 bootfs 会被 umount 掉,rootfs (root file system)
包含的就是典型 Linux 系统中的/dev,/proc,/bin,/etc 等标准目录和文件,下图就是 docker image 中最基础的两层结构,不同的 linux 发行版(如 ubuntu 和 CentOS) 在 rootfs 这一层会有所区别。但是对于 docker 镜像通常都比较小,官方提供的
centos 基础镜像在 200MB 左右,一些其他版本的镜像甚至只有几 MB,docker 镜像直接调用宿主机的内核,镜像中只提供 rootfs,也就是只需要包括最基本的命令、工具和程序库就可以了,比如 alpine 镜像,在 5M 左右。下图就是有两个不同的镜像在一个宿主机内核上实现不同的 rootfs。
在这里插入图片描述
在不同的层代表了镜像不同的变更,如下图:
Apache 所在的镜像层引用了 emacs 所在层表示的镜像,而 emacs 所在镜像又是基于
Debian 基础镜像创建来的。在使用 Dockerfile 创建镜像时,更能体现下面的分层结构。
在这里插入图片描述
Docker 镜像存在的各个阶段和状态可以从下图看出:
在这里插入图片描述

搜索镜像

在使用 docker 命令时,可以很方便的使用命令和子命令的帮助:
在官方的 docker 仓库 中搜索指定名称的 docker 镜像, 也会有很多镜像。

# 使用<docker 子命令 --help>来获取帮助
~$ docker --help
~$ docker image --help
~$ docker container --help  # container是docker的子命令
~$ docker container logs --help  # logs是container的子命令
~$ docker search --help
~$ docker save --help
~$ docker exec --help

在官方的 docker 仓库中搜索指定名称的 docker 镜像:

~$ docker search IMAGE_NAME:TAG
~$ docker search --help
root@Docker-1:~# docker search alpine
NAME                                   DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
alpine                                 A minimal Docker image based on Alpine Linux…   6359          [OK]                
mhart/alpine-node                      Minimal Node.js built on Alpine Linux           465                                
anapsix/alpine-java                    Oracle Java 8 (and 7) with GLIBC 2.28 over A…   442                               [OK]
frolvlad/alpine-glibc                  Alpine Docker image with glibc (~12MB)          239                                     [OK]
gliderlabs/alpine                      Image based on Alpine Linux will help you wi…   181                                     
alpine/git                             A  simple git container running in alpine li…   125                                     [OK]
mvertes/alpine-mongo                   light MongoDB container                         111                                     [OK]
yobasystems/alpine-mariadb             MariaDB running on Alpine Linux [docker] [am…   64                                      [OK]
alpine/socat                           Run socat command in alpine container           50                                      [OK]
kiasaki/alpine-postgres                PostgreSQL docker image based on Alpine Linux   45                                      [OK]
davidcaste/alpine-tomcat               Apache Tomcat 7/8 using Oracle Java 7/8 with…   43                                      [OK]
jfloff/alpine-python                   A small, more complete, Python Docker image …   36                                      [OK]
zzrot/alpine-caddy                     Caddy Server Docker Container running on Alp…   36                                      [OK]
byrnedo/alpine-curl                    Alpine linux with curl installed and set as …   31                                      [OK]
hermsi/alpine-sshd                     Dockerize your OpenSSH-server with rsync and…   30                                      [OK]
etopian/alpine-php-wordpress           Alpine WordPress Nginx PHP-FPM WP-CLI           24                                      [OK]
hermsi/alpine-fpm-php                  Dockerize your FPM PHP 7.4 upon a lightweigh…   24                                      [OK]
zenika/alpine-chrome                   Chrome running in headless mode in a tiny Al…   19                                      [OK]
bashell/alpine-bash                    Alpine Linux with /bin/bash as a default she…   16                                      [OK]
davidcaste/alpine-java-unlimited-jce   Oracle Java 8 (and 7) with GLIBC 2.21 over A…   13                                      [OK]
spotify/alpine                         Alpine image with `bash` and `curl`.            11                                      [OK]
roribio16/alpine-sqs                   Dockerized ElasticMQ server + web UI over Al…   8                                       [OK]
cfmanteiga/alpine-bash-curl-jq         Docker Alpine image with Bash, curl and jq p…   5                                       [OK]
hermsi/alpine-varnish                  Dockerize Varnish upon a lightweight alpine-…   3                                       [OK]
goodguykoi/alpine-curl-internal        simple alpine image with curl installed no C…   0                                       [OK]

下载镜像

从docker 仓库 将镜像下载到本地 命令格式 如下

~$ docker pull hub.docker.com/nginx/nginx:1.16.1
~$ docker pull 仓库服务器:端口/项目名称/镜像名称:tag(版本)号
root@Docker-1:~# docker pull nginx:1.16.1

root@Docker-1:~# docker pull alpine
Using default tag: latest
latest: Pulling from library/alpine
aad63a933944: Pull complete 
Digest: sha256:b276d875eeed9c7d3f1cfa7edb06b22ed22b14219a7d67c52c56612330348239
Status: Downloaded newer image for alpine:latest

查看本地镜像

下载完成的镜像比下载的大,因为下载完成后会解压

~$ docker images
root@Docker-1:~# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               1.16.1              16af99d71a72        15 hours ago        127MB
alpine              latest              a187dde48cd2        3 weeks ago         5.6MB
REPOSITORY            # 镜像所属的仓库名称
TAG                   # 镜像版本号(标识符),默认为latest
IMAGE ID              # 镜像唯一ID标示
CREATED               # 镜像创建时间
VIRTUAL SIZE          # 镜像的大小

镜像导出

可以将镜像从本地导出问为一个压缩文件,然后复制到其他服务器进行导入使用
镜像导出使用 docker save 命令:

~$ docker [image] save nginx -o /opt/nginx-1.16.1.tar.gz
或者不指定-o选项,直接使用标准输出重定向:
~$ docker [image] save nginx > /opt/nginx-1.16.1.tar.gz
root@Docker-1:~# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               1.16.1              16af99d71a72        15 hours ago        127MB
alpine              latest              a187dde48cd2        3 weeks ago         5.6MB
root@Docker-1:~# docker save nginx -o /opt/nginx-1.16.1.tar.gz
root@Docker-1:~# docker save alpine > /opt/alpine.tar.gz
root@Docker-1:~# ll /opt/
total 133224
drwxr-xr-x  3 root root      4096 Apr 17 09:01 ./
drwxr-xr-x 24 root root      4096 Oct 26 19:34 ../
-rw-r--r--  1 root root   5871104 Apr 17 09:01 alpine.tar.gz
-rw-------  1 root root 130532864 Apr 17 09:00 nginx-1.16.1.tar.gz

查看镜像内容

root@Docker-1:~# cd /opt/
root@Docker-1:/opt# mkdir nginx
root@Docker-1:/opt# tar xf nginx-1.16.1.tar.gz -C nginx/
root@Docker-1:/opt# cd nginx/
root@Docker-1:/opt/nginx# ll
total 36
drwxr-xr-x 5 root root 4096 Apr 17 09:03 ./
drwxr-xr-x 4 root root 4096 Apr 17 09:03 ../
-rw-r--r-- 1 root root 6648 Apr 16 18:11 16af99d71a72da0d83975260ed6855961104ac1c4b3d73a80beab7801d8d528b.json
drwxr-xr-x 2 root root 4096 Apr 16 18:11 2b88b180636e9674634a96ba9f1d1e61cfc09ad098960c1b3f35e27ad1ac0cf8/
drwxr-xr-x 2 root root 4096 Apr 16 18:11 db1595149451b379f2313b21ca97702b5bfa1b3f00ab080b090138bd414ecc27/
drwxr-xr-x 2 root root 4096 Apr 16 18:11 f45abcb94bf801d5ea5575637f6c81ec0db2c72acabb27800ec0a49dea281d8a/
-rw-r--r-- 1 root root  355 Jan  1  1970 manifest.json
-rw-r--r-- 1 root root   88 Jan  1  1970 repositories

root@Docker-1:/opt/nginx# cat manifest.json 
[{"Config":"16af99d71a72da0d83975260ed6855961104ac1c4b3d73a80beab7801d8d528b.json",  # 该镜像的详细配置
"RepoTags":["nginx:1.16.1"],  # 仓库和镜像tag名称
"Layers":["2b88b180636e9674634a96ba9f1d1e61cfc09ad098960c1b3f35e27ad1ac0cf8/layer.tar","f45abcb94bf801d5ea5575637f6c81ec0db2c72acabb27800ec0a49dea281d8a/layer.tar", # 键Layers记录了目前该镜像的分层情况
"db1595149451b379f2313b21ca97702b5bfa1b3f00ab080b090138bd414ecc27/layer.tar"]}]

root@Docker-1:/opt/nginx# cat repositories   # repositories使用json格式记录了镜像的仓库信息和tag名称
{"nginx":{"1.16.1":"db1595149451b379f2313b21ca97702b5bfa1b3f00ab080b090138bd414ecc27"}}

查看镜像的详细配置和构建历史

root@Docker-1:/opt/nginx# cat 16af99d71a72da0d83975260ed6855961104ac1c4b3d73a80beab7801d8d528b.json 

镜像导入

将其他容器导出的镜像,导入到 Docker 生成另一个镜像,使用docker load命令

~$ docker [image] load -i /path/to/image.tar.gz
~$ docker [image] load < /path/to/image.tar.gz
root@Docker-1:/opt# scp nginx-1.16.1.tar.gz 172.20.32.102:/opt/
The authenticity of host '172.20.32.102 (172.20.32.102)' can't be established.
nginx-1.16.1.tar.gz                                                                              100%  124MB  62.2MB/s   00:02   

# 在172.20.32.102
root@Docker-2:/opt# ll
total 127492
drwxr-xr-x  3 root root      4096 Apr 17 09:21 ./
drwxr-xr-x 24 root root      4096 Oct 26 19:34 ../
drwx--x--x  4 root root      4096 Apr 17 09:21 containerd/
-rw-------  1 root root 130532864 Apr 17 09:15 nginx-1.16.1.tar.gz

root@Docker-2:/opt# docker load -i nginx-1.16.1.tar.gz 
b60e5c3bcef2: Loading layer [==================================================>]  72.49MB/72.49MB
1b7f58b2d14e: Loading layer [==================================================>]  58.02MB/58.02MB
0b12ec6fd453: Loading layer [==================================================>]  3.584kB/3.584kB
Loaded image: nginx:1.16.1
root@Docker-2:/opt# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               1.16.1              16af99d71a72        15 hours ago        127MB

删除镜像

从 Docker 当前已有的镜像列表中删除镜像

~$ docker image rm ID
~$ docker rmi ID
root@Docker-1:~# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               1.16.1              16af99d71a72        15 hours ago        127MB
nginx               latest              5a8dfb2ca731        15 hours ago        127MB
alpine              latest              a187dde48cd2        3 weeks ago         5.6MB
root@Docker-1:~# docker image rm a187dde48cd2 
Untagged: alpine:latest
Untagged: alpine@sha256:b276d875eeed9c7d3f1cfa7edb06b22ed22b14219a7d67c52c56612330348239
Deleted: sha256:a187dde48cd289ac374ad8539930628314bc581a481cdb41409c9289419ddb72
Deleted: sha256:beee9f30bc1f711043e78d4a2be0668955d4b761d587d6f60c2c8dc081efb203
root@Docker-1:~# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               1.16.1              16af99d71a72        15 hours ago        127MB
nginx               latest              5a8dfb2ca731        15 hours ago        127MB

root@Docker-1:~# docker rmi  5a8dfb2ca731 
Untagged: nginx:latest
Untagged: nginx@sha256:4a1f25606ce84be14bb5b4a4e11825d9ce78affeec62545d0a027dc8a1b2ce76
Deleted: sha256:5a8dfb2ca7312ee39433331b11d92f45bb19d7809f7c0ff19e1d01a2c131e959
Deleted: sha256:eede83f79a434879440e1f6f6f98a135b38057a35ddcdace715ae1bddcd7a884
Deleted: sha256:fa994cfd7aeedcd46b70cf30fea0ccf9f59f990bbb86bfa9b7c02d7ff2a833eb
root@Docker-1:~# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               1.16.1              16af99d71a72        15 hours ago        127MB

镜像管理命令总结

~$ docker [image] pull
~$ docker search IMAGE[:TAG]
~$ docker images
~$ docker [image] save IMAGE -o /path/to/IMAGE.tar.gz
~$ docker [image] save IMAGE > /path/to/IMAGE.tar.gz
~$ docker [image] load -i /path/to/IMAGE.tar.gz
~$ docker [image] load < /path/to/IMAGE.tar.gz
~$ docker [image] rm ID
~$ docker rmi ID

注意:
删除指定 ID 的镜像时,通过镜像启动容器的时候该镜像不能被删除,除非将容器全部关闭。删除镜像时可以是镜像 ID 也可以是镜像名称。

容器操作基础命令

Docker 容器根据对其不同的操作和不同的情况其可以处于多种状态,这些状态组成了容器的生命周期,主要的状态如下图所示:
在这里插入图片描述
容器管理主要涉及从镜像启动容器、暂停或停止容器、恢复暂停或停止的容器、删除正在运行的容器及显示相应状态的容器等操作。
命令格式:

~$ docker run --help # 获取帮助
~$ docker run [OPT] IMAGE [CMD] [ARG...] # 运行容器
~$ docker ps [OPT] # 显示运行的容器
root@Docker-1:~# docker run --help 

Usage:  docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

Run a command in a new container

Options:
......

从镜像启动一个容器

从镜像启动一个容器后会直接进入到该容器,并随机生成容器 ID 和名称

root@Docker-1:~# docker run --help
...
-i, --interactive                    Keep STDIN open even if not attached
   # 保持标准输入开启,使得容器可以接受命令行的命令,即使用交互式创建容器。

-t, --tty                            Allocate a pseudo-TTY
   # 给创建的容器分配一个伪终端
...

所以可以使用docker run -i -t来创建容器,并进入 Docker 为其分配的终端

root@Docker-1:~# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               1.16.1              16af99d71a72        15 hours ago        127MB
alpine              latest              a187dde48cd2        3 weeks ago         5.6MB
root@Docker-1:~# docker run -it alpine sh
/ # echo "hello world"
hello world
/ # exit  # 退出交互式运行的容器,其将不再在后台运行

root@Docker-1:~# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
root@Docker-1:~# docker ps -a   # 可以看到容器alpine已经退出,-a选项显示所有状态容器
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS                         PORTS               NAMES
b15e4ffee417        alpine              "sh"                     About a minute ago   Exited (0) 48 seconds ago                          zen_borg
0efb1d4d3d75        nginx:1.16.1        "nginx -g 'daemon of…"   2 hours ago          Exited (0) About an hour ago 
# ctrl+p+q 退出容器,容器任然在后台运行
root@Docker-1:~# tty
/dev/pts/0
root@Docker-1:~# docker run -it alpine sh
/ #   #这里执行了ctrl+p+q 退出容器,容器任然在后台运行
/ # root@Docker-1:~# tty  #退回容器回到当前终端 在执行tty命令查看
/dev/pts/0

root@Docker-1:~# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS               NAMES
37c8301af2da        alpine              "sh"                About a minute ago   Up About a minute                       zen_noyce
root@Docker-1:~# docker exec -it 37c8301af2da sh
/ # tty
/dev/pts/1 # docker为alpine容器分配的tty为/dev/pts/1
/ # read escape sequence    #  ctrl+p+q 剥离当前终端的容器
root@Docker-1:~# docker ps  # alpine容器还在
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
37c8301af2da        alpine              "sh"                2 minutes ago       Up 2 minutes                            zen_noyce

显示正在运行的容器

~$ docker ps
~$ docker ps --help
root@Docker-1:~# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
46b415548bbd        nginx:1.16.1        "nginx -g 'daemon of…"   10 seconds ago      Up 9 seconds        80/tcp              hardcore_jackson
37c8301af2da        alpine              "sh"                     7 minutes ago       Up 7 minutes                            zen_noyce
root@Docker-1:~# docker ps -f name=zen_noyce  # 以名字过滤容器
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
37c8301af2da        alpine              "sh"                9 minutes ago       Up 9 minutes                            zen_noyce

显示所有容器:

~$ docker ps -a
root@Docker-1:~# docker run -it -d nginx:1.16.1
46b415548bbd3f876672c807a8a86e68a171e07b173950465ef5fabfa235f405
root@Docker-1:~# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
46b415548bbd        nginx:1.16.1        "nginx -g 'daemon of…"   10 seconds ago      Up 9 seconds        80/tcp              hardcore_jackson
37c8301af2da        alpine              "sh"                     7 minutes ago       Up 7 minutes                            zen_noyce
root@Docker-1:~# docker container stop 46b415548bbd  #停止nginx容器
46b415548bbd
root@Docker-1:~# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
37c8301af2da        alpine              "sh"                11 minutes ago      Up 11 minutes                           zen_noyce

删除运行中的容器

删除容器使用docker rm命令

~$ docker [container] rm ID
~$ docker [container] rm -f ID

注意:在执行删除容器操作时,指定 -f 选项即使容正在运行当中,也会被强制删除掉

root@Docker-1:~# docker ps  # alpine容器在运行
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
37c8301af2da        alpine              "sh"                13 minutes ago      Up 13 minutes                           zen_noyce
root@Docker-1:~# docker rm 37c8301af2da # 提示无法删除运行的容器
Error response from daemon: You cannot remove a running container 37c8301af2da7784ae645497fd528607ffe16c9228a76a6f6f2d586dc9226ad4. 
Stop the container before attempting removal or force remove
root@Docker-1:~# docker stop 37c8301af2da  # 停止容器后删除
37c8301af2da
root@Docker-1:~# docker rm 37c8301af2da
37c8301af2da
root@Docker-1:~# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

root@Docker-1:~# docker run -it -d alpine:latest   # 再起一个容器
34de16983e1281a1d189c30c0520e163ebf3f0aa5576d4c857c2394241e6cfc9
root@Docker-1:~# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
34de16983e12        alpine:latest       "/bin/sh"           5 seconds ago       Up 4 seconds                            adoring_pike
root@Docker-1:~# docker rm -f 34de16983e12  
34de16983e12 
root@Docker-1:~# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
#强制删除成功

随机映射端口

~$ docker run --help
...
-p, --publish list      Publish a container\'s port(s) to the host
   # -p,小写的-p选项用来将容器的端口映射到主机的某端口
-P, --publish-all       Publish all exposed ports to random ports
   # -P,大写的-P选项用来将容器的端口映射到主机的随机端口
...

# 例如:
~$ docker run -it -d -p 主机端口:容器端口 <...>
root@Docker-1:~# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               1.16.1              16af99d71a72        16 hours ago        127MB
alpine              latest              a187dde48cd2        3 weeks ago         5.6MB
root@Docker-1:~# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
root@Docker-1:~# docker run -it -d -P nginx:1.16.1 
81718abe85ccd52e91968df20231377226d53fe755dcb3ffb609ecc7a6aba690
root@Docker-1:~# docker ps # 可以看到,nginx的默认80端口被映射到主机的随机端口10001
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                   NAMES
81718abe85cc        nginx:1.16.1        "nginx -g 'daemon of…"   3 seconds ago       Up 1 second         0.0.0.0:10001->80/tcp   tender_aryabhata
root@Docker-1:~# ss -ntl
LISTEN          0                20480                   *:10001                    *:*     

root@Docker-1:~# docker run -it -d -P --name=kaivi_test nginx:1.16.1 # 再起一个容器后,可以看到nginx的80端口被映射到主机的10002端口
61d042ca633093b3e7b342db8308fc48fc4f777ca8249b320e46df5f289d6217
root@Docker-1:~# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                   NAMES
61d042ca6330        nginx:1.16.1        "nginx -g 'daemon of…"   8 seconds ago       Up 7 seconds        0.0.0.0:10002->80/tcp   kaivi_test
81718abe85cc        nginx:1.16.1        "nginx -g 'daemon of…"   2 minutes ago       Up 2 minutes        0.0.0.0:10001->80/tcp   tender_aryabhata
root@Docker-1:~# lsof -i:10001 # 查看是谁在占用端口10001
COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
docker-pr 3301 root    4u  IPv6  52569      0t0  TCP *:10001 (LISTEN)
root@Docker-1:~# lsof -i:10002 # 查看是谁在占用端口10002
COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
docker-pr 3403 root    4u  IPv6  53591      0t0  TCP *:10002 (LISTEN)
root@Docker-1:~# ss -ntl           
LISTEN          0                20480                           *:10001                        *:*              
LISTEN          0                20480                           *:10002                        *:*              

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

指定端口映射

1.将主机端口 80 映射到容器端口 80("-p 主机端口:容器端口")

~$ docker run -it -d -p 主机端口:容器端口 <...>
root@Docker-1:~# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               1.16.1              16af99d71a72        16 hours ago        127MB
alpine              latest              a187dde48cd2        3 weeks ago         5.6MB
root@Docker-1:~# docker run -it -d -p 80:80 --name=kaivi_test1 nginx:1.16.1 #再起一个容器
93d953d6c30ab768be0d84fa794bbbe140ee46e88fa1d6f9d27eb11cdd27d517
root@Docker-1:~# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                   NAMES
93d953d6c30a        nginx:1.16.1        "nginx -g 'daemon of…"   7 seconds ago       Up 5 seconds        0.0.0.0:80->80/tcp      kaivi_test1
61d042ca6330        nginx:1.16.1        "nginx -g 'daemon of…"   14 minutes ago      Up 14 minutes       0.0.0.0:10002->80/tcp   kaivi_test
81718abe85cc        nginx:1.16.1        "nginx -g 'daemon of…"   17 minutes ago      Up 17 minutes       0.0.0.0:10001->80/tcp   tender_aryabhata
root@Docker-1:~# ss -ntl       
LISTEN          0                20480                        *:80                           *:*            
LISTEN          0                20480                        *:10001                        *:*              
LISTEN          0                20480                        *:10002                        *:*              

root@Docker-1:~# lsof -i:80
COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
docker-pr 3529 root    4u  IPv6  56741      0t0  TCP *:http (LISTEN)

2.将主机的 IP 加端口映射到容器的某端口(主机 IP:本地端口:容器端口)

~$ docker run -it -d -p IP:PORT:PORT <...>
root@Docker-1:~# docker run -it -d -p 172.20.32.101:81:80 --name=kaivi_test2 nginx:1.16.1
5522e58261b9581e59c9e2da6ac09336ca1421699813eb002500b67f85f5cf4b

3.将主机 IP 和随机端口映射到容器的某端口(主机 IP::PORT)

root@Docker-1:~# docker run -it -d -p 172.20.32.101::80 --name=kaivi_test3 nginx:1.16.1
93974f01ee647a7fddad7d2bf540f8009bf57e77646d433c1c4560d88401791b

4.将主机的 IP 加端口映射到容器的某端口并指定协议(主机 IP:本地端口:容器端口/协议)

root@Docker-1:~# docker run -it -d -p 172.20.32.101:82:80/udp --name=kaivi_test4 nginx:1.16.1
4ac2c4f97459a4fc4e97e73d371a707bb473d698e30b368174406b8adc52d942

5.映射多个端口

root@Docker-1:~# docker run -it -d -p 172.20.32.101:83:80/udp -p 443:443/tcp -p 50:50/udp  --name=kaivi_test5 nginx:1.16.1
a56a5c0fb4822d91c8d63379e299e76dac938a5fd9b1765cde71e12bdd9295a7

查看端口映射情况

root@Docker-1:~# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                                                        NAMES
a56a5c0fb482        nginx:1.16.1        "nginx -g 'daemon of…"   24 seconds ago      Up 23 seconds       0.0.0.0:50->50/udp, 80/tcp, 0.0.0.0:443->443/tcp, 172.20.32.101:83->80/udp   kaivi_test5
4ac2c4f97459        nginx:1.16.1        "nginx -g 'daemon of…"   2 minutes ago       Up 2 minutes        80/tcp, 172.20.32.101:82->80/udp                                             kaivi_test4
93974f01ee64        nginx:1.16.1        "nginx -g 'daemon of…"   4 minutes ago       Up 4 minutes        172.20.32.101:10003->80/tcp                                                  kaivi_test3
5522e58261b9        nginx:1.16.1        "nginx -g 'daemon of…"   6 minutes ago       Up 6 minutes        172.20.32.101:81->80/tcp                                                     kaivi_test2
93d953d6c30a        nginx:1.16.1        "nginx -g 'daemon of…"   10 minutes ago      Up 10 minutes       0.0.0.0:80->80/tcp                                                           kaivi_test1
61d042ca6330        nginx:1.16.1        "nginx -g 'daemon of…"   25 minutes ago      Up 25 minutes       0.0.0.0:10002->80/tcp                                                        kaivi_test
81718abe85cc        nginx:1.16.1        "nginx -g 'daemon of…"   28 minutes ago      Up 28 minutes       0.0.0.0:10001->80/tcp   
                                                     tender_aryabhata
root@Docker-1:~# ss -ntl
State           Recv-Q           Send-Q                        Local Address:Port                        Peer Address:Port           
LISTEN          0                20480                         172.20.32.101:81                               0.0.0.0:*              
LISTEN          0                20480                         172.20.32.101:10003                            0.0.0.0:*              
LISTEN          0                128                           127.0.0.53%lo:53                               0.0.0.0:*              
LISTEN          0                128                                 0.0.0.0:22                               0.0.0.0:*              
LISTEN          0                128                               127.0.0.1:6010                             0.0.0.0:*              
LISTEN          0                20480                                     *:80                                     *:*              
LISTEN          0                20480                                     *:10001                                  *:*              
LISTEN          0                20480                                     *:10002                                  *:*              
LISTEN          0                128                                    [::]:22                                  [::]:*              
LISTEN          0                128                                   [::1]:6010                                [::]:*              
LISTEN          0                20480                                     *:443                                    *:*   

查看 nginx 容器的访问日志

~$ docker logs NAME/ID #单次查看
~$ docker logs -f NAME/ID #持续查看
root@Docker-1:~# docker logs kaivi_test
172.20.32.1 - - [17/Apr/2020:02:14:17 +0000] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36" "-"
2020/04/17 02:14:17 [error] 6#6: *1 open() "/usr/share/nginx/html/favicon.ico" failed (2: No such file or directory), client: 172.20.32.1, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "172.20.32.101:10002", referrer: "http://172.20.32.101:10002/"
172.20.32.1 - - [17/Apr/2020:02:14:17 +0000] "GET /favicon.ico HTTP/1.1" 404 555 "http://172.20.32.101:10002/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36" "-"
172.20.32.1 - - [17/Apr/2020:02:14:39 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36" "-"

root@Docker-1:~# docker logs -f kaivi_test #持续查看

root@Docker-1:~# docker logs 61d042ca6330

查看容器已经映射的端口

~$ docker port NAME/ID
# 该命令的输出是以容器的角度来看端口映射关系
# 即:容器端口 -> 主机端口
root@Docker-1:~# docker port 4ac2c4f97459
80/udp -> 172.20.32.101:82
root@Docker-1:~# docker port kaivi_test4
80/udp -> 172.20.32.101:82
root@Docker-1:~# docker port kaivi_test5
443/tcp -> 0.0.0.0:443
50/udp -> 0.0.0.0:50
80/udp -> 172.20.32.101:83

自定义容器名称

~$ docker run -it -d --name=cus_name IMAGE/ID

自定义容器名称

从镜像运行容器时指定-d选项,可以让容器后台运行, -i -t打开 STDI 并分配 tty 给容器

root@Docker-1:~# docker run -it -d --name=kaivi_test6 alpine
8bc97beeed6fe24560575e6f22f4e03ec6981889a6b6be714c392a4dbf55e954
root@Docker-1:~# docker ps -f name=kaivi_test6 #用名字过滤
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS               NAMES
8bc97beeed6f        alpine              "/bin/sh"           About a minute ago   Up About a minute                       kaivi_test6

创建并进入容器

从镜像创建并运行容器时,可以在命令最后指定需要容器运行的命令。这样可以创建容器后直接进入容器,执行 exit 退出后容器并关闭容器。使用ctrl + p + q可以不退出容器将其剥离终端在后台运行。

root@Docker-1:~# docker run -it  --name=kaivi_test7 alpine # 不指定-d选项
/ # ls   # 直接进入运行shell的容器
bin    dev    etc    home   lib    media  mnt    opt    proc   root   run    sbin   srv    sys    tmp    usr    var
/ # pwd
/
/ # ps aux
PID   USER     TIME  COMMAND
    1 root      0:00 /bin/sh
    7 root      0:00 ps aux
/ # exit

单次运行

单词运行容器可以用来测试容器是否可以正常创建并运行,使用–rm选项可以让容器单次运行,在容器退出后会被自动删除。

root@Docker-1:~# tty
/dev/pts/0
root@Docker-1:~# docker run -it  --rm --name=kaivi_test8 alpine
/ # exit

# 在新终端/dev/pts/1查看 
root@Docker-1:~# docker ps -f name=kaivi_test8   # 未退出时在/dev/pts/1可以看到其运行
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
25e5aa9e6516        alpine              "/bin/sh"           37 seconds ago      Up 36 seconds                           kaivi_test8
root@Docker-1:~# docker ps -f name=kaivi_test8
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

传递运行命令

容器需要有一个前台运行的进程才能保持容器的运行,通过传递运行参数是一种方式,另外也可以在构建镜像的时候指定容器启动时运行的前台命令。

# 尝试不给alpine容器分配tty和打开标准输入
root@Docker-1:~# docker run -d alpine
046dd4df9922bd8a9d5ca6d1d3710dcad0e874ea13ad24a35c828322bc0fa680
root@Docker-1:~# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                                                        NAMES
root@Docker-1:~# docker ps -a  # 创建后运行了一下/bin/sh就退出了
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                         PORTS                                                                        NAMES
046dd4df9922        alpine              "/bin/sh"                21 seconds ago      Exited (0) 20 seconds ago   
# 给alpine容器传一个前台运行的命令(依附于tty和标准输入)
root@Docker-1:~# docker run -d alpine /usr/bin/tail -f '/etc/issue'
e89d3650d99d497f51a7ce31948a09b88a215ea0e92a8958011a64130bc5761d
root@Docker-1:~# docker ps #这次运行成功
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                                                        NAMES
e89d3650d99d        alpine              "/usr/bin/tail -f /e…"   6 seconds ago       Up 5 seconds                                                                                     naughty_davinci

容器的启动和关闭

~$ docker stop ID/NAMES
~$ docker start ID/NAMES
root@Docker-1:~# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                                                        NAMES
e89d3650d99d        alpine              "/usr/bin/tail -f /e…"   4 minutes ago       Up 4 minutes                                                                                     naughty_davinci
8bc97beeed6f        alpine              "/bin/sh"                30 minutes ago      Up 30 minutes                                                                                    kaivi_test6
a56a5c0fb482        nginx:1.16.1        "nginx -g 'daemon of…"   43 minutes ago      Up 43 minutes       0.0.0.0:50->50/udp, 80/tcp, 0.0.0.0:443->443/tcp, 172.20.32.101:83->80/udp   kaivi_test5
4ac2c4f97459        nginx:1.16.1        "nginx -g 'daemon of…"   45 minutes ago      Up 45 minutes       80/tcp, 172.20.32.101:82->80/udp                                             kaivi_test4
93974f01ee64        nginx:1.16.1        "nginx -g 'daemon of…"   About an hour ago   Up About an hour    172.20.32.101:10003->80/tcp                                                  kaivi_test3
5522e58261b9        nginx:1.16.1        "nginx -g 'daemon of…"   About an hour ago   Up About an hour    172.20.32.101:81->80/tcp                                                     kaivi_test2
93d953d6c30a        nginx:1.16.1        "nginx -g 'daemon of…"   About an hour ago   Up About an hour    0.0.0.0:80->80/tcp                                                           kaivi_test1
61d042ca6330        nginx:1.16.1        "nginx -g 'daemon of…"   About an hour ago   Up About an hour    0.0.0.0:10002->80/tcp                                                        kaivi_test
81718abe85cc        nginx:1.16.1        "nginx -g 'daemon of…"   About an hour ago   Up About an hour    0.0.0.0:10001->80/tcp                                                        tender_aryabhata
root@Docker-1:~# docker stop naughty_davinci
naughty_davinci
root@Docker-1:~# docker ps -f name=naughty_davinci
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
root@Docker-1:~# docker start naughty_davinci
naughty_davinci
root@Docker-1:~# docker ps -f name=naughty_davinci
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
e89d3650d99d        alpine              "/usr/bin/tail -f /e…"   5 minutes ago       Up 3 seconds                            naughty_davinci

进入到正在运行的容器

在单机运行容器时,有的时候涉及到进入容器查看或者修改内容。有几种不同的方式可以进入运行中的容器,比较推荐使用 nsenter 命令进入容器(name space enter)

使用 attach
使用命令 docker attach NAME进入运行的容器,attach 类似于 vnc,在容器中的每个操作会在各个终端显示,所有使用此方式进入容器的操作都是同步显示的且使用 exit 命令退出后容器将被关闭,不推荐使用,其要求需要进入到有 shell环境的容器,这里以centos镜像为例:

root@Docker-1:~# docker pull centos
root@Docker-1:~# docker run -it centos bash
在另外一个终端运行
root@Docker-1:~# docker attach 15188b202e6b
#在另外一个窗口启动测试页面是否同步

在这里插入图片描述
在不同的主机终端进入 ubuntu 容器后,操作都是同步的,在容器中都分配了同一个终端。一边退出后,其它的终端也退出了,退出后容器也关闭了。

使用 exec
可以使用 docker exec 命令在容器中执行单次命令或是进入容器,不大推荐此方式,使用docker exec 命令进入容器后 exit 退出容器其并不会停止。

root@Docker-1:~# docker exec -it kaivi_test6 sh
/ # echo $SHELLS

/ # echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
/ # exit
root@Docker-1:~# docker ps -f name=kaivi_test6 # 容器未退出
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
8bc97beeed6f        alpine              "/bin/sh"           41 minutes ago      Up 41 minutes                           kaivi_test6

使用 nsenter
推荐使用 nsenter 命令进入容器,该命令需要通过容器的 PID 进入到容器内部,比较麻烦。
不过可以使用docker inspect 命令获取到容器的 PID。

安装 nsenter 工具,包名 Ubuntu 和 CentOS 一样都要安装 util-linux

root@Docker-1:~# apt install util-linux

root@Docker-1:~#  man nsenter
NAME
       nsenter - run program with namespaces of other processes # 使用其他进程的名称空间运行程序

SYNOPSIS
       nsenter [options] [program [arguments]]
       。。。

docker inspect NAME/ID 命令使用,该命令用来获取当前运行的容器的底层对象信息,以 JSON格式返回到标准输出。

root@Docker-1:~# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               1.16.1              16af99d71a72        18 hours ago        127MB
alpine              latest              a187dde48cd2        3 weeks ago         5.6MB
centos              latest              470671670cac        3 months ago        237MB
root@Docker-1:~# docker run -it -d alpine
54cd0e05ee0d8f5c4c1f652e3f9e4e5426bec53677721a8886010ff2b9dba14d
root@Docker-1:~# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
54cd0e05ee0d        alpine              "/bin/sh"           7 seconds ago       Up 6 seconds                            zealous_tesla
root@Docker-1:~# docker inspect zealous_tesla
[
    {
        "Id": "54cd0e05ee0d8f5c4c1f652e3f9e4e5426bec53677721a8886010ff2b9dba14d",
        "Created": "2020-04-17T04:40:21.494420684Z",
        "Path": "/bin/sh",
        "Args": [],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 7348,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2020-04-17T04:40:21.918256845Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
后面省略。。。

可以使用该命令返回的 JSON 格式中的键来获取特定的信息,这样就可以获取当前运行的
容器的任何信息如:

root@Docker-1:~# docker inspect -f "{{.NetworkSettings.IPAddress}}" zealous_tesla
172.17.0.2        #   # -f 选项指定模板,模板是go语言风格的模板

root@Docker-1:~# docker inspect -f "{{.NetworkSettings.MacAddress}}" zealous_tesla
02:42:ac:11:00:02

docker inspect -f "{{.State.Pid}}" NAME/ID 获取容器的 PID。获取到 docker 容器的 PID,就可以使用 nsenter 命令通过 PID 进入到容器内。

root@Docker-1:~# docker run -it  -d -p 80:80 nginx:1.16.1
7016fd0210c6155c26ed0c657ab3f2025e4da39f6e0d33b00ad5435e882b4f15
root@Docker-1:~# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
7016fd0210c6        nginx:1.16.1        "nginx -g 'daemon of…"   9 seconds ago       Up 8 seconds        0.0.0.0:80->80/tcp   ecstatic_kowalevski
54cd0e05ee0d        alpine              "/bin/sh"                23 minutes ago      Up 23 minutes                            zealous_tesla
root@Docker-1:~# docker inspect -f "{{.NetworkSettings.IPAddress}}" ecstatic_kowalevski
172.17.0.3
root@Docker-1:~# docker inspect -f "{{.State.Pid}}" ecstatic_kowalevski
7804
# 获取到docker容器的PID,就可以使用nsenter命令通过PID进入到容器内
root@Docker-1:~# nsenter -t 7804 -m -u -i -n -p 
mesg: ttyname failed: No such device 
root@7016fd0210c6:/# tty  # 未分配终端
not a tty
root@7016fd0210c6:/# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@7016fd0210c6:/# pwd
/
root@7016fd0210c6:/# echo "kaivi test"
kaivi test
root@7016fd0210c6:/# exit
logout
root@Docker-1:~# docker ps   # 退出容器后,容器任然运行
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
7016fd0210c6        nginx:1.16.1        "nginx -g 'daemon of…"   2 minutes ago       Up 2 minutes        0.0.0.0:80->80/tcp   ecstatic_kowalevski
54cd0e05ee0d        alpine              "/bin/sh"                26 minutes ago      Up 26 minutes                            zealous_tesla

使用脚本
由于使用 nsenter 命令进入容器需要提前使用docker inspect -f "{{.State.Pid}}"来获取容器 PID,比较麻烦,一个折中的方案是将 nsenter 命令和docker inspect命令写入脚本,进入某个容器时,通过脚本和容器名称就可以进入。

脚本可以这样写:将容器名作为参数传给脚本

#!/bin/bash
if [[ $# -eq 0 ]]; then
    echo "Usage: `basename $0` CONTAINER_NAME"
    exit 80;
fi

enter(){
    local C_NAME=$1
    PID=`docker inspect -f "{{.State.Pid}}" ${C_NAME}`
    nsenter -t ${PID} -m -u -n -i -p
}

enter $1

测试脚本是否可以使用:

root@Docker-1:~# cd /data/
root@Docker-1:/data# vim enter_container.sh
root@Docker-1:/data# cat enter_container.sh 
#!/bin/bash
if [[ $# -eq 0 ]]; then
    echo "Usage: `basename $0` CONTAINER_NAME"
    exit 80;
fi

enter(){
    local C_NAME=$1
    PID=`docker inspect -f "{{.State.Pid}}" ${C_NAME}`
    nsenter -t ${PID} -m -u -n -i -p
}

enter $1
root@Docker-1:/data# chmod a+x enter_container.sh 
root@Docker-1:/data# ./enter_container.sh 
Usage: enter_container.sh CONTAINER_NAME
root@Docker-1:/data# echo $?
80
root@Docker-1:/data# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
7016fd0210c6        nginx:1.16.1        "nginx -g 'daemon of…"   6 minutes ago       Up 6 minutes        0.0.0.0:80->80/tcp   ecstatic_kowalevski
54cd0e05ee0d        alpine              "/bin/sh"                29 minutes ago      Up 29 minutes                            zealous_tesla
root@Docker-1:/data# ./enter_container.sh ecstatic_kowalevski
mesg: ttyname failed: No such device
root@7016fd0210c6:/# echo "kaivi test 1"
kaivi test 1
root@7016fd0210c6:/# exit
logout

查看容器内部 hosts 文件
在 Docker 容器实例中,默认容器会将自己的 ID 添加到 hosts 文件中。
这样容器可以将自己的 ID 解析为自己的 IP。

root@Docker-1:~# docker run -it -p 82:80 --name=nginx_host nginx:1.16.1 /bin/bash
root@a56389a0e2df:/# 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.4  a56389a0e2df    # 默认容器会将自己的ID添加到hosts文件中
root@a56389a0e2df:/# ping a56389a0e2df   
bash: ping: command not found
root@a56389a0e2df:/# apt update
。。。
root@a56389a0e2df:/# apt install iputils-ping -y
。。。
root@a56389a0e2df:/# ping a56389a0e2df   # ping此容器ID后其将ID解析为自己的IP
PING a56389a0e2df (172.17.0.4) 56(84) bytes of data.
64 bytes from a56389a0e2df (172.17.0.4): icmp_seq=1 ttl=64 time=0.013 ms
64 bytes from a56389a0e2df (172.17.0.4): icmp_seq=2 ttl=64 time=0.024 ms
64 bytes from a56389a0e2df (172.17.0.4): icmp_seq=3 ttl=64 time=0.066 ms

批量关闭正在运行的容器

root@Docker-1:~# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS                NAMES
a56389a0e2df        nginx:1.16.1        "/bin/bash"              7 minutes ago       Exited (0) 42 seconds ago                        nginx_host
b8b50669060f        nginx:1.16.1        "/bin/bash"              8 minutes ago       Created                                          nginx_host_test
7016fd0210c6        nginx:1.16.1        "nginx -g 'daemon of…"   19 minutes ago      Up 19 minutes               0.0.0.0:80->80/tcp   ecstatic_kowalevski
0c4104ed16c1        nginx:1.16.1        "nginx -g 'daemon of…"   22 minutes ago      Exited (0) 19 minutes ago                        frosty_haslett
54cd0e05ee0d        alpine              "/bin/sh"                42 minutes ago      Up 42 minutes                                    zealous_tesla
15188b202e6b        centos              "bash"                   2 hours ago         Exited (0) 2 hours ago                           lucid_euler
e76aea40683c        centos              "bash"                   2 hours ago         Exited (0) 2 hours ago                           vigilant_perlman
046dd4df9922        alpine              "/bin/sh"                2 hours ago         Exited (0) 2 hours ago                           naughty_wescoff
cbe1a84960ce        alpine              "/bin/sh"                2 hours ago         Exited (0) 2 hours ago                           kaivi_test7
46b415548bbd        nginx:1.16.1        "nginx -g 'daemon of…"   4 hours ago         Exited (0) 4 hours ago                           hardcore_jackson
b15e4ffee417        alpine              "sh"                     4 hours ago         Exited (0) 4 hours ago                           zen_borg
0efb1d4d3d75        nginx:1.16.1        "nginx -g 'daemon of…"   5 hours ago         Exited (0) 5 hours ago                           vigilant_noether
b5cec0fd4a18        nginx:1.16.1        "nginx -g 'daemon of…"   13 hours ago        Exited (0) 12 hours ago                          vigorous_shockley

root@Docker-1:~# docker ps -a -q
a56389a0e2df
b8b50669060f
7016fd0210c6
0c4104ed16c1
54cd0e05ee0d
15188b202e6b
e76aea40683c
046dd4df9922
cbe1a84960ce
46b415548bbd
b15e4ffee417
0efb1d4d3d75
b5cec0fd4a18

root@Docker-1:~# docker stop `docker ps -a -q`
a56389a0e2df
b8b50669060f
7016fd0210c6
0c4104ed16c1
54cd0e05ee0d
15188b202e6b
e76aea40683c
046dd4df9922
cbe1a84960ce
46b415548bbd
b15e4ffee417
0efb1d4d3d75
b5cec0fd4a18
root@Docker-1:~# root@Docker-1:~# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

批量强制关闭正在运行的容器

root@Docker-1:~# docker start `docker ps -a -q`
a56389a0e2df
b8b50669060f
54cd0e05ee0d
15188b202e6b
e76aea40683c
046dd4df9922
cbe1a84960ce
46b415548bbd
b15e4ffee417

root@Docker-1:~# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
a56389a0e2df        nginx:1.16.1        "/bin/bash"              10 minutes ago      Up 13 seconds       0.0.0.0:82->80/tcp   nginx_host
b8b50669060f        nginx:1.16.1        "/bin/bash"              12 minutes ago      Up 13 seconds       0.0.0.0:80->80/tcp   nginx_host_test
54cd0e05ee0d        alpine              "/bin/sh"                About an hour ago   Up 12 seconds                            zealous_tesla
15188b202e6b        centos              "bash"                   2 hours ago         Up 12 seconds                            lucid_euler
e76aea40683c        centos              "bash"                   2 hours ago         Up 11 seconds                            vigilant_perlman
cbe1a84960ce        alpine              "/bin/sh"                3 hours ago         Up 11 seconds                            kaivi_test7
46b415548bbd        nginx:1.16.1        "nginx -g 'daemon of…"   4 hours ago         Up 10 seconds       80/tcp               hardcore_jackson
b15e4ffee417        alpine              "sh"                     4 hours ago         Up 10 seconds                            zen_borg
root@Docker-1:~# docker kill `docker ps -a -q`
a56389a0e2df
b8b50669060f
54cd0e05ee0d
15188b202e6b
e76aea40683c
cbe1a84960ce
46b415548bbd
b15e4ffee417

root@Docker-1:~# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

批量删除已退出容器

root@Docker-1:~# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
root@Docker-1:~# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                        PORTS               NAMES
a56389a0e2df        nginx:1.16.1        "/bin/bash"              13 minutes ago      Exited (137) 2 minutes ago                        nginx_host
b8b50669060f        nginx:1.16.1        "/bin/bash"              14 minutes ago      Exited (137) 2 minutes ago                        nginx_host_test
7016fd0210c6        nginx:1.16.1        "nginx -g 'daemon of…"   25 minutes ago      Exited (128) 5 minutes ago                        ecstatic_kowalevski
0c4104ed16c1        nginx:1.16.1        "nginx -g 'daemon of…"   28 minutes ago      Exited (128) 25 minutes ago                       frosty_haslett
54cd0e05ee0d        alpine              "/bin/sh"                About an hour ago   Exited (137) 2 minutes ago                        zealous_tesla
15188b202e6b        centos              "bash"                   2 hours ago         Exited (137) 2 minutes ago                        lucid_euler
e76aea40683c        centos              "bash"                   2 hours ago         Exited (137) 2 minutes ago                        vigilant_perlman
046dd4df9922        alpine              "/bin/sh"                2 hours ago         Exited (0) 2 minutes ago                          naughty_wescoff
cbe1a84960ce        alpine              "/bin/sh"                3 hours ago         Exited (137) 2 minutes ago                        kaivi_test7
46b415548bbd        nginx:1.16.1        "nginx -g 'daemon of…"   4 hours ago         Exited (137) 2 minutes ago                        hardcore_jackson
b15e4ffee417        alpine              "sh"                     4 hours ago         Exited (137) 2 minutes ago                        zen_borg
0efb1d4d3d75        nginx:1.16.1        "nginx -g 'daemon of…"   6 hours ago         Exited (128) 5 hours ago                          vigilant_noether
b5cec0fd4a18        nginx:1.16.1        "nginx -g 'daemon of…"   13 hours ago        Exited (128) 12 hours ago                         vigorous_shockley
root@Docker-1:~# docker start a56389a0e2df
a56389a0e2df
root@Docker-1:~# docker start 15188b202e6b
15188b202e6b
root@Docker-1:~# docker start b15e4ffee417
b15e4ffee417
root@Docker-1:~# 
root@Docker-1:~# docker ps 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                NAMES
a56389a0e2df        nginx:1.16.1        "/bin/bash"         14 minutes ago      Up 23 seconds       0.0.0.0:82->80/tcp   nginx_host
15188b202e6b        centos              "bash"              2 hours ago         Up 13 seconds                            lucid_euler
b15e4ffee417        alpine              "sh"                4 hours ago         Up 5 seconds                             zen_borg
root@Docker-1:~# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                        PORTS                NAMES
a56389a0e2df        nginx:1.16.1        "/bin/bash"              14 minutes ago      Up 30 seconds                 0.0.0.0:82->80/tcp   nginx_host
b8b50669060f        nginx:1.16.1        "/bin/bash"              15 minutes ago      Exited (137) 3 minutes ago                         nginx_host_test
7016fd0210c6        nginx:1.16.1        "nginx -g 'daemon of…"   26 minutes ago      Exited (128) 6 minutes ago                         ecstatic_kowalevski
0c4104ed16c1        nginx:1.16.1        "nginx -g 'daemon of…"   29 minutes ago      Exited (128) 26 minutes ago                        frosty_haslett
54cd0e05ee0d        alpine              "/bin/sh"                About an hour ago   Exited (137) 3 minutes ago                         zealous_tesla
15188b202e6b        centos              "bash"                   2 hours ago         Up 20 seconds                                      lucid_euler
e76aea40683c        centos              "bash"                   2 hours ago         Exited (137) 3 minutes ago                         vigilant_perlman
046dd4df9922        alpine              "/bin/sh"                2 hours ago         Exited (0) 3 minutes ago                           naughty_wescoff
cbe1a84960ce        alpine              "/bin/sh"                3 hours ago         Exited (137) 3 minutes ago                         kaivi_test7
46b415548bbd        nginx:1.16.1        "nginx -g 'daemon of…"   4 hours ago         Exited (137) 3 minutes ago                         hardcore_jackson
b15e4ffee417        alpine              "sh"                     4 hours ago         Up 11 seconds                                      zen_borg
0efb1d4d3d75        nginx:1.16.1        "nginx -g 'daemon of…"   6 hours ago         Exited (128) 5 hours ago                           vigilant_noether
b5cec0fd4a18        nginx:1.16.1        "nginx -g 'daemon of…"   13 hours ago        Exited (128) 12 hours ago                          vigorous_shockley
root@Docker-1:~# docker rm -f `docker ps -a -q -f status=exited`  # -f 选项指定过滤条件
b8b50669060f
7016fd0210c6
0c4104ed16c1
54cd0e05ee0d
e76aea40683c
046dd4df9922
cbe1a84960ce
46b415548bbd
0efb1d4d3d75
b5cec0fd4a18
root@Docker-1:~# docker ps -a 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                NAMES
a56389a0e2df        nginx:1.16.1        "/bin/bash"         15 minutes ago      Up About a minute   0.0.0.0:82->80/tcp   nginx_host
15188b202e6b        centos              "bash"              2 hours ago         Up About a minute                        lucid_euler
b15e4ffee417        alpine              "sh"                4 hours ago         Up About a minute                        zen_borg

docker ps命令使用-f选项可以选择性的过滤容器,可以基于容器名称和状态

root@Docker-1:~# docker ps -a 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                NAMES
a56389a0e2df        nginx:1.16.1        "/bin/bash"         17 minutes ago      Up 3 minutes        0.0.0.0:82->80/tcp   nginx_host
15188b202e6b        centos              "bash"              2 hours ago         Up 3 minutes                             lucid_euler
b15e4ffee417        alpine              "sh"                4 hours ago         Up 3 minutes                             zen_borg

root@Docker-1:~# docker ps -a -f name=nginx_host
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                NAMES
a56389a0e2df        nginx:1.16.1        "/bin/bash"         18 minutes ago      Up 4 minutes        0.0.0.0:82->80/tcp   nginx_host

删除所有容器

使用docker ps命令的-q选项和-a选项就可以获取所有的容器 ID,再使用docker rm IDs命令批量删除容器。

root@Docker-1:~# docker rm -f `docker ps -a -q`
a56389a0e2df
15188b202e6b
b15e4ffee417
root@Docker-1:~# docker ps 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

指定容器 DNS

Docker 容器采用的 Dns 服务默认采用宿主机的 dns 地址,也可以在创建和启动容器时指定 dns。

默认的 DNS

# 查看主机DNS
root@Docker-1:~# systemd-resolve --status
Global
         DNS Servers: 114.114.114.114
          DNSSEC NTA: 10.in-addr.arpa
.......
# 创建容器并查看默认的DNS
root@Docker-1:~# docker run -it --name=DNS_ins centos /bin/bash
[root@70c19c138315 /]# cat /etc/resolv.conf 
nameserver 114.114.114.114
nameserver 8.8.8.8

指定 DNS

root@Docker-1:~# docker run -it --name=DNS_INI --rm --dns=223.6.6.6 centos /bin/bash
[root@31737e23f8f3 /]# cat /etc/resolv.conf 
nameserver 223.6.6.6    # 查看容器中的DNS为指定的DNS
[root@31737e23f8f3 /]# 

参考Reference

Linux Namespace-WIKI
Linux Cgroups 文档 manpage
Docker-pros-and-cons
Discussing Docker. Pros and Cons

更多咨询,关注微信公众号

Docker学习(1)-Docker简介

Kaivi

一、简介

统称来说,容器是一种工具,指的 是可以装下其它物品的工具,以方便人类归纳放置 物品 、存储和异地运输具体来说比如人类使用的 衣柜 、行李箱、 背包 等可以成为容器,但 今天 我们 所说 的容器是一种 IT 技术。

容器技术是虚拟化、云计算、大数据之后的一门新兴的并且是炙手可热的新技术, 容器 技术提高了硬件资源利用率、 方便 了 企业 的业务快速横向扩容、 实现 了业务 宕机自愈功能 ,因此未来数年会 是一个容器愈发流行的 时代 这是 一个对于IT 行业 来说非常有影响和价值的技术,而对于 IT 行业 的从业者来说, 熟练 掌握容器 技术无疑是一 个 很有前景 的行业 工作 机会。
容器技术最早出现 在 freebsd 叫做 jail 。

docker 简介

Docker 是 什么

https://www.docker.com/#官方链接

首先Docker 是 一个 在 2013 年 开源的 应用 程序 并且 是 一个 基于 go 语言编写是一个 开源的 PAAS 服务 Platform as a Service 平台即服务 的 缩写 go 语言是 由google 开发 docker 公司 最早 叫 dotCloud 后 由于 D ocker 开源后 大受欢迎就 将公司 改名为 Docker Inc 总部位于美国加州的旧金山 D ocker 是基于 linux 内核 实现 Docker 最早 采用 LXC 技术 LinuX Container 的简写 LXC 是 Linux 原生支持的容器 技术 可以提供轻量级的虚拟化 可以说 docker 就是基于 LXC 发展起来的,提供 LXC 的高级封装,发展标准的配置方法 而 虚拟化 技术 KVM Kernel-based Virtual Machine 基于 模块实现, D ocker 后 改为自己研发 并开源 的 runc 技术 运行容器。

Docker 相比 虚拟机的交付 速度 更快 资源消耗更低 D ocker 采用 客户端、服务端架构 ,使用远程 API 来管理和创建 Docker 容器 ,其可以轻松的创建一个轻量级的、 可 移植 的 、自给自足的容器, docker 的 三大理念是 build( 构建 、ship 运输 、 run 运行 D ocker 遵从 ap ache 2.0 协议 ,并通过 namespace 及cgroup 等)来提供容器的资源隔离与安全保障等 ,所以 Docke 容器在运行时不需要类似虚拟机(空运行的虚拟机占用物理机 6 8% 性能)的额外资源开销,因此可以大幅提高资源利用率 总而 言之 Docker 是一种用了新颖方式实现的轻量级虚拟机 类似于 VM 但是在原理和应用上和 VM 的差别还是很大的,并且 docker的专业叫法是应用容器(Application Container)。

Docker 的组成

https://docs.docker.com/get-started/overview/#Docker 的组成

Docker 为客服端-服务器架构。Docker 服务端也就是 Docker 的守护进程(docker daemon),Docker 客户端通过 REST API 和守护进程通信,Docker daemon 负责创建、运行和分发容器。客户端和服务端可以运行于同一系统,也可以使用客户端连接远程服务进程。在同一系统时客户端和服务端通过 UNIX sockets 通信,不在同一系统则通过网络接口通信。

Docker主机 Host 一个物理机或虚拟机,用于运行 D ocker 服务 进程和容器。
Docker 服务端 Server D ocker 守护 进程, 运行 docker 容器。
Docker 客户端 Client 客户端 使用 docker 命令 或其他工具 调用 docker API 。
Docker 仓库 Registry 保存 镜像的仓库,类似于 git 或 svn 这样的版本控制系
Docker镜像 Images 镜像 可以 理解为创建实例 使用 的模板。
Docker 容器 Container )): 容器是 从镜像生成对外提供服务的一个 或 一组服务 。

https://hub.docker.com/#官方仓库

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

Docker 组成
Docker 由多项技术组成,既包括 Linux 内核的功能,也包括 Docker 自己开发的库,还包括了 OCI 组织定义的容器标准。

Docker engine
Docker 引擎由 Docker 服务端守护进程、Docker 客户端及它们之间交流的 REST API组成。Docker 引擎是运行和管理容器的核心。

在这里插入图片描述
Server 服务端
Docker 服务端(Server):Docker 守护进程(dockerd),运行 docker 容器。并接受docker client(docker 命令工具)的指令,已进行相应的创建和运行容器的工作。其监听 Docker API 请求并管理 Docker 对象(镜像,容器,网络和存储等)。服务端守护程序之间也可以通讯以管理 Docker 服务。

Client 客户端
Docker 客户端(Client):用于向 Docker 服务端发送指令的命令行工具,在 linux下的客户端使用 docker 命令调用 docker REST API 和 服务端通讯。如:当运行如下命令时:

docker run -it -p 80:80 nginx:1.16.1

Docker 客户端将该命令发送给dockerd,dockerd进程解析该命令后会寻找nginx:1.16.1这个镜像,并启动为容器,-it表示交互式运行容器并为其分配一个伪终端,-p 80:80表示将主机的 80 端口映射到容器的 80 端口。

Registry 仓库
Docker 仓库(Registry): 保存镜像的仓库,类似于 git 或 svn 这样的版本控制系。
Docker Hub 是 Docker 建立的公开镜像仓库,任何人都可以使用。
运行docker pull IMAGE时,Docker 默认会到 Docker Hub 仓库拉取镜像 IMAGE。
运行docker run IMAGE时,如果本地没有该镜像,则 Docker 也会到 Docker Hub拉取该镜像并由 dockerd 创建容器运行。

Docker objects 对象
当使用 Docker 时,实际上就是创建和使用镜像、容器、网络和存储等对象。

images 镜像
Docker 镜像(Images):镜像可以理解为创建容器实例使用的模板。

镜像为包含创建容器所需指令的只读模板(read-only template)。一般来说,我们使用的镜像都是基于另一个镜像创建的,在前一个镜像的基础上进行了一些自定义。例如:可以基于 ubuntu 镜像创建另一个镜像,自定义的内容仅仅是安装 Apache 服务器和一些工具及使得这些软件能够运行的配置细节。

container 容器
Docker 容器(Container): 容器是从镜像生成对外提供服务的一个或一组服务。

简单的说,一个容器就是一个镜像的可运行实例。可以使用 Docker API 来创建、启动、停止、移动或删除一个容器。默认情况下,各个容器之间及容器和运行 Docker 的主机系统之间都是隔离的。可以控制一个容器的网络、存储、或者其它的底层系统和其他容器之间的隔离细节。

一个容器被其对应的镜像和用户创建其时所提供的选项所定义,当一个容器被移除后,任何对其作出的更改(未存储在磁盘的信息)都将消失。

下面的命令运行了一个 ubuntu 镜像,以交互式运行在本地命令行会话中,并运行程序/bin/bash。

~$ docker run -it ubuntu /bin/bash

当运行上面的命令时,发生了以下事情(假设使用默认的镜像仓库配置):

如果本地没有名为ubuntu的镜像,Docker 就会从默认配置的镜像仓库拉取该镜像,相当于运行了命令
~$ docker pull ubuntu。
镜像拉取到本地后,Docker 创建一个新的容器,相当于运行命令docker container create
Docker 分配一个可读写的文件系统给该容器,作为其最后一层。这样使得运行的容器可以在自己的文件系统中创建和修改文件和目录。
Docker 创建一个网络接口来将容器连接到默认的网络上(如果不指定任何网络选项),该过程中 docker 分配了一个 IP 给容器。默认情况下容器是可以通过主机的网络接口访问外部网络的。
Docker 运行该容器并运行/bin/bash,由于容器是交互式运行并依附于当前终端(-it),所以可以在 bash 中输入命令来运行。
当运行键入exit后回车,就退出了/bin/bash,由于是交互式运行 ubuntu 容器,所以此时 ubuntu 容器也停止了运行,但是未被移除。后面还可以再次运行该容器。

services 服务
服务(Service)允许在多个 Docker daemon 之间进行容器伸缩管理。多个 Docker daemon共同工作结合多个manager和多个worker组成了 Docker swarm。Docker swarm 的每个成员都是一个 Docker daemon,各个 daemon 之间使用 Docker API 通讯。Service允许管理员定义预期的状态。Docker 引擎在 Docker1.12 版本后支持 swarm 模式。

Docker对比虚拟机

资源利用率更高:一台物理机可以运行数百个容器,但是一 般 只能运行数十个虚拟机 。
开销更小:不需要启动单独的虚拟机占用硬件资源。
启动速度更快:可以在数秒内完成启动。
体积小:不像虚拟机使用 GB 为计量单位,容器的大小使用 MB 为单位。

对比 指标 VMs-虚拟化 Container-容器
体积 重量级,GB 轻量级,MB
性能 性能损失大 接近 host 原生的性能表现
运行环境 每个应用运行于自己的 OS 所有容器应用运行于同一个 OS
虚拟化级别 硬件级别的虚拟化 OS 操作系统级的虚拟化
启动时间 可能需要几分钟 启动时间在几秒内,甚至几毫米
内存消耗 消耗大量内存 消耗少量内存,类似 OS 自己的进程
隔离级别 所有虚拟机和应用之间完全隔离,比较安全 进程级别的隔离,可能不安全

在这里插入图片描述
在这里插入图片描述
使用虚拟机是为了更好的实现服务运行环境隔离,每个虚拟机都有独立的内核,虚拟化可以实现不同操作系统的虚拟机,但是通常一个虚拟机只运行一个服务,很明显资源利用率比较低且造成不必要的性能损耗。创建虚拟机的目的是为了运行应用程序,比如 Nginx、PHP、Tomcat 等web 程序,使用虚拟机无疑带来了一些不必要的资源开销。

容器技术的出现则减少了中间大量的运行和转换环节,节约了大量不必要的性能损耗和体积占用。
在这里插入图片描述
但是,如上图 一个宿主机 运行了 N 个 容器, 多个容器带来的以下问题怎么解决
1.怎么样保证每个容器都有不同的文件系统并且能互不影响?
2.一个 docker 主进程内的各个容器都是其子进程,那么实现同一个主进程下不同类型的子进程? 各个进程间通信能相互访问 内 数据吗
3.每个容器怎么解决IP及端口分配的问题
4.多个容器的主机名能一样吗
5.每个容器都要不要有 root 用户?怎么解决账户重名问题?
以上问题 怎么 解决?

幸运的是,在前人的基础上(Linux 提供的基础功能),docker 成功解决了上述问题。
其中最重要的两项技术都由 Linux 内核提供:Linux Namespace技术和Linux Control Group技术。

Linux Namespace技术

Linux Namespace 是 Linux 系统的底层概念,其由内核实现。Linux 命名空间起源于 2002年 2.4.19 内核中的 mount 命名空间类。从 2006 年开始添加了其他名称空间,并一直持续。随着用户命名空间(User namespace)的引入,在内核 3.8 版本中完成了足够的容器支持功能。

到 Linux kernel 内核版本 4.10,已经有 7 种命名空间加入到其中。从完成的任务角度看,所有命名空间的功能都是相同的:每个进程都和一个命名空间相关联并且只能访问或者使用和该命名空间相关联的资源,这样一来每个进程对系统的资源都有一个唯一的角度。何种资源被隔离取决于为进程组所创建的命名空间类型。

一般,在 Linux 系统下,由于运行软件或者服务产生的新进程一般是由fork()系统调用生成,或者在 bash 中键入命令,bash 会调用exec()系统调用来生成普通的进程。但是容器进程是不一样的,当发送一个创建容器的请求给 Docker 引擎时,Docker 引擎最终会调用clone()系统调用来生成容器进程,使用该系统调用就可以创建带有命名空间的容器化的进程。

在运行 Docker 容器时,Docker 会为该容器创建一组命名空间(在内存中表现为各种数据结构),该容器的多个方面都被限定在这一组命名空间中。各个 docker 容器运行在同一个 docker 主进程并且共用同一个宿主机系统内核,各 docker 容器运行在宿主机的用户空间,每个容器都要有类似于虚拟机一样的相互隔离的运行空间,但是容器技术是在一个进程内实现运行指定服务的运行环境,并且还可以保护宿主机内核不受其他进程的干扰和影响,如文件系统空间、网络空间、进程空间等。容器运行空间的相互隔离本质上是共同的内核上运行的不同的用户空间之间的隔离,目前内核提供的命名空间功能包括:

命名空间 功能 解释 clone()系统调用使用的 flag 引入时内核版本
MNT(mount namespace) 提供磁盘挂载点和文件系统的隔离能力 隔离挂载点(Mount point) CLONE_NEWNS Linux 2.4.19
IPC Namespace 进程间通信相关的隔离功能 隔离内核中的 System V IPC, POSIX message queues CLONE_NEWIPC Linux 2.6.19
UTS Namespace(UNIX Timesharing System) 提供主机名隔离能力 隔离主机名和 NIS 域名 CLONE+NEWUTS Linux 2.6.19
PID Namespace 提供进程隔离能力 隔离进程 ID 名字空间,不同的进程 ID 空间中进程 ID 从 1 开始 CLONE_NEWPID Linux 2.6.24
Net Namespace 提供网络隔离能力 隔离网络设备,栈,端口等 CLONE_NEWNET Linux 2.6.29
User Namespace 提供用户隔离能力 隔离用户 ID 和组 ID CLONE_NEWUSER Linux 3.8
Cgroup Namespace 提供 cgroup 的隔离 隔离 Cgroup 的根目录 CLONE_NEWCGROUP Linux 4.6

在 Linux 内核中,以下三个系统调用可以修改命名空间:

clone()系统调用,其使用 flag(上面表格中的 CLONE_NEW..) 来指定新的进程应当被合并到哪个新的命名空间。
unshare()系统调用,允许一个进程将其和其他进程共享的部分运行上下文分离开。
setns()系统调用, 进入一个文件描述符指定的名称空间。

命名空间 参考链接
MNT Namespace http://man7.org/linux/man-pages/man7/mount_namespaces.7@@man-pages.html
IPC Namespace http://man7.org/linux/man-pages/man7/ipc_namespaces.7@@man-pages.html
UTS Namespace http://man7.org/linux/man-pages/man7/uts_namespaces.7@@man-pages.html
PID Namespace http://man7.org/linux/man-pages/man7/pid_namespaces.7@@man-pages.html
Net Namespace http://man7.org/linux/man-pages/man7/network_namespaces.7@@man-pages.html
User Namespace http://man7.org/linux/man-pages/man7/user_namespaces.7@@man-pages.html
Linux Control Groups http://man7.org/linux/man-pages/man7/cgroups.7@@man-pages.html

Cgroups介绍

Linux Cgroups 的全称是 Linux Control Groups,它最主要的作用,就是限制一个进程组能够使用的资源上限,包括 CPU、内存、磁盘、网络带宽等等。此外,还能够对进程进行优先级设置,以及将进程挂起和恢复等操作。

Linux Control Groups 为内核的一项特性,该特性可将多个进程组织成层级结构的进程组,这些进程组所使用的各种资源即可以被限制和监控。内核的 Cgroups 接口通过叫做 cgroupfs 的伪文件系统(pseudo-filesystem)提供。进程的分组功能(Process groups)是在 cgroup 的核心代码(内核代码)中实现的,而资源的跟踪和限制功能则在一组分别控制每种资源类型(per-resource-type)的子系统中实现(这些子系统分别控制内存,CPU 等)

Cgroups 术语解释

cgroup:一个 cgroup 就是与多个限制和参数绑定的进程,这些限制和参数通过cgroup 文件系统定义。
subsystem:一个 subsystem 就是用来修改和控制属于某个 cgroup 的进程行为的内核组件。内核实现了多个不同的子系统,这使得例如控制某个 cgroup 的 CPU 时间和可用内存等工作可行,也可以进行如:监控某个 cgroup 使用的 CPU 时间、暂停和恢复某个 cgroup 内的进程等工作。
resource controller:subsystem 有时也被叫做 resource controller(资源控制器,简称控制器)。

属于某个控制器的 cgroups 被组织成层级结构。通过在 cgroup 文件系统中创建、删除和重命名子文件夹来定义该层级结构。在层级结构的每一层都可以定义属性(即限制措施)。

查看内核所支持的 Cgroups 特性
在使用 Docker 创建和使用容器时,如果不对其做任何资源限制,则宿主机 OS可能会允许其占用无限大的内存空间,有时候会因为容器中运行的程序代码bug 导致程序会一直申请内存,直到把宿主机内存占完,为了避免此类的问题出现,宿主机有必要对容器进行资源分配限制,比如 CPU、内存等。而 Cgroups的功能正是解决以上问题的 Linux 内核功能特性。要使用 Cgroups,编译内核时必须带上CONFIG_CGROUP_XXX选项。可以查看内核编译参数来确定是否支持 Cgroups 功能。

在 Ubuntu 18.04.3 LTS 查看

root@Docker-1:~# uname -r
4.15.0-29-generic # # 内核版本为4.15.0
root@Docker-1:~# cat /boot/config-4.15.0-29-generic |grep CGROUP
CONFIG_CGROUPS=y
CONFIG_BLK_CGROUP=y
# CONFIG_DEBUG_BLK_CGROUP is not set
CONFIG_CGROUP_WRITEBACK=y
CONFIG_CGROUP_SCHED=y
CONFIG_CGROUP_PIDS=y
CONFIG_CGROUP_RDMA=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_HUGETLB=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_PERF=y
CONFIG_CGROUP_BPF=y
# CONFIG_CGROUP_DEBUG is not set
CONFIG_SOCK_CGROUP_DATA=y
CONFIG_NETFILTER_XT_MATCH_CGROUP=m
CONFIG_NET_CLS_CGROUP=m
CONFIG_CGROUP_NET_PRIO=y
CONFIG_CGROUP_NET_CLASSID=y
root@Docker-1:~# cat /boot/config-4.15.0-29-generic |grep CGROUP |grep -v "#" |wc -l
17  # ubuntu有17项Cgroups相关特性
同理在centos中也一样的查看 蚕食centos中提供Cgroups相关特性只有12个

Cgroups 在内核层默认已经开启,从 centos 和 ubuntu 对比结果来看,显然内核
较新的 ubuntu 支持的功能更多。

root@Docker-1:~# cat /boot/config-4.15.0-29-generic | grep "CG" | grep "MEM"
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y
# CONFIG_MEMCG_SWAP_ENABLED is not set
CONFIG_SLUB_MEMCG_SYSFS_ON=y

Cgroups 控制器具体实现介绍
cgroups 的最初 release V1 版本在 kernel-1.6.24 版本,此时已有多个控制器被实现,然而由于开发这些控制器时未形成统一协调的开发过程,导致了在控制器之间出现了不一致及 cgroup 层级管理变得比较复杂。由于初代的开发原因,在kernel-3.10 版本又重新开发了 cgroup 的 V2 版本,新版本于 kernel-4.5 由官方发布。由于兼容原因,V1 和 V2 并存与内核,V2 只实现了 V1 版本的部分控制器。

Cgroups 的版本 2 的控制器大多继承于版本 1,差异和详细说明可以在man7.ogr找到:

man7.ogr
Cgroups 使用例子

root@Docker-1:~# df -TH
Filesystem     Type      Size  Used Avail Use% Mounted on
udev           devtmpfs  969M     0  969M   0% /dev
tmpfs          tmpfs     200M  9.5M  191M   5% /run
/dev/sda1      ext4       98G  2.1G   91G   3% /
tmpfs          tmpfs     1.0G     0  1.0G   0% /dev/shm
tmpfs          tmpfs     5.3M     0  5.3M   0% /run/lock
tmpfs          tmpfs     1.0G     0  1.0G   0% /sys/fs/cgroup  # cgroup所在地的文件系统类型为tmpfs
/dev/sda3      ext4       49G   55M   47G   1% /data
/dev/sda2      ext4      968M   80M  822M   9% /boot
tmpfs          tmpfs     200M     0  200M   0% /run/user/0
root@Docker-1:~# ll /sys/fs/cgroup/ # 目前系统的cgroups表现为多个目录
total 0
drwxr-xr-x 15 root root 380 Apr 16 22:41 ./
drwxr-xr-x  9 root root   0 Apr 16 22:41 ../
dr-xr-xr-x  4 root root   0 Apr 16 22:41 blkio/
lrwxrwxrwx  1 root root  11 Apr 16 22:41 cpu -> cpu,cpuacct/
lrwxrwxrwx  1 root root  11 Apr 16 22:41 cpuacct -> cpu,cpuacct/
dr-xr-xr-x  4 root root   0 Apr 16 22:41 cpu,cpuacct/
dr-xr-xr-x  2 root root   0 Apr 16 22:41 cpuset/
dr-xr-xr-x  4 root root   0 Apr 16 22:41 devices/
dr-xr-xr-x  2 root root   0 Apr 16 22:41 freezer/
dr-xr-xr-x  2 root root   0 Apr 16 22:41 hugetlb/
dr-xr-xr-x  4 root root   0 Apr 16 22:41 memory/
lrwxrwxrwx  1 root root  16 Apr 16 22:41 net_cls -> net_cls,net_prio/
dr-xr-xr-x  2 root root   0 Apr 16 22:41 net_cls,net_prio/
lrwxrwxrwx  1 root root  16 Apr 16 22:41 net_prio -> net_cls,net_prio/
dr-xr-xr-x  2 root root   0 Apr 16 22:41 perf_event/
dr-xr-xr-x  4 root root   0 Apr 16 22:41 pids/
dr-xr-xr-x  2 root root   0 Apr 16 22:41 rdma/
dr-xr-xr-x  5 root root   0 Apr 16 22:41 systemd/
dr-xr-xr-x  5 root root   0 Apr 16 22:41 unified/

创建 Cgroups 和移动进程
cgroup 文件系统初始只包含单个根 cgroup(root cgroup),"/",所有进程都属于该组。要创建一个新的 group,即是在 cgroup 文件系统中创建一个新的目录:

~$ mkdi /sys/fs/cgroup/cpu/cg1  # 该动作就创建了一个新的cgroup

一个进程可以移动到 cgroup 中,通过将该进程的进程 PID 写入到cgroup.procs文件中即可:

~$ echo $$ > /sys/fs/cgroup/cpu/cg1/cgroup.procs 

root@Docker-1:~# echo $$
1469
root@Docker-1:~# ps -A |grep bash
  1350 tty1     00:00:00 bash
  1469 pts/0    00:00:00 bash

一次只能写一个 PID 到该文件。移动该进程的同时,其包含的线程也属于该组。

移除 cgroups
为了移除某个 cgroup,其必须没有子 cgroup 并且不包含任何进程。要移除cgroup 直接移除代表其的目录即可,里面的文件不用管。

容器管理工具简介
在 Linux 的 chroot、namespace、cgroups 的特性的支持下,具备了基础的容器运行环境,但是还需要有相应的容器创建与删除的管理工具、以及怎么样把容器运行起来、容器数据怎么处理、怎么进行启动与关闭等问题需要解决,于是容器管理技术出现了。早期主要使用了 LXC,目前主流使用 Docker。

https://linuxcontainers.org/#LCX官网
LXC
LXC 为 Linux Container 的简写。可以提供轻量级的虚拟化,以便隔离进程和资源。

Ubuntu 使用 LXC:

~$ apt install lxc lxd
~$ lxc-checkconfig #检查内核对lcx的支持状况,必须全部为lcx
~$ lxc-create -t 模板名称 -n lcx-test
~$ lxc-create -t download --name alpine12 -- --dist alpine  --release 3.9 --arch amd64
~$  lxc-start alpine12 #启动lxc容器
~$  lxc-attach  alpine12 #进入lxc容器

# 命令备注:
-t 模板: -t 选项后面跟的是模板,模式可以认为是一个原型,用来说明我们需
要一个什么样的容器(比如容器里面需不需要有vim, apache等软件).模板实际
上就是一个脚本文件(位于/usr/share/lxc/templates目录),我们这里指定
download模板(lxc-create会调用lxc-download脚本,该脚本位于刚说的模板目
录中)是说明我们目前没有自己模板,需要下载官方的模板
--name 容器名称: 为创建的容器命名
-- : --用来说明后面的参数是传递给download脚本的,告诉脚本需要下载什么样的模板
--dist 操作系统名称:指定操作系统
--release 操作系统: 指定操作系统,可以是各种Linux的变种
--arch 架构:指定架构,是x86还是arm,是32位还是64位

国内模板源地址
lxc 启动容器依赖于模板,但是做模板相对较难,需要手动一步步创构建文件系统、准备基础目录及可执行程序等,而且在大规模使用容器的场景很难横向扩展,另外后期代码升级也需要重新从头构建模板,基于以上种种原因便有了 docker。

Docker

Docker 启动一个容器也需要一个外部模板叫做镜像,docker 的镜像可以保存在一个公共的仓库共享使用,只要把镜像下载下来就可以使用,最主要的是可以在镜像基础之上做自定义配置并且可以再把其提交为一个镜像,一个镜像可以被启动为多个容器。

Docker 的镜像是分层构建的,镜像底层为库文件且属于只读层即不能写入也不能删除和修改数据,从镜像加载启动为一个容器后会生成一个可写层,其写入的数据会复制到容器目录,但是容器内的数据在删除容器后也会被随之删除。
在这里插入图片描述
pouch
pouch 为阿里巴巴在 docker 基础上开发并发开源的容器技术。
https://www.infoq.cn/article/alibaba-pouch#pouch介绍

https://github.com/alibaba/pouch#开源社区项目

Docker 优缺点

Docker 优势
快速部署: 在极短时间内可以部署成百上千个应用,可以快速交付产品到生产中。
高效虚拟化: 不需要额外的 hypervisor 程序支持,直接基于 linux 内核提供的功能实现应用虚拟化,相比虚拟机大幅提高性能和效率。
节省成本: 提高服务器利用率,降低 IT 支出。
简化配置: 将运行环境和应用打包保存至容器,使用时直接启动即可。
快速迁移和扩展: 容器可以夸平台运行在物理机、虚拟机、公有云等环境,良好的兼容性可以方便将应用从 A 宿主机迁移到 B 宿主机,甚至是不同的平台之间迁移。

Docker 不足
隔离性: Docker 管理的容器提供进程级别的隔离,而不是虚拟机接近硬件级别的隔离。这样的隔离性下,内核的 BUG 会影响任何运行于其上的容器。
大量的容器管理: 在大量的容器部署和管理方面,Docker 有不小的挑战,但是 google 的Kubernetes 可以帮忙。

Docker 容器的核心技术

实际上不仅仅是 Docker 容器,任何其他的容器,要想快速发展和进入到实际应用,都离不开下面的核心技术的支持。

容器规范
容器技术除了 docker 之外,还有 coreOS 的 rkt、阿里的 Pouch 等,为了保证容器生态系统的标准统一和维持健康可持续发展。包括 Linux 基金会、Docker、微软、红帽、谷歌、IBM 等公司在 2015 年 6 月共同成立了一个叫 open container initiative(OCI)的开源组织,其目的就是制定开放的标准的容器规范,目前 OCI 一共发布了两个规范,分别是 runtime spec 和 image format spec,有了这两个规范,不同的容器公司开发的容器只要兼容这两个规范,就可以保证不同公司之间使用的容器的可移植性和可操作性。

容器 runtime
runtime 是真正运行容器的地方,为了运行不同的容器,runtime 需要和操作系统内核紧密合作,以便为容器提供相应的运行环境。
目前主流的三种容器 runtime:
LXC:linux 上早期的 runtime,Docker 早期就是采用 lxc 作为 runtime。
runc:目前 Docker 默认的 runtime,runc 遵守 OCI 规范,因此可以兼容 lxc。
rkt:是 CoreOS 开发的容器 runtime,也符合 OCI 规范,所以使用 rktruntime也可以运行 Docker 容器。

runtime 只负责一件事,而且做得很好,那就是运行容器,Runc 运行容器时需要两种东西:
1.一个规格说明文件
2.表示某镜像的根文件系统的路径

容器管理工具
容器管理工具处于 runtime 和使用容器的用户之间,用于对用户提供图形或命令方式操作
管理容器,将用户操作传递给 runtime 执行。例如:
1.lxc 是 lxd 的管理工具。
2.Docker engine 是 Runc 的管理工具是,docker engine 包含后台 deamon 和 cli 两部分,大家经常提到的 Docker 就是指的 docker engine。
3.Rkt 的管理工具是 rkt cli。

容器构建定义工具
容器定义工和构建具允许用户定义容器的属性和内容,以方便容器能够被保存、共享和重建。
Docker 生态使用 Docker image 来创建容器。而 Docker image 是使用 Dockerfile 来定义。

Docker image : 是 docker 容器的模板,runtime 依据 docker image 创建容器。
Dockerfile : 是包含了多个命令的文本文件,通过 dockerfile 即可创建出 docker image。
ACI(App container image):与 docker image 类似,是 CoreOS 开发的 rkt 容器的镜像格式。

镜像仓库 Registry
在 Docker 生态中,Registry 用来统一保存镜像,叫做镜像仓库。镜像仓库可以分为公共仓库和私有仓库。

Image registry:docker 官方提供的私有仓库部署工具。
Docker hub:docker 官方的公共仓库,已经保存了大量的常用镜像,可以方便大家直接下载使用。
Harbor:vmware 提供的自带 web 界面自带认证功能的镜像仓库,目前有很多公司使用该仓库中的镜像。

容器编排工具
Docker 虽然可以在单个主机上运行多个容器,但是当多个容器在多个主机运行的时候,单独管理特定容器是相当复杂的而且很容易出错,而且也无法实现某一台主机宕机后容器自动迁移到其他主机从而实现高可用的目的,也无法实现动态伸缩容器的功能,因此需要有一种工具可以实现统一管理、动态伸缩、故障自愈、批量执行等容器管理高级功能,这就是容器编排引擎。

容器编排技术通常包括容器管理、调度、集群定义和服务发现等功能。随着需求的提出,出现了很多的容器编排工具,如下:

Docker swarm:Docker 自家开发的容器编排引擎。
Kubernetes:google 开发的容器编排引擎,google 内部项目 Borg 的开源实现版本,且其同时支持 docker 和 CoreOS 的容器编排。
Mesos+Marathon:通用的集群组员调度平台,mesos(资源分配)与 marathon(容器编排平台)一起提供容器编排引擎功能。

Docker 容器依赖的技术

这里指的 Docker 依赖的技术不是指其实现依赖的内核特性等技术,而是其作为容器技术普遍面临的技术依赖,即其大规模普及和应用于生产时的缺陷。幸运的是,可以使用第三方的各种技术来弥补 Docker 在多种环境下的功能缺陷(也不能说是缺陷,只能说一个平台不是万能的,能面对各种境况。)

容器网络
Docker 自带的网络 docker network 仅支持管理单机上的容器网络,当多主机运行的时候需要使用第三方开源网络,例如 calico、flannel 等。

服务发现
容器的动态扩容特性决定了容器 IP 也会随之变化,因此需要有一种机制可以自动识别并将用户请求动态转发到新创建的容器上,kubernetes 自带服务发现功能,需要结合kube-dns 服务解析内部域名。

容器监控
可以通过原生命令 docker ps/top/stats 查看容器运行状态,另外也可以使heapster或Prometheus 等第三方监控工具监控容器的运行状态。

数据管理
容器的动态迁移会导致其在不同的 Host 之间迁移,因此如何保证与容器相关的数据也能随之迁移或随时访问,可以使用逻辑卷/存储挂载等方式解决。

日志收集
Docker 虽然自带原生的日志查看工具 docker logs,但是容器内部的日志需要通过 ELK 等专门的日志收集分析和展示工具进行处理,docker 并不能分门别类的处理个容器日志。

更多咨询,关注微信公众号

K8S学习–Kubeadm-6–Pod生命周期和探针

Kaivi

K8S学习–Kubeadm-1-组件简介

K8S学习–Kubeadm-2-安装部署

K8S学习–Kubeadm-3-Dashboard部署和升级

K8S学习–Kubeadm-4-测试运行Nginx+Tomcat

K8S学习–Kubeadm-5-资源管理核心概念

一:Pod的状态和探针:

https://kubernetes.io/zh/docs/concepts/workloads/pods/pod-lifecycle/ #Pod的状态和探针

在这里插入图片描述

第一阶段:
Pending(挂起):
#正在创建Pod但是Pod中的容器还没有全部被创建完成,处于此状态的Pod应该检查Pod依赖的存储是否有权限挂载、镜像是否可以下载、调度是否正常等。
Failed
#Pod中有容器启动失败而导致pod工作异常。
Unknown
#由于某种原因无法获得pod的当前状态,通常是由于与pod所在的node节点通信错误。
Succeeded
#Pod中的所有容器都被成功终止即pod里所有的containers均已terminated。

第二阶段:
Unschedulable:
#Pod不能被调度,kube-scheduler没有匹配到合适的node节点 筛选主机的限制
PodScheduled
#pod正处于调度中,在kube-scheduler刚开始调度的时候,还没有将pod分配到指定的pid,在筛选出合适的节点后就会更新etcd数据,将pod分配到指定的pod
Initialized
#所有pod中的初始化容器已经完成了
ImagePullBackOff:
#Pod所在的node节点下载镜像失败 网络问题 权限问题 镜像服务器地址写错或者镜像名称写错
Running
#Pod内部的容器已经被创建并且启动。
Ready
#表示pod中的容器已经可以提供访问服务

在这里插入图片描述

Pod调度过程:

k8s 实战案例 2.1.3:kube-scheduler:需要安装好二进制文件才知道如何调度

Pod探针:

https://kubernetes.io/zh/docs/concepts/workloads/pods/pod-lifecycle/#%E5%AE%B9%E5%99%A8%E6%8E%A2%E9%92%88

探针简介:

探针 是由 kubelet 对容器执行的定期诊断,以保证Pod的状态始终处于运行状态,要执行诊断,kubelet 调用由容器实现的Handler,有三种类型的处理程序:
基于命令式的访问探测方式,类似redis mysql rebbitmq等这些服务 需要基于命令在内部命令式访问

ExecAction
#在容器内执行指定命令,如果命令退出时返回码为0则认为诊断成功。

TCPSocketAction
#对指定端口上的容器的IP地址进行TCP检查,如果端口打开,则诊断被认为是成功的。类似HAproxy 探测端口

HTTPGetAction(推荐)
#对指定的端口和路径上的容器的IP地址执行HTTPGet请求,如果响应的状态码大于等于200且小于 400,则诊断被认
为是成功的。 301 302 都是成功的 

每次探测都将获得以下三种结果之一:

成功:容器通过了诊断。
失败:容器未通过诊断。
未知:诊断失败,因此不会采取任何行动。

配置探针:

基于探针实现对Pod的状态检测

探针类型:

livenessProbe
存活探针,检测容器容器是否正在运行,如果存活探测失败,则kubelet会杀死容器,并且容器将受到其重启策略的
影响,如果容器不提供存活探针,则默认状态为 Success,livenessProbe用户控制是否重启pod。
readinessProbe
就绪探针,如果就绪探测失败,端点控制器将从与Pod匹配的所有Service的端点中删除该Pod的IP地址,初始延迟之
前的就绪状态默认为Failure,如果容器不提供就绪探针,则默认状态为 Success,readinessProbe用于控制pod
是否添加至service。

探针配置:

https://kubernetes.io/zh/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/

探针有很多配置字段,可以使用这些字段精确的控制存活和就绪检测的行为:

initialDelaySeconds: 120
#初始化延迟时间,告诉kubelet在执行第一次探测前应该等待多少秒,默认是0秒,最小值是0

periodSeconds: 60
#探测周期间隔时间,指定了kubelet应该每多少秒秒执行一次存活探测,默认是 10 秒。最小值是 1

timeoutSeconds: 5
#单次探测超时时间,探测的超时后等待多少秒,默认值是1秒,最小值是1。

successThreshold: 1
#从失败转为成功的重试次数,探测器在失败后,被视为成功的最小连续成功数,默认值是1,存活探测的这个值必须是1,最小值是 1。连续探测成功多少次,才把pod标记为成功

failureThreshold: 3
#从成功转为失败的重试次数,当Pod启动了并且探测到失败,Kubernetes的重试次数,存活探测情况下的放弃就意味着重新启动容器,就绪探测情况下的放弃Pod 会被打上未就绪的标签,默认值是3,最小值是1。

HTTP 探测器可以在 httpGet 上配置额外的字段:

host:
#连接使用的主机名,默认是Pod的 IP,也可以在HTTP头中设置 “Host” 来代替。

scheme: http
#用于设置连接主机的方式(HTTP 还是 HTTPS),默认是 HTTP。

path: /monitor/index.html
#访问 HTTP 服务的路径。

httpHeaders:
#请求中自定义的 HTTP 头,HTTP 头字段允许重复。

port: 80
#访问容器的端口号或者端口名,如果数字必须在 1 ~ 65535 之间。

HTTP探针示例:

root@master-1:/opt/k8s-data/yaml/linux39# vim nginx.yml
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels: #rs or deployment
      app: ng-deploy-80
    #matchExpressions:
    # - {key: app, operator: In, values: [ng-deploy-80,ng-rs-81]}
  template:
    metadata:
      labels:
        app: ng-deploy-80
    spec:
      containers:
      - name: ng-deploy-80
        image: nginx:1.17.5
        ports:
        - containerPort: 80
        #readinessProbe:  #探测异常则下线 通过service的时候没有被转发到后端pod
        livenessProbe:    #探测异常则重启 ,不关心在service后面有没有后端的pod 只是到service这一层面。不会摘除pod
          httpGet: 
            #path: /monitor/monitor.html #对nginx这个页面进行探测 如果存在则正常 不存在则会404 从而重启 当重启到3次之后则下线
            path: /index.html #正确页面 则探测正常
            port: 80
        initialDelaySeconds: 5
        periodSeconds: 3
        timeoutSeconds: 5
        successThreshold: 1
        failureThreshold: 3 #连续失败数次则下线
---
apiVersion: v1
kind: Service
metadata:
  name: ng-deploy-80
  spec:
    ports:
    - name: http
      port: 81
      targetPort: 80
      nodePort: 40012
      protocol: TCP
    type: NodePort
    selector:
      app: ng-deploy-80

生产中这2个探测结合使用,固定URL 不能发生变化 2个探测的URL保持一致 结合使用

periodSeconds 字段指定了 kubelet 每隔 3 秒执行一次存活探测。initialDelaySeconds 字段告诉 kubelet 在执行第一次探测前应该等待 3 秒。kubelet 会向容器内运行的服务(服务会监听 8080 端口)发送一个 HTTP GET 请求来执行探测。如果服务上 /healthz 路径下的处理程序返回成功码,则 kubelet 认为容器是健康存活的。如果处理程序返回失败码,则 kubelet 会杀死这个容器并且重新启动它。

任何大于或等于 200 并且小于 400 的返回码标示成功,其它返回码都标示失败。

TCP探针示例:

第三种类型的存活探测是使用 TCP 套接字。通过配置,kubelet 会尝试在指定端口和容器建立套接字链接。如果能建立链接,这个容器就被看作是健康的,如果不能则这个容器就被看作是有问题的。

kubelet 会在容器启动 5 秒后发送第一个就绪探测。这会尝试连接 goproxy 容器的 8080 端口。如果探测成功,这个 Pod 会被标记为就绪状态,kubelet 将继续每隔 10 秒运行一次检测。

除了就绪探测,这个配置包括了一个存活探测。kubelet 会在容器启动 15 秒后进行第一次存活探测。就像就绪探测一样,会尝试连接 goproxy 容器的 8080 端口。如果存活探测失败,这个容器会被重新启动。

# cat nginx-tcp.yaml
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels: #rs or deployment
      app: ng-deploy-80
    #matchExpressions:
    # - {key: app, operator: In, values: [ng-deploy-80,ng-rs-81]}
  template:
    metadata:
      labels:
        app: ng-deploy-80
    spec:
      containers:
      - name: ng-deploy-80
        image: nginx:1.17.5
        ports:
        - containerPort: 80
        livenessProbe:
        #readinessProbe:
          tcpSocket:
            port: 80
            #port: 8080
          initialDelaySeconds: 5
          periodSeconds: 3
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 3
---
apiVersion: v1
kind: Service
metadata:
  name: ng-deploy-80
spec:
  ports:
  - name: http
    port: 81
    targetPort: 80
    nodePort: 40012
    protocol: TCP
  type: NodePort
  selector:
    app: ng-deploy-80
ExecAction探针:

可以基于指定的命令对Pod进行特定的状态检查。

# docker pull redis #下载redis镜像

# cat redis.yaml
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-deployment
spec:
  replicas: 1
  selector:
    matchLabels: #rs or deployment
      app: redis-deploy-6379
      #matchExpressions:
      # - {key: app, operator: In, values: [redis-deploy-6379,ng-rs-81]}
    template:
      metadata:
        labels:
          app: redis-deploy-6379
      spec:
        containers:
        - name: redis-deploy-6379
          image: redis
          ports:
          - containerPort: 6379
          livenessProbe:
          #readinessProbe:
            exec:
              command: #执行命令
              #- /apps/redis/bin/redis-cli
              - /usr/local/bin/redis-cli  #执行的客户端命令
              - quit     #退出来   执行命令能进去也能退出来说明是正常的
            initialDelaySeconds: 5 #初始化延迟时间
            periodSeconds: 3
            timeoutSeconds: 5
            successThreshold: 1  #这个探测次数值必须为1 
            failureThreshold: 3
---
apiVersion: v1
kind: Service
metadata:
  name: redis-deploy-6379
spec:
  ports:
  - name: http
    port: 6379
    targetPort: 6379 #pod端口 必须是对应的服务端口redis是6379
    nodePort: 40016
    protocol: TCP
  type: NodePort
  selector:
    app: redis-deploy-6379

如果端口检测连续超过指定的三次都没有通过,则Pod状态会出现CrashLoopBackOff 的STATUS值

livenessProbe和readinessProbe的对比

配置参数一样
livenessProbe #连续探测失败会重启、重建pod,readinessProbe不会执行重启或者重建Pod操作
livenessProbe #连续检测指定次数失败后会将容器置于(Crash Loop BackOff)切不可用,readinessProbe不会

readinessProbe
连续探测失败会从service的endpointd中删除该Pod,livenessProbe不具备此功能,但是会将容器挂起livenessProbe
livenessProbe用户控制是否重启pod,readinessProbe用于控制pod是否添加至service

建议: 两个探针都配置

Pod重启策略:

k8s在Pod出现异常的时候会自动将Pod重启以恢复Pod中的服务。

restartPolicy: #注意缩进问题 6空格
Always:当容器异常时,k8s自动重启该容器,ReplicationController/Replicaset/Deployment。
OnFailure:当容器失败时(容器停止运行且退出码不为0),k8s自动重启该容器。
Never:不论容器运行状态如何都不会重启该容器,Job或CronJob。

示例:

          containers: #和pod平级 
          - name: magedu-tomcat-app1-container
            image: harbor.magedu.local/magedu/tomcat-app1:v1
            #command: ["/apps/tomcat/bin/run_tomcat.sh"]
            #imagePullPolicy: IfNotPresent
            imagePullPolicy: Always
            ports:
            - containerPort: 8080
              protocol: TCP
              name: http
            env:
            - name: "password"
              value: "123456"
            - name: "age"
              value: "18"
            resources:
              limits:
                cpu: 1
                memory: "512Mi"
              requests:
                cpu: 500m
                memory: "512Mi"
          restartPolicy: Always   #增加策略

HPA控制器简介及实现

https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#HPA参考

HPA全称Horizontal Pod Autoscaler控制器工作流程

手动调整pod数量:

root@master-1:~# kubectl get pod #当前pod数量
NAME                                 READY   STATUS    RESTARTS   AGE
net-test1-5fcc69db59-j78d7           1/1     Running   0          8h
net-test1-5fcc69db59-jz944           1/1     Running   1          5d3h
net-test1-5fcc69db59-wzlmg           1/1     Running   2          5d3h
nginx-deployment-8c449b55f-sdksb     1/1     Running   0          8h
tomcat-deployment-7cd955f48c-lthk2   1/1     Running   1          3d21h

#查看命令使用帮助
root@master-1:~# kubectl --help |grep scale #文本没有更新 这里deployment也可以
  scale          Set a new size for a Deployment, ReplicaSet or Replication Controller
  autoscale      Auto-scale a Deployment, ReplicaSet, or ReplicationController

#执行扩容/缩容
root@master-1:~# kubectl scale deployment/tomcat-deployment --replicas=3 -n default
deployment.apps/tomcat-deployment scaled

#验证手动扩容结果  增加了2个pod
root@master-1:~# kubectl get pod
NAME                                 READY   STATUS              RESTARTS   AGE
net-test1-5fcc69db59-j78d7           1/1     Running             0          8h
net-test1-5fcc69db59-jz944           1/1     Running             1          5d3h
net-test1-5fcc69db59-wzlmg           1/1     Running             2          5d3h
nginx-deployment-8c449b55f-sdksb     1/1     Running             0          8h
tomcat-deployment-7cd955f48c-b8k6j   1/1     Running             0          7s
tomcat-deployment-7cd955f48c-lthk2   1/1     Running             1          3d21h
tomcat-deployment-7cd955f48c-v5dch   0/1     ContainerCreating   0          8s
root@master-1:~# kubectl get pod
NAME                                 READY   STATUS    RESTARTS   AGE
net-test1-5fcc69db59-j78d7           1/1     Running   0          8h
net-test1-5fcc69db59-jz944           1/1     Running   1          5d3h
net-test1-5fcc69db59-wzlmg           1/1     Running   2          5d3h
nginx-deployment-8c449b55f-sdksb     1/1     Running   0          8h
tomcat-deployment-7cd955f48c-b8k6j   1/1     Running   0          11s
tomcat-deployment-7cd955f48c-lthk2   1/1     Running   1          3d21h
tomcat-deployment-7cd955f48c-v5dch   1/1     Running   0          12s

在这里插入图片描述

HPA自动伸缩pod数量:

Horizontal Pod Autoscaling,简称HPA,是Kubernetes中实现POD水平自动伸缩的功能。为什么要水平而不叫垂直, 那是因为自动扩展主要分为两种:

水平扩展(scale out),针对于实例数目的增减
垂直扩展(scal up),即单个实例可以使用的资源的增减, 比如增加cpu和增大内存
而HPA属于前者。它可以根据CPU使用率或应用自定义metrics自动扩展Pod数量(支持 replication controller、deployment 和 replica set)
架构介绍

获取metrics的两种方式:
Heapster: heapster提供metrics服务, 但是在v1(autoscaling/v1)版本中仅支持以CPU作为扩展度量指标, 而其他比如:内存, 网络流量, qps等目前处于beta阶段(autoscaling/v2beta1)
Cousom: 同样处于beta阶段(autoscaling/v2beta1), 但是涉及到自定义的REST API的开发, 复杂度会大一些, 并且当需要从自定义的监控中获取数据时,只能设置绝对值,无法设置使用率
kubectl autoscale 自动控制在k8s集群中运行的pod数量(水平自动伸缩),需要提前设置pod范围及触发条件。

k8s从1.1版本开始增加了名称为HPA(Horizontal Pod Autoscaler)的控制器,用于实现基于pod中资源
(CPU/Memory)利用率进行对pod的自动扩缩容功能的实现,早期的版本只能基于Heapster组件实现对CPU利用率
做为触发条件,但是在k8s 1.11版本开始使用Metrices Server完成数据采集,然后将采集到的数据通过
API(Aggregated API,汇总API),例如metrics.k8s.io、custom.metrics.k8s.io、external.metrics.k8s.io,然后
再把数据提供给HPA控制器进行查询,以实现基于某个资源利用率对pod进行扩缩容的目的。

控制管理器默认每隔15s(可以通过–horizontal-pod-autoscaler-sync-period修改)查询metrics的资源使用情况
支持以下三种metrics指标类型:
->预定义metrics(比如Pod的CPU)以利用率的方式计算
->自定义的Pod metrics,以原始值(raw value)的方式计算
->自定义的object metrics
支持两种metrics查询方式:
->Heapster
->自定义的REST API
支持多metrics

在这里插入图片描述
工作流程:

1.创建HPA资源,设定目标CPU使用率限额,以及最大、最小实例数, 一定要设置Pod的资源限制参数: request, 负责HPA不会工作。
2.控制管理器每隔30s(可以通过–horizontal-pod-autoscaler-sync-period修改)查询metrics的资源使用情况
3.然后与创建时设定的值和指标做对比(平均值之和/限额),求出目标调整的实例个数
4.目标调整的实例数不能超过1中设定的最大、最小实例数,如果没有超过,则扩容;超过,则扩容至最大的实例个数
重复2-4步

更多咨询,关注微信公众号

K8S学习–Kubeadm-5-资源管理核心概念

Kaivi

K8S学习–Kubeadm-1-组件简介

K8S学习–Kubeadm-2-安装部署

K8S学习–Kubeadm-3-Dashboard部署和升级

K8S学习–Kubeadm-4-测试运行Nginx+Tomcat

k8s的设计理念—分层架构

http://docs.kubernetes.org.cn/251.html#Kubernetes架构

Kubernetes设计理念和功能其实就是一个类似Linux的分层架构,如下图所示
在这里插入图片描述

核心层:Kubernetes最核心的功能,对外提供API构建高层的应用,对内提供插件式应用执行环境
应用层:部署(无状态应用(无集群关系)、有状态应用(数据库主从 Rredis集群)、批处理任务、集群应用等)和路由(服务发现、DNS解析等)。有状态应用一般是跑在物理机上面
管理层:系统度量(如基础设施、容器和网络的度量),自动化(如自动扩展、动态Provision等)以及策略管理(RBAC、Quota、PSP、NetworkPolicy等)
接口层:kubectl命令行工具、客户端SDK以及集群联邦
生态系统:在接口层之上的庞大容器集群管理调度的生态系统,可以划分为两个范畴
1.Kubernetes外部:日志、监控、配置管理、CI、CD、Workflow、FaaS、OTS应用、ChatOps等
2.Kubernetes内部:CRI、CNI、CVI、镜像仓库、Cloud Provider、集群自身的配置和管理等

k8s的设计理念—API设计原则

https://www.kubernetes.org.cn/kubernetes%e8%ae%be%e8%ae%a1%e7%90%86%e5%bf%b5
API设计原则

所有API应该是声明式的。
•API对象是彼此互补而且可组合的。
•高层API以操作意图为基础设计。
•低层API根据高层API的控制需要设计。
•尽量避免简单封装,不要有在外部API无法显式知道的内部隐藏的机制。
•API操作复杂度与对象数量成正比。
•API对象状态不能依赖于网络连接状态。
•尽量避免让操作机制依赖于全局状态,因为在分布式系统中要保证全局状态的同步是非常困难的。

Kubernetes设计理念与分布式系统

分析和理解Kubernetes的设计理念可以使我们更深入地了解Kubernetes系统,更好地利用它管理分布式部署的云原生应用,另一方面也可以让我们借鉴其在分布式系统设计方面的经验。

API设计原则

对于云计算系统,系统API实际上处于系统设计的统领地位,正如本文前面所说,K8s集群系统每支持一项新功能,引入一项新技术,一定会新引入对应的API对象,支持对该功能的管理操作,理解掌握的API,就好比抓住了K8s系统的牛鼻子。K8s系统API的设计有以下几条原则:

1.所有API应该是声明式的。
正如前文所说,声明式的操作,相对于命令式操作,对于重复操作的效果是稳定的,这对于容易出现数据丢失或重复的分布式环境来说是很重要的。另外,声明式操作更容易被用户使用,可以使系统向用户隐藏实现的细节,隐藏实现的细节的同时,也就保留了系统未来持续优化的可能性。此外,声明式的API,同时隐含了所有的API对象都是名词性质的,例如Service、Volume这些API都是名词,这些名词描述了用户所期望得到的一个目标分布式对象。

2.API对象是彼此互补而且可组合的。
这里面实际是鼓励API对象尽量实现面向对象设计时的要求,即“高内聚,松耦合”,对业务相关的概念有一个合适的分解,提高分解出来的对象的可重用性。事实上,K8s这种分布式系统管理平台,也是一种业务系统,只不过它的业务就是调度和管理容器服务。

3.高层API以操作意图为基础设计。
如何能够设计好API,跟如何能用面向对象的方法设计好应用系统有相通的地方,高层设计一定是从业务出发,而不是过早的从技术实现出发。因此,针对K8s的高层API设计,一定是以K8s的业务为基础出发,也就是以系统调度管理容器的操作意图为基础设计。

4.低层API根据高层API的控制需要设计。
设计实现低层API的目的,是为了被高层API使用,考虑减少冗余、提高重用性的目的,低层API的设计也要以需求为基础,要尽量抵抗受技术实现影响的诱惑。

5.尽量避免简单封装,不要有在外部API无法显式知道的内部隐藏的机制。
简单的封装,实际没有提供新的功能,反而增加了对所封装API的依赖性。内部隐藏的机制也是非常不利于系统维护的设计方式,例如PetSet和ReplicaSet,本来就是两种Pod集合,那么K8s就用不同API对象来定义它们,而不会说只用同一个ReplicaSet,内部通过特殊的算法再来区分这个ReplicaSet是有状态的还是无状态。

6.API操作复杂度与对象数量成正比。
这一条主要是从系统性能角度考虑,要保证整个系统随着系统规模的扩大,性能不会迅速变慢到无法使用,那么最低的限定就是API的操作复杂度不能超过O(N),N是对象的数量,否则系统就不具备水平伸缩性了。

7.API对象状态不能依赖于网络连接状态。由于众所周知,在分布式环境下,网络连接断开是经常发生的事情,因此要保证API对象状态能应对网络的不稳定,API对象的状态就不能依赖于网络连接状态。本机可以访问。但是跨主机还是得依赖网络。kubeadm默认没有暴露 二进制安装的会暴露8080 监听在127.0.0.1 只要连接到本机即可访问API

8.尽量避免让操作机制依赖于全局状态,因为在分布式系统中要保证全局状态的同步是非常困难的。

API:对象 —-是K8S集群之的管理操作单元
在这里插入图片描述

在这里插入图片描述

k8s命令使用

在这里插入图片描述

kubectl 概述

https://kubernetes.io/zh/docs/reference/kubectl/overview/
Kubectl 命令行接口

使用以下语法 kubectl 从终端窗口运行命令:

kubectl [command] [TYPE] [NAME] [flags]
其中 command、TYPE、NAME 和 flags 分别是:

command:指定要对一个或多个资源执行的操作,例如 create、get、describe、delete。

TYPE:指定资源类型。资源类型不区分大小写,可以指定单数、复数或缩写形式。例如,以下命令输出相同的结果:
  kubectl get pod 
  kubectl get pods 
  kubectl get po
root@master-1:~# kubectl get pod 
NAME                                 READY   STATUS    RESTARTS   AGE
net-test1-5fcc69db59-jz944           1/1     Running   1          2d16h
net-test1-5fcc69db59-wzlmg           1/1     Running   2          2d16h
net-test1-5fcc69db59-xthfd           1/1     Running   2          2d16h
nginx-deployment-574b87c764-9m59f    1/1     Running   1          34h
tomcat-deployment-7cd955f48c-lthk2   1/1     Running   1          34h
root@master-1:~# kubectl get pods
NAME                                 READY   STATUS    RESTARTS   AGE
net-test1-5fcc69db59-jz944           1/1     Running   1          2d16h
net-test1-5fcc69db59-wzlmg           1/1     Running   2          2d16h
net-test1-5fcc69db59-xthfd           1/1     Running   2          2d16h
nginx-deployment-574b87c764-9m59f    1/1     Running   1          34h
tomcat-deployment-7cd955f48c-lthk2   1/1     Running   1          34h
root@master-1:~# kubectl get po
NAME                                 READY   STATUS    RESTARTS   AGE
net-test1-5fcc69db59-jz944           1/1     Running   1          2d16h
net-test1-5fcc69db59-wzlmg           1/1     Running   2          2d16h
net-test1-5fcc69db59-xthfd           1/1     Running   2          2d16h
nginx-deployment-574b87c764-9m59f    1/1     Running   1          34h
tomcat-deployment-7cd955f48c-lthk2   1/1     Running   1          34h

操作命令和语法

在这里插入图片描述
在这里插入图片描述
https://kubernetes.io/zh/docs/reference/kubectl/overview/#参考链接

root@master-1:~# kubectl get service
NAME                    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes              ClusterIP   192.168.0.1      <none>        443/TCP        2d19h
magedu-nginx-service    NodePort    192.168.9.132    <none>        80:30004/TCP   37h
magedu-tomcat-service   NodePort    192.168.14.155   <none>        80:31849/TCP   35h

root@master-1:~# kubectl describe service magedu-tomcat-service #不加最后参数则查看全部的service
Name:                     magedu-tomcat-service
Namespace:                default
Labels:                   app=kaivi-tomcat-service-label
Annotations:              kubectl.kubernetes.io/last-applied-configuration:
                            {"apiVersion":"v1","kind":"Service","metadata":
                            {"annotations":{},"labels":{"app":"kaivi-tomcat-service-
                            label"},"name":"magedu-tomcat-servi...
Selector:                 app=tomcat
Type:                     NodePort
IP:                       192.168.14.155
Port:                     http  80/TCP
TargetPort:               8080/TCP
NodePort:                 http  31849/TCP
Endpoints:                10.10.4.7:8080
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>
root@master-1:~# kubectl explain pod  #查看某个对象的方法 层层嵌套 

root@master-1:~# kubectl explain pod.apiVersion

root@master-1:~# kubectl explain deployment.spec.selector

Crete和apply的区别:

apply支持对yaml文件的多次修改和动态生效,修改完成重新执行apply -f file.yml
crete 单次创建资源 后期如果修改yml文件下想生效 那么在删除之前的资源再重新创建 而且文件创建过程需要在删除之前修改 然后再重新创建 先删再改再创建

root@master-1:~# kubectl cluster-info 
Kubernetes master is running at https://172.20.10.248:6443
KubeDNS is running at https://172.20.10.248:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
root@master-1:~# kubectl cordon --help
Mark node as unschedulable.

Examples:
  # Mark node "foo" as unschedulable.
  kubectl cordon foo

Options:
      --dry-run=false: If true, only print the object that would be sent, without sending it.
  -l, --selector='': Selector (label query) to filter on

Usage:
  kubectl cordon NODE [options]

Use "kubectl options" for a list of global command-line options (applies to all commands).
root@master-1:~# kubectl cordon master-1 #不被调度
node/master-1 cordoned
root@master-1:~# kubectl get node 
NAME       STATUS                     ROLES    AGE     VERSION
master-1   Ready,SchedulingDisabled   master   2d19h   v1.17.4
master-2   Ready                      master   2d19h   v1.17.4
master-3   Ready                      master   2d18h   v1.17.4
node-1     Ready                      <none>   2d18h   v1.17.4
node-2     Ready                      <none>   2d18h   v1.17.4
node-3     Ready                      <none>   2d18h   v1.17.4
root@master-1:~# kubectl uncordon master-1 #取消不被调度
node/master-1 uncordoned
root@master-1:~# kubectl get node 
NAME       STATUS   ROLES    AGE     VERSION
master-1   Ready    master   2d19h   v1.17.4
master-2   Ready    master   2d19h   v1.17.4
master-3   Ready    master   2d18h   v1.17.4
node-1     Ready    <none>   2d18h   v1.17.4
node-2     Ready    <none>   2d18h   v1.17.4
node-3     Ready    <none>   2d18h   v1.17.4
root@master-1:~# kubectl drain --help #驱逐无状态服务 用于node紧急下线

Usage:
  kubectl drain NODE [options]
root@master-1:~# kubectl api-resources
NAME                              SHORTNAMES   APIGROUP                       NAMESPACED   KIND
bindings                                                                      true         Binding
componentstatuses                 cs                                          false        ComponentStatus
configmaps                        cm                                          true         ConfigMap
endpoints                         ep                                          true         Endpoints
events                            ev                                          true         Event
limitranges                       limits                                      true         LimitRange
namespaces                        ns                                          false        Namespace
nodes                             no                                          false        Node
persistentvolumeclaims            pvc                                         true         PersistentVolumeClaim
persistentvolumes                 pv                                          false        PersistentVolume
pods                              po                                          true         Pod
podtemplates                                                                  true         PodTemplate
replicationcontrollers            rc                                          true         ReplicationController
resourcequotas                    quota                                       true         ResourceQuota
secrets                                                                       true         Secret
serviceaccounts                   sa                                          true         ServiceAccount
services                          svc                                         true         Service
mutatingwebhookconfigurations                  admissionregistration.k8s.io   false        MutatingWebhookConfiguration
validatingwebhookconfigurations                admissionregistration.k8s.io   false        ValidatingWebhookConfiguration
customresourcedefinitions         crd,crds     apiextensions.k8s.io           false        CustomResourceDefinition
apiservices                                    apiregistration.k8s.io         false        APIService
controllerrevisions                            apps                           true         ControllerRevision
daemonsets                        ds           apps                           true         DaemonSet
deployments                       deploy       apps                           true         Deployment
replicasets                       rs           apps                           true         ReplicaSet
statefulsets                      sts          apps                           true         StatefulSet
tokenreviews                                   authentication.k8s.io          false        TokenReview
localsubjectaccessreviews                      authorization.k8s.io           true         LocalSubjectAccessReview
selfsubjectaccessreviews                       authorization.k8s.io           false        SelfSubjectAccessReview
selfsubjectrulesreviews                        authorization.k8s.io           false        SelfSubjectRulesReview
subjectaccessreviews                           authorization.k8s.io           false        SubjectAccessReview
horizontalpodautoscalers          hpa          autoscaling                    true         HorizontalPodAutoscaler
cronjobs                          cj           batch                          true         CronJob
jobs                                           batch                          true         Job
certificatesigningrequests        csr          certificates.k8s.io            false        CertificateSigningRequest
leases                                         coordination.k8s.io            true         Lease
endpointslices                                 discovery.k8s.io               true         EndpointSlice
events                            ev           events.k8s.io                  true         Event
ingresses                         ing          extensions                     true         Ingress
ingresses                         ing          networking.k8s.io              true         Ingress
networkpolicies                   netpol       networking.k8s.io              true         NetworkPolicy
runtimeclasses                                 node.k8s.io                    false        RuntimeClass
poddisruptionbudgets              pdb          policy                         true         PodDisruptionBudget
podsecuritypolicies               psp          policy                         false        PodSecurityPolicy
clusterrolebindings                            rbac.authorization.k8s.io      false        ClusterRoleBinding
clusterroles                                   rbac.authorization.k8s.io      false        ClusterRole
rolebindings                                   rbac.authorization.k8s.io      true         RoleBinding
roles                                          rbac.authorization.k8s.io      true         Role
priorityclasses                   pc           scheduling.k8s.io              false        PriorityClass
csidrivers                                     storage.k8s.io                 false        CSIDriver
csinodes                                       storage.k8s.io                 false        CSINode
storageclasses                    sc           storage.k8s.io                 false        StorageClass
volumeattachments                              storage.k8s.io                 false        VolumeAttachment

输出选项和语法

在这里插入图片描述

root@master-1:~# kubectl get pod
NAME                                 READY   STATUS    RESTARTS   AGE
net-test1-5fcc69db59-jz944           1/1     Running   1          2d16h
net-test1-5fcc69db59-wzlmg           1/1     Running   2          2d16h
net-test1-5fcc69db59-xthfd           1/1     Running   2          2d16h
nginx-deployment-574b87c764-9m59f    1/1     Running   1          35h
tomcat-deployment-7cd955f48c-lthk2   1/1     Running   1          35h
root@master-1:~# kubectl get pod -o wide
NAME                                 READY   STATUS    RESTARTS   AGE     IP          NODE     NOMINATED NODE   READINESS GATES
net-test1-5fcc69db59-jz944           1/1     Running   1          2d16h   10.10.3.3   node-1   <none>           <none>
net-test1-5fcc69db59-wzlmg           1/1     Running   2          2d16h   10.10.4.9   node-2   <none>           <none>
net-test1-5fcc69db59-xthfd           1/1     Running   2          2d16h   10.10.5.8   node-3   <none>           <none>
nginx-deployment-574b87c764-9m59f    1/1     Running   1          35h     10.10.5.9   node-3   <none>           <none>
tomcat-deployment-7cd955f48c-lthk2   1/1     Running   1          35h     10.10.4.7   node-2   <none>           <none>

K8S—-API

k8s的几个重要概念

对象用k8s是和什么打交道?
K8s声明式API
列举下面yum文件为例子:

apiVersion: apps/v1  #创建该对象所使用的KubernetesAPI 的版本
kind: Deployment     #kind-想要创建的对象的类型  
metadata:            #帮助识别对象唯一性的数据,包括一个name名称、可选的namespace
  name: nginx-deployment
  labels:
    app: nginx
spec:            #定义容器的状态 可以定义多个容器 名称不能冲突
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: harbor.linux39.com/baseimages/nginx:1.14.2
        ports:
        - containerPort: 80
---
kind: Service
apiVersion: v1
metadata:
  labels:
    app: kaivi-nginx-service-label
  name: magedu-nginx-service
  namespace: default
spec:
  type: NodePort
  ports:
  - name: http
    port: 80  #service端口  通过service端口的80转发到容器的(targetPort)pod端口80
    protocol: TCP
    targetPort: 80 #pod端口
    nodePort: 30004  #宿主机端口   通过宿主机端口30004访问到service端口的80
  selector:
    app: nginx

必需字段怎么声明?
1.apiVersion-创建该对象所使用的KubernetesAPI 的版本
2.kind-想要创建的对象的类型
3.metadata-帮助识别对象唯一性的数据,包括一个name名称、可选的namespace
4.spec 定义容器的状态 可以定义多个容器 名称不能冲突
5.status(Pod创建完成后k8s自动生成status状态)

root@master-1:~# kubectl get pod
NAME                                 READY   STATUS    RESTARTS   AGE
net-test1-5fcc69db59-jz944           1/1     Running   1          2d18h
net-test1-5fcc69db59-wzlmg           1/1     Running   2          2d18h
net-test1-5fcc69db59-xthfd           1/1     Running   2          2d18h
nginx-deployment-574b87c764-9m59f    1/1     Running   1          36h
tomcat-deployment-7cd955f48c-lthk2   1/1     Running   1          36h

root@master-1:~# kubectl describe pod tomcat-deployment-7cd955f48c-lthk2
Name:         tomcat-deployment-7cd955f48c-lthk2
Namespace:    default
Priority:     0
Node:         node-2/172.20.10.201
Start Time:   Mon, 30 Mar 2020 22:15:46 +0800
Labels:       app=tomcat
              pod-template-hash=7cd955f48c
Annotations:  <none>
Status:       Running   #状态是否runing
IP:           10.10.4.7
IPs:
  IP:           10.10.4.7
Controlled By:  ReplicaSet/tomcat-deployment-7cd955f48c
Containers:
  tomcat:
    Container ID:   docker://3ad024e3fa02efb0013ea776200ad70d684ee468b76b777d2c21a5017e65c660
    Image:          harbor.linux39.com/baseimages/tomcat:app
    Image ID:       docker-pullable://harbor.linux39.com/baseimages/tomcat@sha256:de80cfab99f015db3c47ea33cab64cc4e6
    5dd5d41a147fd6c9fc41fcfaeb69f1
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Running      #状态是否runing
      Started:      Wed, 01 Apr 2020 08:32:44 +0800
    Last State:     Terminated
      Reason:       Error
      Exit Code:    255
      Started:      Mon, 30 Mar 2020 22:19:37 +0800
      Finished:     Wed, 01 Apr 2020 08:26:14 +0800
    Ready:          True
    Restart Count:  1
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-9n88d (ro)
Conditions:
  Type              Status  #状态的查询
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  default-token-9n88d:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-9n88d
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:          <none>

yaml文件及语法基础:

需要提前创建好yaml文件,并创建好好pod运行所需要的namespace、yaml文件等资源

root@master-1:~# cd /opt/
root@master-1:/opt# mkdir file-yaml
root@master-1:/opt# cd file-yaml/
root@master-1:/opt/file-yaml# vim linux39-ns.yml
apiVersion: v1 #API版本
kind: Namespace #类型为namespac
metadata: #定义元数据
  name: linux39 #namespace名称

root@master-1:/opt/file-yaml# kubectl get ns
NAME                   STATUS   AGE
default                Active   2d20h
kube-node-lease        Active   2d20h
kube-public            Active   2d20h
kube-system            Active   2d20h
kubernetes-dashboard   Active   2d16h

root@master-1:/opt/file-yaml# kubectl apply -f linux39-ns.yml 
namespace/linux39 created

root@master-1:/opt/file-yaml# kubectl get ns
NAME                   STATUS   AGE
default                Active   2d20h
kube-node-lease        Active   2d20h
kube-public            Active   2d20h
kube-system            Active   2d20h
kubernetes-dashboard   Active   2d16h
linux39                Active   8s       #新创建的namespace

在这里插入图片描述
查看linux39的namespace已经存储到etcd 但是现在还没有任何数据

http://www.bejson.com/validators/yaml_editor/#在线yaml与json编辑器

大小写敏感
使用缩进表示层级关系
缩进时不允许使用Tal键,只允许使用空格
缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
使用”#” 表示注释,从这个字符一直到行尾,都会被解析器忽略
比json更适用于配置文件

yaml文件主要特性:

上下级关系
列表
键值对(也称为maps,即key:value 格式的键值对数据)

Nginx 业务yaml文件详解

# pwd
/opt/k8s-data/yaml/linux39
# mkdir nginx-tomcat-app1 tomcat-app2
# cd nginx/

# pwd
/opt/k8s-data/yaml/linux39/nginx

# cat nginx.yaml
kind: Deployment  #类型,是deployment控制器,kubectl explain Deployment
apiVersion: extensions/v1 #API版本,# kubectl explain Deployment.apiVersion 查看版本 需要保持一致
metadata: #pod的元数据信息,kubectl explain Deployment.metadata
  labels: #自定义pod的标签,# kubectl explain Deployment.metadata.labels 用于做筛选serivice接口
    app: linux39-nginx-deployment-label #标签名称为app值为linux39-nginx-deployment-label,后面会用到此标签
  name: linux39-nginx-deployment #pod的名称
  namespace: linux39 #pod的namespace,默认是defaule
spec: #定义deployment中容器的详细信息,kubectl explain Deployment.spec
  replicas: 1 #创建出的pod的副本数,即多少个pod,默认值为1 根据实际生产决定 kubectl explain Deployment.spec.replicas
  selector: #定义标签选择器 在新版中必须设置这个参数
    matchLabels: #定义匹配的标签,必须要设置
      app: linux39-nginx-selector #匹配的目标标签, 和Deployment.spec.template.app保持一致
  template: #定义模板,必须定义,模板是起到描述要创建的pod的作用
    metadata: #定义模板元数据
      labels: #定义模板label,Deployment.spec.template.metadata.labels
        app: linux39-nginx-selector #定义标签,等于Deployment.spec.selector.matchLabels 一定要保持一致
    spec: #定义pod信息 在当前的pod容器定义信息 
      containers:#定义pod中容器列表,可以多个至少一个,pod不能动态增减容器 只能是先删除再重新创建
      - name: linux39-nginx-container #容器名称  “-”表示数组 可以同时写多个 但是要平级
        image: harbor.magedu.net/linux39/nginx-web1:v1 #镜像地址
        #command: ["/apps/tomcat/bin/run_tomcat.sh"] #容器启动执行的命令或脚本
        #imagePullPolicy: IfNotPresent   #用已经有的镜像  没有再去拉取镜像 
        imagePullPolicy: Always #拉取镜像策略 重新拉取镜像 比较消耗带宽
        ports: #定义容器端口列表
        - containerPort: 80 #定义一个端口
          protocol: TCP #端口协议  只有TCP和UDP
          name: http #端口名称
        - containerPort: 443 #定义一个端口
          protocol: TCP #端口协议
          name: https #端口名称
         env: #配置环境变量  用于容器传递变量
         - name: "password" #变量名称。必须要用引号引起来
           value: "123456" #当前变量的值
         - name: "age" #另一个变量名称
           value: "18" #另一个变量的值
         resources: #对资源的请求设置和限制设置 
           limits: #资源限制设置,上限  硬限制
             cpu: 2 #cpu的限制,单位为core数,可以写0.5或者500m等CPU压缩值,1000毫核
             memory: 2Gi #内存限制,单位可以为Mib/Gib,将用于docker run --memory参数
           requests: #资源请求的设置  软限制
             cpu: 1 #cpu请求数,容器启动的初始可用数量,可以写0.5或者500m等CPU压缩值
             memory: 512Mi #内存请求大小,容器启动的初始可用数量,用于调度pod时候使用
---
kind: Service #类型为service   K8S内部的均衡调用请求
apiVersion: v1 #service API版本, service.apiVersion
metadata: #定义service元数据,service.metadata
  labels: #自定义标签,service.metadata.labels 用于K8S中的HPA动态扩容
    app: linux39-nginx #定义service标签的内容
  name: linux38-nginx-spec #定义service的名称,此名称会被DNS解析
  namespace: linux39 #该service隶属于的namespaces名称,即把service创建到哪个namespace里面
spec: #定义service的详细信息,service.spec
  type: NodePort #service的类型,定义服务的访问方式,默认为ClusterIP, service.spec.type
  ports: #定义访问端口, service.spec.ports
  - name: http #定义一个端口名称
    port: 80 #service 80端口
    protocol: TCP #协议类型
    targetPort: 80 #目标pod的端口
    nodePort: 30001 #node节点暴露的端口
  - name: https #SSL 端口
    port: 443 #service 443端口
    protocol: TCP #端口协议
    targetPort: 443 #目标pod端口
    nodePort: 30043 #node节点暴露的SSL端口
  selector: #service的标签选择器,定义要访问的目标pod
    app: linux39-nginx #将流量路到选择的pod上,须等于Deployment.spec.selector.matchLabels

spec和status的区别:
spec是期望状态
status是实际状态

Pod概述:
1.pod是k8s中的最小单元
2.一个pod中可以运行一个容器,也可以运行多个容器
3.运行多个容器的话,这些容器是一起被调度的
4.Pod的生命周期是短暂的,不会自愈,是用完就销毁的实体
5.一般我们是通过Controller来创建和管理pod的

Controller:控制器

https://kubernetes.io/zh/docs/concepts/workloads/controllers/replicationcontroller/#ReplicationController

https://kubernetes.io/zh/docs/concepts/overview/working-with-objects/labels/#标签选择器

实验实例

root@master-1:/opt/k8s-data/yaml/namespaces# pwd
/opt/k8s-data/yaml/namespaces
root@master-1:/opt/k8s-data/yaml/namespaces# ll
total 16
drwxr-xr-x 2 root root 4096 Apr  1 21:03 ./
drwxr-xr-x 6 root root 4096 Apr  1 20:58 ../
-rw-r--r-- 1 root root  121 Apr  1 21:00 linux39-ns.yml
-rw-r--r-- 1 root root  121 Apr  1 21:03 linux40-ns.yml
root@master-1:/opt/k8s-data/yaml/namespaces# cat linux*
apiVersion: v1 #API版本
kind: Namespace #类型为namespac
metadata: #定义元数据
  name: linux39 #namespace名称

apiVersion: v1 #API版本
kind: Namespace #类型为namespac
metadata: #定义元数据
  name: linux40 #namespace名称
root@master-1:/opt/k8s-data/yaml/namespaces# kubectl apply -f linux39-ns.yml  
root@master-1:/opt/k8s-data/yaml/namespaces# kubectl apply -f linux40-ns.yml
root@master-1:/opt/k8s-data/yaml/namespaces# kubectl get ns
NAME                   STATUS   AGE
default                Active   3d6h
kube-node-lease        Active   3d6h
kube-public            Active   3d6h
kube-system            Active   3d6h
kubernetes-dashboard   Active   3d2h
linux39                Active   6h
linux40                Active   12s

case1 :pod的控制器类型

root@master-1:/opt/k8s-data/yaml/linux39/case1# pwd
/opt/k8s-data/yaml/linux39/case1
root@master-1:/opt/k8s-data/yaml/linux39/case1# ll
total 20
drwxr-xr-x 2 root root 4096 Apr  1 21:14 ./
drwxr-xr-x 8 root root 4096 Apr  1 21:08 ../
-rw-r--r-- 1 root root  523 Apr  1 21:14 deployment.yml
-rw-r--r-- 1 root root  388 Mar 30 18:33 rc.yml
-rw-r--r-- 1 root root  459 Mar 30 18:33 rs.yml

deployment

root@master-1:/opt/k8s-data/yaml/linux39/case1# vim deployment.yml 
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: linux39
spec:
  replicas: 2
  selector:
    #app: ng-deploy-80 #rc
    #matchLabels: #rs or deployment
    #  app: ng-deploy-80

    matchExpressions:
      - {key: app, operator: In, values: [ng-deploy-80,ng-rs-81]}
  template:
    metadata:
      labels:
        app: ng-deploy-80
    spec:
      containers:
      - name: ng-deploy-80
        image: nginx
        ports:
        - containerPort: 80
        - 
root@master-1:/opt/k8s-data/yaml/linux39/case1# kubectl apply -f deployment.yml 
deployment.apps/nginx-deployment created

root@master-1:/opt/k8s-data/yaml/linux39/case1# kubectl get pod -n linux39
NAME                                READY   STATUS              RESTARTS   AGE
nginx-deployment-6997c89dfb-8gk5t   0/1     ContainerCreating   0          15s #处于创建状态 正在拉取镜像
nginx-deployment-6997c89dfb-dvg9b   0/1     ContainerCreating   0          15s

root@master-1:/opt/k8s-data/yaml/linux39/case1# kubectl get pod -n linux39
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-6997c89dfb-8gk5t   1/1     Running   0          2m22s  #已经正常运行
nginx-deployment-6997c89dfb-dvg9b   1/1     Running   0          2m22s

ReplicaSet

root@master-1:/opt/k8s-data/yaml/linux39/case1# vim rs.yml #ReplicaSet控制器
apiVersion: extensions/v1beta1
apiVersion: apps/v1
kind: ReplicaSet  #ReplicaSet控制器
metadata:
  name: frontend
  namespace: linux39
spec:
  replicas: 3
  selector:
    #matchLabels:
    #  app: ng-rs-80
    matchExpressions:
      - {key: app, operator: In, values: [ng-rs-80,ng-rs-81]} #正则匹配多个
  template:
    metadata:
      labels:
        app: ng-rs-80
    spec:
      containers:
      - name: ng-rs-80
        image: nginx
        ports:
        - containerPort: 80

先把之前的资源删除:

root@master-1:/opt/k8s-data/yaml/linux39/case1# kubectl delete -f deployment.yml 
deployment.apps "nginx-deployment" deleted
root@master-1:/opt/k8s-data/yaml/linux39/case1# kubectl get pod -n linux39
No resources found in linux39 namespace.

用ReplicaSet创建新的资源

root@master-1:/opt/k8s-data/yaml/linux39/case1# kubectl apply -f rs.yml 
replicaset.apps/frontend created
root@master-1:/opt/k8s-data/yaml/linux39/case1# kubectl get pod -n linux39
NAME             READY   STATUS              RESTARTS   AGE
frontend-749kw   0/1     ContainerCreating   0          6s
frontend-krjxb   0/1     ContainerCreating   0          6s
frontend-xgrcl   0/1     ContainerCreating   0          6s

root@master-1:/opt/k8s-data/yaml/linux39/case1# kubectl get pod -n linux39
NAME             READY   STATUS    RESTARTS   AGE
frontend-749kw   1/1     Running   0          110s
frontend-krjxb   1/1     Running   0          110s
frontend-xgrcl   1/1     Running   0          110s

rs需要先删除之后才能再次修改 除非加一些参数选项

root@master-1:/opt/k8s-data/yaml/linux39/case1# kubectl delete -f rs.yml 
replicaset.apps "frontend" deleted

root@master-1:/opt/k8s-data/yaml/linux39/case1# kubectl create --help

root@master-1:/opt/k8s-data/yaml/linux39/case1# kubectl create -f rs.yml --save-config=true #再次创建
replicaset.apps/frontend created
root@master-1:/opt/k8s-data/yaml/linux39/case1# vim rs.yml 
  replicas: 2 #把副本的数量改为2个
root@master-1:/opt/k8s-data/yaml/linux39/case1# kubectl apply -f rs.yml  #再次创建还是依赖apply
replicaset.apps/frontend configured
root@master-1:/opt/k8s-data/yaml/linux39/case1# kubectl get pod -n linux39
NAME             READY   STATUS    RESTARTS   AGE
frontend-4bhjv   1/1     Running   0          62s
frontend-r6trh   1/1     Running   0          62s

ReplicationController(快淘汰)

root@master-1:/opt/k8s-data/yaml/linux39/case1# vim rc.yml #ReplicationController控制器
apiVersion: v1
kind: ReplicationController
metadata:
  name: ng-rc
  namespace: linux39
spec:
  replicas: 2
  selector:
    app: ng-rc-80
    #app1: ng-rc-81

  template:
    metadata:
      labels:
        app: ng-rc-80
        #app1: ng-rc-81
    spec:
      containers:
      - name: ng-rc-80
        image: nginx
        ports:
        - containerPort: 80
root@master-1:/opt/k8s-data/yaml/linux39/case1# kubectl delete -f deployment.yml 
deployment.apps "nginx-deployment" deleted
root@master-1:/opt/k8s-data/yaml/linux39/case1# kubectl get pod -n linux39
No resources found in linux39 namespace.

用ReplicationController创建新的资源

root@master-1:/opt/k8s-data/yaml/linux39/case1# kubectl apply -f rc.yml 
replicationcontroller/ng-rc created
root@master-1:/opt/k8s-data/yaml/linux39/case1# kubectl get pod -n linux39
NAME          READY   STATUS    RESTARTS   AGE
ng-rc-4tp5p   1/1     Running   0          17s
ng-rc-j7tfx   1/1     Running   0          17s

Rc,Rs和Deployment
•ReplicationController:副本控制器(selector= 或者!=)(等于或者不等于)
•ReplicaSet:副本控制集,和副本控制器的区别是:对选择器的支持(selector还支持innotin)
•Deployment:比rs更高一级的控制器,除了有rs的功能之外,还有很多高级功能,,比如说最重要的:滚动升级、回滚等
https://kubernetes.io/zh/docs/concepts/workloads/controllers/deployment/

Service

•Why:pod重启之后ip就变了,pod之间直接访问会有问题
•What:解耦了服务和应用。简化服务的调用
•How:声明一个service对象

一般常用的有两种:
•k8s集群内的service:selector指定pod,自动创建Endpoints
•k8s集群外的service:手动创建Endpoints,指定外部服务的ip,端口和协议

kube-proxy和service的关系:
kube-proxy——————> k8s-apiserver
watch
kube-proxy监听着k8s-apiserver,一旦service资源发生变化(调k8s-api修改service信息),kube-proxy就会生成对应的负载调度的调整,这样就保证service的最新状态。

kube-proxy有三种调度模型:
•userspace:k8s 1.1之前 )(淘汰)
•iptables:k8s1.10之前 (还能用)
•ipvs:k8s 1.11之后,如果没有开启ipvs,则自动降级为iptables

Service和deployment实现一个nginx

root@master-1:/opt/k8s-data/yaml/linux39/case2# pwd
/opt/k8s-data/yaml/linux39/case2
root@master-1:/opt/k8s-data/yaml/linux39/case2# ll
total 3916
drwxr-xr-x 2 root root    4096 Apr  1 21:11 ./
drwxr-xr-x 8 root root    4096 Apr  1 21:08 ../
-rw-r--r-- 1 root root     542 Mar 30 18:33 1-deploy_node.yml
-rw-r--r-- 1 root root     214 Mar 30 18:33 2-svc_service.yml
-rw-r--r-- 1 root root     233 Mar 30 18:33 3-svc_NodePort.yml
-rw-r--r-- 1 root root 3983872 Mar 30 18:33 busybox-online.tar.gz
-rw-r--r-- 1 root root     277 Mar 30 18:33 busybox.yaml
root@master-1:/opt/k8s-data/yaml/linux39/case2# 
root@master-1:/opt/k8s-data/yaml/linux39/case2# vim 1-deploy_node.yml 
root@master-1:/opt/k8s-data/yaml/linux39/case2# vim 1-deploy_node.yml 
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: linux39
spec:
  replicas: 1
  selector:
    #matchLabels: #rs or deployment
    #  app: ng-deploy3-80
    matchExpressions:
      - {key: app, operator: In, values: [ng-deploy-80,ng-rs-81]}
  template:
    metadata:
      labels:
        app: ng-deploy-80
    spec:
      containers:
      - name: ng-deploy-80
        image: nginx:1.17.5
        ports:
        - containerPort: 80
      #nodeSelector:
      #  env: group1

root@master-1:/opt/k8s-data/yaml/linux39/case2# kubectl apply -f 1-deploy_node.yml 
deployment.apps/nginx-deployment created
root@master-1:/opt/k8s-data/yaml/linux39/case2# kubectl get pod -n linux39
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-85ff9fcf5b-b77fp   1/1     Running   0          105s

ClusterIP 内部访问

root@master-1:/opt/k8s-data/yaml/linux39/case2# pwd
/opt/k8s-data/yaml/linux39/case2
root@master-1:/opt/k8s-data/yaml/linux39/case2# vim 2-svc_service.yml 
apiVersion: v1
kind: Service
metadata:
  name: ng-deploy-80
  namespace: linux39
spec:
  ports:
  - name: http
    port: 80
    targetPort: 80
    protocol: TCP
  type: ClusterIP
  selector:
    app: ng-deploy-80

root@master-1:/opt/k8s-data/yaml/linux39/case2# kubectl apply -f 2-svc_service.yml 
service/ng-deploy-80 created
root@master-1:~# kubectl get svc -n linux39  #获取linux39的svc集群地址
NAME           TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
ng-deploy-80   ClusterIP   192.168.15.201   <none>        80/TCP    3m45s

进入到pod服务器

root@master-1:/opt/k8s-data/yaml/linux39/case2# kubectl get pod 
NAME                                 READY   STATUS    RESTARTS   AGE
net-test1-5fcc69db59-jz944           1/1     Running   1          3d6h
net-test1-5fcc69db59-wzlmg           1/1     Running   2          3d6h
net-test1-5fcc69db59-xthfd           1/1     Running   2          3d6h
nginx-deployment-574b87c764-9m59f    1/1     Running   1          2d
tomcat-deployment-7cd955f48c-lthk2   1/1     Running   1          2d

root@master-1:/opt/k8s-data/yaml/linux39/case2# kubectl exec -it net-test1-5fcc69db59-xthfd  sh
/ # root@master-1:/opt/k8s-data/yaml/linux39/case2# 
/ # apk add curl
fetch http://dl-cdn.alpinelinux.org/alpine/v3.11/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.11/community/x86_64/APKINDEX.tar.gz
(1/4) Installing ca-certificates (20191127-r1)
(2/4) Installing nghttp2-libs (1.40.0-r0)
(3/4) Installing libcurl (7.67.0-r0)
(4/4) Installing curl (7.67.0-r0)
Executing busybox-1.31.1-r9.trigger
Executing ca-certificates-20191127-r1.trigger
OK: 7 MiB in 18 packages
/ # 
/ # curl 192.168.15.201 #访问svc集权地址 看是否能够联通
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
。。。。。。
/ # 
/ # ping ng-deploy-80  #ping一下service名称 不通
ping: bad address 'ng-deploy-80'

busybox镜像创建:

root@master-1:/opt/k8s-data/yaml/linux39/case2# docker pull busybox

root@master-1:/opt/k8s-data/yaml/linux39/case2# docker images
busybox                        latest              83aa35aa1c79      3 weeks ago         1.22MB

root@master-1:/opt/k8s-data/yaml/linux39/case2# docker tag  83aa35aa1c79  harbor.linux39.com/baseimages/busybox 

root@master-1:/opt/k8s-data/yaml/linux39/case2# docker push harbor.linux39.com/baseimages/busybox 

在这里插入图片描述

root@master-1:/opt/k8s-data/yaml/linux39/case2# vim busybox.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: busybox
  namespace: linux39  #default namespace的DNS
spec:
  containers:
  - image: harbor.linux39.com/baseimages/busybox
    command:
      - sleep
      - "3600"
    imagePullPolicy: Always
    name: busybox
  restartPolicy: Always

root@master-1:/opt/k8s-data/yaml/linux39/case2# kubectl apply -f busybox.yaml 
pod/busybox created
root@master-1:/opt/k8s-data/yaml/linux39/case2# kubectl get pod -n linux39
NAME                                READY   STATUS    RESTARTS   AGE
busybox                             1/1     Running   0          35s
nginx-deployment-85ff9fcf5b-b77fp   1/1     Running   0          25m

测试在同一个namespace中能够ping通
这里进入到busybox的pod中进行测试:进行ping之前在

root@master-1:/opt/k8s-data/yaml/linux39/case2# kubectl exec -it busybox sh -n linux39
/ # 
/ # ping ng-deploy-80 #访问service名称 
PING ng-deploy-80 (192.168.15.201): 56 data bytes #虽然ping不通但是能解析DNS 也说明能够访问
^C                            
--- ng-deploy-80 ping statistics ---
26 packets transmitted, 0 packets received, 100% packet loss
/ # wget ng-deploy-80
Connecting to ng-deploy-80 (192.168.15.201:80)
saving to 'index.html'
index.html           100% |*********************************************************************|   612  0:00:00 ETA
'index.html' saved
/ # cat index.html 
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>

结论:在同一个namespace中 可以直接通过service的名称进行访问 在yaml文件中直接指定service-name即可
可以实现微服务对外不访问

service对外访问

root@master-1:/opt/k8s-data/yaml/linux39/case2# vim 3-svc_NodePort.yml 
apiVersion: v1
kind: Service
metadata:
  name: ng-deploy-80
  namespace: linux39
spec:
  ports:
  - name: http
    port: 81
    targetPort: 80  #pod中的服务端口 一定要写对
    nodePort: 30012 #宿主机暴露端口 
    protocol: TCP
  type: NodePort
  selector:
    app: ng-deploy-80
root@master-1:/opt/k8s-data/yaml/linux39/case2# kubectl apply -f 3-svc_NodePort.yml 
service/ng-deploy-80 configured

30012这个自定义端口在K8S集群中每一个宿主机都会监听的一个端口,只要有这个端口就能通过这个端口访问到service地址进而service端口转发到内部的pod节点

#ss -tnl 

在任何一个K8S集群节点都能访问
在这里插入图片描述

Volume

容器中的文件在磁盘上是临时存放的,这给容器中运行的特殊应用程序带来一些问题。 首先,当容器崩溃时,kubelet 将重新启动容器,容器中的文件将会丢失——因为容器会以干净的状态重建。 其次,当在一个 Pod 中同时运行多个容器时,常常需要在这些容器之间共享文件。 Kubernetes 抽象出 Volume 对象来解决这两个问题。

数据和镜像解耦,以及容器间的数据共享
k8s抽象出的一个对象,用来保存数据,做存储用
常用的几种卷:
emptyDir:本地临时卷
hostPath:本地卷
nfs等:共享卷
configmap: 配置文件

CASE3:emptyDir

https://kubernetes.io/zh/docs/concepts/storage/volumes/#emptydir # emptyDir

当Pod 被分配给节点时,首先创建emptyDir卷,并且只要该Pod 在该节点上运行,该卷就会存在。正如卷的名字所述,它最初是空的。Pod 中的容器可以读取和写入emptyDir卷中的相同文件,尽管该卷可以挂载到每个容器中的相同或不同路径上。当出于任何原因从节点中删除Pod 时,emptyDir中的数据将被永久删除。

Pod 示例

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: k8s.gcr.io/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir: {}
root@master-1:/opt/k8s-data/yaml/linux39/case3# pwd
/opt/k8s-data/yaml/linux39/case3

root@master-1:/opt/k8s-data/yaml/linux39/case3# vim deploy_empty.yml 
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: linux39
spec:
  replicas: 1
  selector:
    matchLabels: #rs or deployment
      app: ng-deploy-80
  template:
    metadata:
      labels:
        app: ng-deploy-80
    spec:
      containers:
      - name: ng-deploy-80
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - mountPath: /cache
          name: cache-volume
      volumes:
      - name: cache-volume
        emptyDir: {}
root@master-1:/opt/k8s-data/yaml/linux39/case3# kubectl apply -f deploy_empty.yml 
deployment.apps/nginx-deployment created

root@master-1:/opt/k8s-data/yaml/linux39/case3# kubectl get pod -n linux39
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-7cc86d98d5-8gbcb   1/1     Running   0          62s

root@master-1:/opt/k8s-data/yaml/linux39/case3# kubectl exec -it nginx-deployment-7cc86d98d5-8gbcb bash -n linux39
root@nginx-deployment-7cc86d98d5-8gbcb:/# cd /cache/
root@nginx-deployment-7cc86d98d5-8gbcb:/cache# echo 112233 > linux39.txt
root@nginx-deployment-7cc86d98d5-8gbcb:/cache# exit
exit
root@master-1:/opt/k8s-data/yaml/linux39/case3#
root@master-1:/opt/k8s-data/yaml/linux39/case3# kubectl get pod -n linux39 -o wide #查看创建的数据在哪一个节点 发现在node-3中
NAME                                READY   STATUS    RESTARTS   AGE   IP           NODE     NOMINATED NODE   READINESS GATES
nginx-deployment-7cc86d98d5-8gbcb   1/1     Running   0          11m   10.10.5.19   node-3   <none>           <none>

在node-3中查找数据的存储目录

root@Node-3:~# find / -name linux39.txt
/var/lib/kubelet/pods/014f1689-ca48-4f1b-b955-9381f9148dbf/volumes/kubernetes.io~empty-dir/cache-volume/linux39.txt
^C
root@Node-3:~# cat /var/lib/kubelet/pods/014f1689-ca48-4f1b-b955-9381f9148dbf/volumes/kubernetes.io~empty-dir/cache-volume/linux39.txt
112233

上面的路径是固定的。但是pod的编号ID(014f1689-ca48-4f1b-b955-9381f9148dbf)不是 这里可以用 * 进行匹配
emptyDir的数据在pod被删除的同时 数据也会被删除清空

CASE4:hostPath

https://kubernetes.io/zh/docs/concepts/storage/volumes/#hostpath#hostPath

hostPath 卷能将主机节点文件系统上的文件或目录挂载到您的 Pod 中。 虽然这不是大多数 Pod 需要的,但是它为一些应用程序提供了强大的逃生舱。

hostPath卷将主机节点的文件系统中的文件或目录挂载到集群中,pod删除的时候,卷不会被删除

#apiVersion: extensions/v1beta1
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment-2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ng-deploy-80
  template:
    metadata:
      labels:
        app: ng-deploy-80
    spec:
      containers:
      - name: ng-deploy-80
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - mountPath: /data/mysql
          name: data-volume  #和下面volumes的挂载名称要一致
      volumes:
      - name: data-volume #定义挂载的名称
        hostPath:   #指定使用什么类型 什么样子的卷 
          path: /data/mysql
root@master-1:/opt/k8s-data/yaml/linux39/case4# kubectl apply -f deploy_hostPath.yml 
deployment.apps/nginx-deployment-2 created

root@master-1:/opt/k8s-data/yaml/linux39/case4# kubectl get pod 
NAME                                  READY   STATUS    RESTARTS   AGE
net-test1-5fcc69db59-jz944            1/1     Running   1          4d6h
net-test1-5fcc69db59-wzlmg            1/1     Running   2          4d6h
net-test1-5fcc69db59-xthfd            1/1     Running   2          4d6h
nginx-deployment-2-7944748bc4-xpbln   1/1     Running   0          34s
nginx-deployment-574b87c764-9m59f     1/1     Running   1          3d
tomcat-deployment-7cd955f48c-lthk2    1/1     Running   1          3d
root@master-1:/opt/k8s-data/yaml/linux39/case4# kubectl get pod -o wide #查看在哪一个主机中 在node-3中
NAME                                  READY   STATUS    RESTARTS   AGE         IP           NODE     NOMINATED NODE   READINESS GATES
net-test1-5fcc69db59-jz944            1/1     Running   1          4d4h        10.10.3.3    node-1   <none>           <none>
net-test1-5fcc69db59-wzlmg            1/1     Running   2          4d4h        10.10.4.9    node-2   <none>           <none>
net-test1-5fcc69db59-xthfd            1/1     Running   2          4d4h        10.10.5.8    node-3   <none>           <none>
nginx-deployment-2-7944748bc4-xpbln   1/1     Running   0          <invalid>   10.10.5.20   node-3   <none>           <none>
nginx-deployment-574b87c764-9m59f     1/1     Running   1          2d22h       10.10.5.9    node-3   <none>           <none>
tomcat-deployment-7cd955f48c-lthk2    1/1     Running   1          2d22h       10.10.4.7    node-2   <none>           <none>

可以去node-3主机中查看是否自动创建了一个/data/mysql的目录

root@master-1:/opt/k8s-data/yaml/linux39/case4# kubectl exec -it nginx-deployment-2-66d68c95d9-46z6b bash
root@nginx-deployment-2-66d68c95d9-46z6b:/# cd /data/
root@nginx-deployment-2-66d68c95d9-46z6b:/data# mkdir logs
root@nginx-deployment-2-66d68c95d9-46z6b:/data# echo likai > logs/nginx.logs

root@Node-3中

root@Node-3:/data# cd mysql/
root@Node-3:/data/mysql# ll
total 12
drwxr-xr-x 3 root root 4096 Apr  2 23:10 ./
drwxr-xr-x 4 root root 4096 Apr  2 22:47 ../
drwxr-xr-x 2 root root 4096 Apr  2 23:11 logs/
root@Node-3:/data/mysql# cat logs/nginx.logs  #这份文件宿主机和pod容器就一份 同修改同删除
likai

验证:在pod被删除时候,之前的数据是否被删除

root@master-1:/opt/k8s-data/yaml/linux39/case4# kubectl delete -f deploy_hostPath.yml 
deployment.apps "nginx-deployment-2" deleted
root@Node-3:/data/mysql# cat logs/nginx.logs 
likai

hostPath卷将主机节点的文件系统中的文件或目录挂载到集群中,pod删除的时候,卷不会被删除

CASE5:nfs Volume

nfs:
nfs 卷能将 NFS (网络文件系统) 挂载到您的 Pod 中。 不像 emptyDir 那样会在删除 Pod 的同时也会被删除,nfs 卷的内容在删除 Pod 时会被保存,卷只是被卸载掉了。 这意味着 nfs 卷可以被预先填充数据,并且这些数据可以在 Pod 之间”传递”。

•nfs卷允许将现有的NFS(网络文件系统)共享挂载到容器中。不像emptyDir,当删除Pod 时,nfs卷的内容被保留,卷仅仅是被卸载。这意味着NFS 卷可以预填充数据,并且可以在pod 之间“切换”数据。NFS 可以被多个写入者同时挂载。

警告:
在您使用 NFS 卷之前,必须运行自己的 NFS 服务器并将目标 share 导出备用。

这里实验复用HA-service1的机器:172.20.10.22

root@HA-server1:~# apt install nfs-server -y

root@HA-server1:~# mkdir /data/k8sdata -p

root@HA-server1:~# vim /etc/exports 
/data/k8sdata *(rw,no_root_squash)

root@HA-server1:~# systemctl restart nfs-server.service 
root@HA-server1:~# systemctl enable nfs-server.service 

在node节点上面查看共享出来的挂载卷。如果看不到说明配置有问题 后面实验也挂不上

root@Node-3:~# apt install nfs-common -y
root@Node-3:~# showmount -e 172.20.10.22
Export list for 172.20.10.22:
/data/k8sdata *

在node节点的宿主机挂载:

root@Node-3:~# mount -t nfs 172.20.10.22:/data/k8sdata /mnt #共享文件夹挂载到/mnt目录中

实验:

root@master-1:/opt/k8s-data/yaml/linux39/case5# pwd
/opt/k8s-data/yaml/linux39/case5
root@master-1:/opt/k8s-data/yaml/linux39/case5# ll
total 16
drwxr-xr-x 2 root root 4096 Apr  2 23:54 ./
drwxr-xr-x 8 root root 4096 Apr  1 21:08 ../
-rw-r--r-- 1 root root  804 Mar 30 18:33 deploy_nfs2.yml
-rw-r--r-- 1 root root  978 Apr  2 23:54 deploy_nfs.yml

root@master-1:/opt/k8s-data/yaml/linux39/case5# vim deploy_nfs.yml
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ng-deploy-80
  template:
    metadata:
      labels:
        app: ng-deploy-80
    spec:
      containers:
      - name: ng-deploy-80
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - mountPath: /usr/share/nginx/html/mysite #把nfs的/data/k8sdata挂载到当前目录
          name: my-nfs-volume
      volumes:
      - name: my-nfs-volume
        nfs:
          server: 172.20.10.22 #nfs服务器地址
          path: /data/k8sdata

---
apiVersion: v1
kind: Service
metadata:
  name: ng-deploy-80
spec:
  ports:
  - name: http
    port: 81
    targetPort: 80
    nodePort: 30011 #对外暴露访问端口 
    protocol: TCP
  type: NodePort
  selector:
    app: ng-deploy-80
root@master-1:/opt/k8s-data/yaml/linux39/case5# kubectl apply -f deploy_nfs.yml 
deployment.apps/nginx-deployment-3 created
service/ng-deploy-80 created

root@master-1:/opt/k8s-data/yaml/linux39/case5# kubectl get pod
NAME                                  READY   STATUS    RESTARTS   AGE
net-test1-5fcc69db59-jz944            1/1     Running   1          4d7h
net-test1-5fcc69db59-wzlmg            1/1     Running   2          4d7h
net-test1-5fcc69db59-xthfd            1/1     Running   2          4d7h
nginx-deployment-3-587f55c665-jxjt2   1/1     Running   0          29s
nginx-deployment-574b87c764-9m59f     1/1     Running   1          3d1h
tomcat-deployment-7cd955f48c-lthk2    1/1     Running   1          3d1h

root@master-1:/opt/k8s-data/yaml/linux39/case5# kubectl exec -it nginx-deployment-3-587f55c665-jxjt2 bash
root@nginx-deployment-3-587f55c665-jxjt2:/# df -Th
Filesystem                 Type     Size  Used Avail Use% Mounted on
overlay                    overlay   92G  4.0G   83G   5% /
tmpfs                      tmpfs     64M     0   64M   0% /dev
tmpfs                      tmpfs    953M     0  953M   0% /sys/fs/cgroup
/dev/sda1                  ext4      92G  4.0G   83G   5% /etc/hosts
shm                        tmpfs     64M     0   64M   0% /dev/shm
tmpfs                      tmpfs    953M   12K  953M   1% /run/secrets/kubernetes.io/serviceaccount
172.20.10.22:/data/k8sdata nfs4      46G   52M   44G   1% /usr/share/nginx/html/mysite
tmpfs                      tmpfs    953M     0  953M   0% /proc/acpi
tmpfs                      tmpfs    953M     0  953M   0% /proc/scsi
tmpfs                      tmpfs    953M     0  953M   0% /sys/firmware

在这里插入图片描述

在这里插入图片描述
在共享数据中创建数据,看挂载node节点是否能够访问

root@HA-server1:/data/k8sdata# vim linux39.html
root@HA-server1:/data/k8sdata# cat linux39.html 
linux39 test page

在这里插入图片描述
新建一个pod 看一个存储是否能够被多个pod所挂载

root@master-1:/opt/k8s-data/yaml/linux39/case5# vim deploy_nfs2.yml 

#apiVersion: extensions/v1beta1
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment-site2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ng-deploy-82
  template:
    metadata:
      labels:
        app: ng-deploy-82
    spec:
      containers:
      - name: ng-deploy-82
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - mountPath: /usr/share/nginx/html/mysite
          name: my-nfs-volume
      volumes:
      - name: my-nfs-volume
        nfs:
          server: 172.20.10.22
          path: /data/k8sdata

---
apiVersion: v1
kind: Service
metadata:
  name: ng-deploy-82
spec:
  ports:
  - name: http
    port: 80
    targetPort: 80
    nodePort: 30032 #对外暴露访问端口
    protocol: TCP
  type: NodePort
  selector:
    app: ng-deploy-82

root@master-1:/opt/k8s-data/yaml/linux39/case5# kubectl apply -f deploy_nfs2.yml 
deployment.apps/nginx-deployment-site2 created
service/ng-deploy-81 created
root@master-1:/opt/k8s-data/yaml/linux39/case5# kubectl get pod 
NAME                                      READY   STATUS    RESTARTS   AGE
net-test1-5fcc69db59-jz944                1/1     Running   1          4d8h
net-test1-5fcc69db59-wzlmg                1/1     Running   2          4d8h
net-test1-5fcc69db59-xthfd                1/1     Running   2          4d8h
nginx-deployment-574b87c764-9m59f         1/1     Running   1          3d2h
nginx-deployment-site2-659498cf9c-8cth6   1/1     Running   0          11s
tomcat-deployment-7cd955f48c-lthk2        1/1     Running   1          3d2h

root@master-1:/opt/k8s-data/yaml/linux39/case5# kubectl exec -it nginx-deployment-site2-659498cf9c-8cth6 bash
root@nginx-deployment-site2-659498cf9c-8cth6:/# df -TH
Filesystem                 Type     Size  Used Avail Use% Mounted on
overlay                    overlay   98G  4.3G   89G   5% /
tmpfs                      tmpfs     68M     0   68M   0% /dev
tmpfs                      tmpfs    1.0G     0  1.0G   0% /sys/fs/cgroup
/dev/sda1                  ext4      98G  4.3G   89G   5% /etc/hosts
shm                        tmpfs     68M     0   68M   0% /dev/shm
172.20.10.22:/data/k8sdata nfs4      49G   55M   47G   1% /usr/share/nginx/html/mysite
tmpfs                      tmpfs    1.0G   13k  1.0G   1% /run/secrets/kubernetes.io/serviceaccount
tmpfs                      tmpfs    1.0G     0  1.0G   0% /proc/acpi
tmpfs                      tmpfs    1.0G     0  1.0G   0% /proc/scsi
tmpfs                      tmpfs    1.0G     0  1.0G   0% /sys/firmware

在这里插入图片描述
实现了,一个nfs能被多个pod同时挂载,从而数据共享

在一个pod里面同时挂载多个NFS服务,实现pod里面有多个数据源,类似服务的多个站点数据区分

root@HA-server1:/data/k8sdata# mkdir /data/linux39

root@HA-server1:/data/k8sdata# vim /etc/exports #共享多个nfs
/data/k8sdata *(rw,no_root_squash)

/data/linux39 *(rw,no_root_squash)

root@HA-server1:/data/k8sdata# systemctl restart nfs-server.service 

node节点上查看是否共享成功

root@Node-3:~# showmount -e 172.20.10.22
Export list for 172.20.10.22:
/data/linux39 *
/data/k8sdata *

#apiVersion: extensions/v1beta1
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ng-deploy-80
  template:
    metadata:
      labels:
        app: ng-deploy-80
    spec:
      containers:
      - name: ng-deploy-80
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - mountPath: /usr/share/nginx/html/mysite #对应/data/k8sdata目录挂载
          name: my-nfs-volume #区分挂载哪个nfs
        - mountPath: /data/nginx/html #对应 /data/linux39目录挂载
          name: linux39-nfs-volume  #区分挂载哪个nfs
      volumes:
      - name: my-nfs-volume
        nfs:
          server: 172.20.10.22
          path: /data/k8sdata
      - name: linux39-nfs-volume
        nfs:
          server: 172.20.10.22
          path: /data/linux39

---
apiVersion: v1
kind: Service
metadata:
  name: ng-deploy-80
spec:
  ports:
  - name: http
    port: 81
    targetPort: 80
    nodePort: 30016
    protocol: TCP

 root@master-1:/opt/k8s-data/yaml/linux39/case5# kubectl apply -f deploy_nfs.yml 
deployment.apps/nginx-deployment created
service/ng-deploy-80 created

oot@master-1:/opt/k8s-data/yaml/linux39/case5# kubectl exec -it nginx-deployment-79bf555474-tvgx5 bash
root@nginx-deployment-79bf555474-tvgx5:/# df -TH
Filesystem                 Type     Size  Used Avail Use% Mounted on
overlay                    overlay   98G  4.2G   89G   5% /
tmpfs                      tmpfs     68M     0   68M   0% /dev
tmpfs                      tmpfs    1.0G     0  1.0G   0% /sys/fs/cgroup
/dev/sda1                  ext4      98G  4.2G   89G   5% /etc/hosts
shm                        tmpfs     68M     0   68M   0% /dev/shm
172.20.10.22:/data/linux39 nfs4      49G   55M   47G   1% /data/nginx/html
172.20.10.22:/data/k8sdata nfs4      49G   55M   47G   1% /usr/share/nginx/html/mysite
tmpfs                      tmpfs    1.0G   13k  1.0G   1% /run/secrets/kubernetes.io/serviceaccount
tmpfs                      tmpfs    1.0G     0  1.0G   0% /proc/acpi
tmpfs                      tmpfs    1.0G     0  1.0G   0% /proc/scsi
tmpfs                      tmpfs    1.0G     0  1.0G   0% /sys/firmware

在这里插入图片描述
NFS服务挂载的时候,不仅仅给pod节点pod网段共享目录的权限,也要给宿主机网段权限,不然挂载报错:
授权范围得注意 而且不是用mount去挂载

在这里插入图片描述
或者:

root@HA-server1:/data/k8sdata# vim /etc/exports 
/data/k8sdata 10.10.0.0/16 172.20.10.0/24(rw,no_root_squash) #用空格隔开
/data/linux39 10.10.0.0/16 172.20.10.0/24(rw,no_root_squash)

CASE6: configmap

https://kubernetes.io/zh/docs/concepts/storage/volumes/#configmap # configmap

configmap资源提供了向 Pod 注入配置数据的方法。 ConfigMap 对象中存储的数据可以被 configMap 类型的卷引用,然后被应用到 Pod 中运行的容器化应用。

配置信息大部分放到镜像里面 如果同一些配置信息给多个pod复用 可以用configmap

root@master-1:/opt/k8s-data/yaml/linux39/case6# vim  deploy_configmap.yml 

apiVersion: v1
kind: ConfigMap     #类型是configmap
metadata:
  name: nginx-config #通过这个名称来调用
data:
 default: |               # default一个key的名称 下面为定义的服务内容
    server {
       listen       80;
       server_name  www.mysite.com; 
       index        index.html;

       location / {
           root /data/nginx/html;
           if (!-e $request_filename) {
               rewrite ^/(.*) /index.html last;
           }
       }
    }

---
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ng-deploy-80
  template:
    metadata:
      labels:
        app: ng-deploy-80
    spec:
      containers:
      - name: ng-deploy-80
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - mountPath: /data/nginx/html
          name: nginx-static-dir
        - name: nginx-config       #调用nginx-config 这个的类型是 configMap
          mountPath:  /etc/nginx/conf.d
      volumes:
      - name: nginx-static-dir
        hostPath:
          path: /data/nginx/linux39
      - name: nginx-config
        configMap:
          name: nginx-config
          items:
             - key: default  #key 调用最前面的default
               path: mysite.conf #挂载容器的路径 结合起来就是 /etc/nginx/conf.d/mysite.conf
---
apiVersion: v1
kind: Service
metadata:
  name: ng-deploy-80
spec:
  ports:
  - name: http
    port: 81
    targetPort: 80
    nodePort: 30019 #对外暴露访问端口
    protocol: TCP
  type: NodePort
  selector:
    app: ng-deploy-80                         
root@master-1:/opt/k8s-data/yaml/linux39/case6# kubectl apply -f deploy_configmap.yml 
configmap/nginx-config created
deployment.apps/nginx-deployment created
service/ng-deploy-80 created

root@master-1:/opt/k8s-data/yaml/linux39/case6# kubectl get pod 
NAME                                 READY   STATUS    RESTARTS   AGE
net-test1-5fcc69db59-jz944           1/1     Running   1          4d16h
net-test1-5fcc69db59-wzlmg           1/1     Running   2          4d16h
net-test1-5fcc69db59-xthfd           1/1     Running   2          4d16h
nginx-deployment-8c449b55f-c5pkn     1/1     Running   0          13s
tomcat-deployment-7cd955f48c-lthk2   1/1     Running   1          3d10h
root@master-1:/opt/k8s-data/yaml/linux39/case6# kubectl get service
NAME                    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes              ClusterIP   192.168.0.1      <none>        443/TCP        4d18h
magedu-nginx-service    NodePort    192.168.9.132    <none>        80:30004/TCP   3d12h
magedu-tomcat-service   NodePort    192.168.14.155   <none>        80:31849/TCP   3d10h
ng-deploy-80            NodePort    192.168.3.122    <none>        81:30019/TCP   24s
ng-deploy-81            NodePort    192.168.9.29     <none>        80:30015/TCP   8h

root@master-1:/opt/k8s-data/yaml/linux39/case6# kubectl exec -it nginx-deployment-8c449b55f-c5pkn bash
root@nginx-deployment-8c449b55f-c5pkn:/# cat /etc/nginx/conf.d/mysite.conf  #查看配置信息
server {
   listen       80;
   server_name  www.mysite.com;
   index        index.html;

   location / {
       root /data/nginx/html;
       if (!-e $request_filename) {
           rewrite ^/(.*) /index.html last;
       }
   }
}

在这里插入图片描述
在node3中创建首页文件,看是否能够调用configmap

root@Node-3:~# cd /data/nginx/linux39/
root@Node-3:/data/nginx/linux39# vim index.html
root@Node-3:/data/nginx/linux39# cat index.html
configMap test page
root@Node-3:/data/nginx/linux39# 

访问node3的网页
在这里插入图片描述

DaemonSet

https://kubernetes.io/zh/docs/concepts/workloads/controllers/daemonset/

DaemonSet 确保全部(或者某些)节点上运行一个 Pod 的副本。当有节点加入集群时, 也会为他们新增一个 Pod 。当有节点从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。

DaemonSet会在当前k8s集群中的所有node创建相同的node,主要用于在所有node执行相同的操作的场景
1.日志收集
2.Prometheus
3.flannel

root@master-1:/opt/k8s-data/yaml/linux39# vim Daemonset.yml

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd-elasticsearch
  namespace: kube-system
  labels:
    k8s-app: fluentd-logging
spec:
  selector:
    matchLabels:
      name: fluentd-elasticsearch
  template:
    metadata:
      labels:
        name: fluentd-elasticsearch
    spec:
      tolerations:
      # this toleration is to have the daemonset runnable on master nodes
      # remove it if your masters can't run pods
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
      containers:
      - name: fluentd-elasticsearch
        image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
        resources:
          limits:
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 200Mi
        volumeMounts:
        - name: varlog
          mountPath: /var/log
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
      terminationGracePeriodSeconds: 30
      volumes:
      - name: varlog
        hostPath:
          path: /var/log  #把/var/log挂载到pod里面
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers #把/var/lib/docker/containers挂载到pod里面

root@master-1:/opt/k8s-data/yaml/linux39# kubectl apply -f Daemonset.yml 
daemonset.apps/fluentd-elasticsearch created
root@master-1:/opt/k8s-data/yaml/linux39# kubectl get pod -n kube-system
NAME                               READY   STATUS              RESTARTS   AGE
coredns-7f9c544f75-dd7gc           1/1     Running             4          4d13h
coredns-7f9c544f75-z5pds           1/1     Running             0          4d13h
etcd-master-1                      1/1     Running             26         4d19h
etcd-master-2                      1/1     Running             24         4d18h
etcd-master-3                      1/1     Running             20         4d18h
fluentd-elasticsearch-26jsw        0/1     ContainerCreating   0          29s #正在创建
fluentd-elasticsearch-8b2bl        0/1     ContainerCreating   0          29s
fluentd-elasticsearch-gx6c4        0/1     ContainerCreating   0          29s
fluentd-elasticsearch-hb4hc        0/1     ContainerCreating   0          29s
fluentd-elasticsearch-hpjwd        0/1     ContainerCreating   0          29s
fluentd-elasticsearch-qttwk        0/1     ContainerCreating   0          29s

可以看到集群中所有的master和所有的node节点中都创建了相同的一个pod 可以用于相同资源的获取调用。

更多咨询,关注微信公众号

K8S学习–Kubeadm-4-测试运行Nginx+Tomcat

Kaivi

K8S学习–Kubeadm-1-组件简介

K8S学习–Kubeadm-2-安装部署

K8S学习–Kubeadm-3-Dashboard部署和升级

版本查看

https://kubernetes.io/zh/docs/concepts/workloads/controllers/deployment/
测试运行nginx 并最终可以将实现动静分离 选用1.17版本

环境配置

基于一个之前环境的集群配置

角色 主机名 IP地址
k8s-master1 master1 172.20.10.100
k8s-master2 master2 172.20.10.101
k8s-master3 master3 172.20.10.102
k8s-HA-1 HA-server1 172.20.10.22
k8s-HA-2 HA-server2 172.20.10.44
k8s- harbor Harbor 172.20.10.33
k8s- node1 Node-1 172.20.10.200
k8s- node2 Node-2 172.20.10.201
k8s- node3 Node-3 172.20.10.202
root@master-1:~# kubectl get node 
NAME       STATUS   ROLES    AGE   VERSION
master-1   Ready    master   29h   v1.17.4
master-2   Ready    master   29h   v1.17.4
master-3   Ready    master   28h   v1.17.4
node-1     Ready    <none>   28h   v1.17.4
node-2     Ready    <none>   28h   v1.17.4
node-3     Ready    <none>   28h   v1.17.4

先把对应的镜像下载拉下来,上传到自己搭建好的harbor上面

实验

root@master-1:~# docker pull nginx:1.14.2

root@master-1:~# docker tag nginx:1.14.2 harbor.linux39.com/baseimages/nginx:1.14.2
root@master-1:~# docker push harbor.linux39.com/baseimages/nginx:1.14.2
root@master-1:~# cd /usr/local/src/
root@master-1:/usr/local/src# mkdir kubedm-nginx
root@master-1:/usr/local/src# cd kubedm-nginx/

root@master-1:/usr/local/src/kubedm-nginx# vim nginx-1.14.2.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: harbor.linux39.com/baseimages/nginx:1.14.2 #自定义的镜像地址
        ports:
        - containerPort: 80

---
kind: Service
apiVersion: v1
metadata:
  labels:
    app: kaivi-nginx-service-label
  name: magedu-nginx-service
  namespace: default
spec:
  type: NodePort
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
    nodePort: 30004  #访问端口
  selector:
    app: nginx

创建pod:

root@master-1:/usr/local/src/kubedm-nginx# kubectl apply -f nginx-1.14.2.yml 
deployment.apps/nginx-deployment created
service/magedu-nginx-service created

查看是否nginx服务起来

root@master-1:/usr/local/src/kubadm-nginx# kubectl get pod
NAME                               READY   STATUS    RESTARTS   AGE
net-test1-5fcc69db59-jz944         1/1     Running   1          28h
net-test1-5fcc69db59-wzlmg         1/1     Running   1          28h
net-test1-5fcc69db59-xthfd         1/1     Running   1          28h
nginx-deployment-66fc88798-6pnv4   1/1     Running   0          49s

访问web界面
在这里插入图片描述
进入创建的三个不同pod里面访问,然后分别创建首页文件index.html,编辑可区别的内容即可
这里用第一个pod为示例

root@master-1:/usr/local/src/kubadm-nginx# kubectl exec -it nginx-deployment-66fc88798-6pnv4 bash
root@nginx-deployment-66fc88798-6pnv4:/# cd /usr/share/nginx/html
root@nginx-deployment-66fc88798-6pnv4:/usr/share/nginx/html# ls
50x.html  index.html
root@nginx-deployment-66fc88798-6pnv4:/usr/share/nginx/html# vim index.html 
bash: vim: command not found
root@nginx-deployment-66fc88798-6pnv4:/usr/share/nginx/html# echo "pod1 page test" > index.html 
root@nginx-deployment-66fc88798-6pnv4:/usr/share/nginx/html# exit

再次刷新web界面
在这里插入图片描述

在负载均衡HA中加一个监听地址监听

root@HA-server1:~# vim /etc/haproxy/haproxy.cfg #在最后增加一个新的监听
listen k8s-web-80
  bind 172.20.10.249:80
  mode tcp
  server master1 172.20.10.200:30004 check inter 3s fall 3 rise 5
  server master2 172.20.10.201:30004 check inter 3s fall 3 rise 5
  server master3 172.20.10.202:30005 check inter 3s fall 3 rise 5

需要生成一个172.20.10.249的VIP

root@HA-server1:~# vim /etc/keepalived/keepalived.conf 
vrrp_instance VI_1 {
    state MASTER
    interface eth0
    garp_master_delay 10
    smtp_alert
    virtual_router_id 56
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        172.20.10.248 dev eth0 label eth0:1
        172.20.10.249 dev eth0 label eth0:2  #新增一个VIP
    }
}

重启服务keepalived以及haproxy

root@HA-server1:~# systemctl restart keepalived
root@HA-server1:~# systemctl restart haproxy
root@HA-server1:~# ss -ntl
State         Recv-Q         Send-Q                  Local Address:Port                  Peer Address:Port         
LISTEN        0              2000                    172.20.10.248:6443                       0.0.0.0:*            
LISTEN        0              2000                    172.20.10.249:80                         0.0.0.0:*            
LISTEN        0              128                     127.0.0.53%lo:53                         0.0.0.0:*            
LISTEN        0              128                           0.0.0.0:22                         0.0.0.0:*            
LISTEN        0              128                         127.0.0.1:6010                       0.0.0.0:*            
LISTEN        0              128                              [::]:22                            [::]:*            
LISTEN        0              128                             [::1]:6010                          [::]:*  

用VIP访问也能正常的跳转
在这里插入图片描述
在window做一个域名解析

C:\Windows\System32\drivers\etc/hosts
172.20.10.249 www.linux39.com

在这里插入图片描述

TOMCAT部署:

root@master-1:~# docker run -it --rm -p 8080:8080 tomcat
。。。。。。
30-Mar-2020 13:27:18.528 INFO [main] org.apache.catalina.startup.Catalina.load Initialization processed in 4320 ms
30-Mar-2020 13:27:18.646 INFO [main] org.apache.catalina.core.StandardService.startInternal Starting service [Catalina]
30-Mar-2020 13:27:18.646 INFO [main] org.apache.catalina.core.StandardEngine.startInternal Starting Servlet Engine: Apache Tomcat/8.5.53
30-Mar-2020 13:27:19.128 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"]
30-Mar-2020 13:27:19.626 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 1097 ms
root@master-1:~# docker ps
CONTAINER ID        IMAGE                                                           COMMAND                  CREATED             STATUS              PORTS                    NAMES
b885fdda940f        tomcat                                                          "catalina.sh run"        2 minutes ago       Up About a minute   0.0.0.0:8080->8080/tcp   sweet_cray

root@master-1:~# docker exec -it b885fdda940f bash  #进到tomcat容器
root@b885fdda940f:/usr/local/tomcat# 
root@b885fdda940f:/usr/local/tomcat# cd webapps
root@b885fdda940f:/usr/local/tomcat/webapps# mkdir app
root@b885fdda940f:/usr/local/tomcat/webapps# echo "tomcat app" > app/index.html
root@b885fdda940f:/usr/local/tomcat/webapps#                                     

访问TOMCAT服务器地址的8080下的/app
在这里插入图片描述

创建一个Dockerfile

root@master-1:/usr/local/src/kubeadm-linux39/tomcat-dockerfile# pwd
/usr/local/src/kubeadm-linux39/tomcat-dockerfile
root@master-1:/usr/local/src/kubeadm-linux39/tomcat-dockerfile# vim Dockerfile
root@master-1:/usr/local/src/kubeadm-linux39/tomcat-dockerfile# cat Dockerfile
FROM tomcat

ADD ./app /usr/local/tomcat/webapps/app/

在本机创建一个访问页面:

root@master-1:/usr/local/src/kubeadm-linux39/tomcat-dockerfile# mkdir app
root@master-1:/usr/local/src/kubeadm-linux39/tomcat-dockerfile# vim app/index.html
root@master-1:/usr/local/src/kubeadm-linux39/tomcat-dockerfile# cat app/index.html
Tomcat app images page test for kaivi 

下载镜像 并且打到自定义的harbor中

root@master-1:/usr/local/src/kubeadm-linux39/tomcat-dockerfile# docker pull tomcat
root@master-1:/usr/local/src/kubeadm-linux39/tomcat-dockerfile# docker build -t harbor.linux39.com/baseimages/tomcat:app .
Sending build context to Docker daemon  3.584kB
Step 1/2 : FROM tomcat
 ---> a7fa4ac97be4
Step 2/2 : ADD ./app /usr/local/tomcat/webapps/app/
 ---> ab563ed5aebe
Successfully built ab563ed5aebe
Successfully tagged harbor.linux39.com/baseimages/tomcat:app

重新运行tomcat服务。用新的harbor镜像地址是否能访问:

root@master-1:/usr/local/src/kubeadm-linux39/tomcat-dockerfile# docker run -it --rm -p 8080:8080 harbor.linux39.com/baseimages/tomcat:app
。。。。。。
ina]
30-Mar-2020 13:53:01.280 INFO [main] org.apache.catalina.core.StandardEngine.startInternal Starting Servlet Engine: Apache Tomcat/8.5.53
30-Mar-2020 13:53:01.301 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [/usr/local/tomcat/webapps/app]
30-Mar-2020 13:53:01.517 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/usr/local/tomcat/webapps/app] has finished in [216] ms
30-Mar-2020 13:53:01.520 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"]
30-Mar-2020 13:53:01.534 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 269 ms

再一次访问tomcat服务器的web界面:
在这里插入图片描述
访问能够成功

root@master-1:/usr/local/src/kubeadm-linux39/tomcat-dockerfile# docker images
REPOSITORY                                                                    TAG                 IMAGE ID            CREATED             SIZE
harbor.linux39.com/baseimages/tomcat                                          app                 ab563ed5aebe        5 minutes ago       528MB

root@master-1:/usr/local/src/kubeadm-linux39/tomcat-dockerfile# docker push harbor.linux39.com/baseimages/tomcat:app  #后面的:app 是表示tag号

The push refers to repository [harbor.linux39.com/baseimages/tomcat]
f4a0078a4e57: Pushed 
690fbbe97481: Pushed 
d27e164cc159: Pushed 
3c1fd77de487: Pushed 
ac3e2c206c49: Pushed 
3663b7fed4c9: Pushed 
832f129ebea4: Pushed 
6670e930ed33: Pushed 
c7f27a4eb870: Pushed 
e70dfb4c3a48: Pushed 
1c76bd0dc325: Pushed 
app: digest: sha256:de80cfab99f015db3c47ea33cab64cc4e65dd5d41a147fd6c9fc41fcfaeb69f1 size: 2628

服务跑起来之后,把他迁移到pod中。创建yml文件:

root@master-1:~# cd /usr/local/src/kubeadm-linux39/
root@master-1:/usr/local/src/kubeadm-linux39# mkdir tomcat-yml
root@master-1:/usr/local/src/kubeadm-linux39# cd tomcat-yml
root@master-1:/usr/local/src/kubeadm-linux39/tomcat-yml# cp /usr/local/src/kubadm-nginx/nginx-1.14.2.yml ./nginx-tomcat.yml
root@master-1:/usr/local/src/kubeadm-linux39/tomcat-yml# ll
total 12
drwxr-xr-x 2 root root 4096 Mar 30 22:06 ./
drwxr-xr-x 5 root root 4096 Mar 30 22:00 ../
-rw-r--r-- 1 root root  654 Mar 30 22:06 nginx-tomcat.yml
root@master-1:/usr/local/src/kubeadm-linux39/tomcat-yml# vim nginx-tomcat.yml 
#这里把名称需要全部写成对应的tomcat  %s/nginx/tomcat/g
root@master-1:/usr/local/src/kubeadm-linux39/tomcat-yml# cat nginx-tomcat.yml 

apiVersion: apps/v1
kind: Deployment
metadata:
  name: tomcat-deployment
  labels:
    app: tomcat
spec:
  replicas: 1    #占用的副本数这里实验改为1个即可 太多会占用资源
  selector:
    matchLabels:
      app: tomcat
  template:
    metadata:
      labels:
        app: tomcat
    spec:
      containers:
      - name: tomcat
        image: harbor.linux39.com/baseimages/tomcat:app #镜像地址改修最后上传的tomcat镜像地址
        ports:
        - containerPort: 8080  #访问端口是tomcat的8080

---
kind: Service
apiVersion: v1
metadata:
  labels:
    app: kaivi-tomcat-service-label
  name: magedu-tomcat-service
  namespace: default
spec:
  type: NodePort
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 8080    #访问端口是tomcat的8080
    nodePort: 30005     # nodePort不能重复 之前的30004被nginx占用
  selector:
    app: tomcat

创建pod:

root@master-1:/usr/local/src/kubeadm-linux39/tomcat-yml# kubectl apply -f nginx-tomcat.yml 
deployment.apps/tomcat-deployment created
service/magedu-tomcat-service created
root@master-1:/usr/local/src/kubeadm-linux39/tomcat-yml# kubectl get pod
NAME                                 READY   STATUS    RESTARTS   AGE
net-test1-5fcc69db59-jz944           1/1     Running   1          29h
net-test1-5fcc69db59-wzlmg           1/1     Running   1          29h
net-test1-5fcc69db59-xthfd           1/1     Running   1          29h
nginx-deployment-66fc88798-6pnv4     1/1     Running   0          111m
tomcat-deployment-7cd955f48c-lthk2   1/1     Running   0          1m

访问任何一个node节点的30005
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
静态分离:
一般tomcat服务器不需要对外暴露。所以在yml文件中可以把nodePort: 30005给注释掉

root@master-1:/usr/local/src/kubeadm-linux39/tomcat-yml# pwd
/usr/local/src/kubeadm-linux39/tomcat-yml

root@master-1:/usr/local/src/kubeadm-linux39/tomcat-yml# vim nginx-tomcat.yml 
38   #nodePort: 30005

重新执行pod创建:

root@master-1:/usr/local/src/kubeadm-linux39/tomcat-yml# kubectl apply -f nginx-tomcat.yml 
deployment.apps/tomcat-deployment unchanged
service/magedu-tomcat-service configured

然后这里需要让nginx转发给tomcat服务器:
这里直接登入到dashboard上面进行操作也可以

root@nginx-deployment-574b87c764-9m59f:/etc/nginx/conf.d# pwd
/etc/nginx/conf.d
root@nginx-deployment-574b87c764-9m59f:/etc/nginx/conf.d# vim default.conf 

在这里插入图片描述

root@nginx-deployment-574b87c764-9m59f:/etc/nginx/conf.d# echo "pod for nginx" > /usr/share/nginx/html/index.html
root@nginx-deployment-574b87c764-9m59f:/etc/nginx/conf.d# cat /usr/share/nginx/html/index.html
pod for nginx

查看web的访问情况
在这里插入图片描述

在这里插入图片描述

更多咨询,关注微信公众号

K8S学习–Kubeadm-3-Dashboard部署和升级

Kaivi

K8S学习–Kubeadm-1-组件简介

K8S学习–Kubeadm-2-安装部署

部署 web 服务 dashboard

https://github.com/kubernetes/dashboard #web 服务 dashboard

兼容1.17
https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-rc6/aio/deploy/recommended.yaml

安装配置文件 但是下载url不可用 需要改为国内地址 而且需要修改一定的内容

拉入配置文件admin-user.yml 和 admin-user.yml

采用最简单的方式 让其直接能够给vmware访问

#vim dashboard-2.0.0-rc6.yml 
spec:
  type: NodePort
  ports:
    - port: 443
      targetPort: 8443
      nodePort: 30002
  selector:
    k8s-app: kubernetes-dashboard

 image: harbor.linux39.com/baseimages/dashboard:v2.0.0-rc6  #镜像地址修改

在这里插入图片描述

部署 dashboard 2.0.0 rc6

# kubectl apply f dashboard 2.0.0 rc6.yml f admin user.yml

获取登录 token

# kubectl get secret A | grep admin user
kubernetes dashboard admin user token lkwbr
kubernetes.io/service account toke n 3 3m15s
# kubectl describe secret admin-user-token-lkwbr n kubernetes dashboard

基于kubeconfig文件登入验证

root@master-1:~# cp /root/.kube/config /opt/kubeconfig 

root@master-1:~# vim /opt/kubeconfig #再最后添加获取到的token 注意格式

在这里插入图片描述
然后上传到宿主机即可

实验:

把镜像pull下来之后打到harbor中:

root@master-1:/usr/local/src# docker images 
REPOSITORY                                                                    TAG                 IMAGE ID            CREATED             SIZE
kubernetesui/dashboard                                                        v2.0.0-rc6          cdc71b5a8a0e        2 weeks ago         221MB
quay.io/coreos/flannel                                                        v0.12.0-amd64       4e9f801d2217        2 weeks ago         52.8MB
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-proxy                v1.17.2             cba2a99699bd        2 months ago        116MB
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-apiserver            v1.17.2             41ef50a5f06a        2 months ago        171MB
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-controller-manager   v1.17.2             da5fd66c4068        2 months ago        161MB
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-scheduler            v1.17.2             f52d4c527ef2        2 months ago        94.4MB
registry.cn-hangzhou.aliyuncs.com/google_containers/coredns                   1.6.5               70f311871ae1        4 months ago        41.6MB
registry.cn-hangzhou.aliyuncs.com/google_containers/etcd                      3.4.3-0             303ce5db0e90        5 months ago        288MB
registry.cn-hangzhou.aliyuncs.com/google_containers/pause                     3.1                 da86e6ba6ca1        2 years ago         742kB

在master和node节点中增加hosts域名解析给harbor地址

# vim /etc/hosts
172.20.10.33  harbor.linux39.com

在每一个需要上传下载镜像的master或者node都要配置下面的参数 node节点通常比较多的要上传下载镜像

# vim /lib/systemd/system/docker.service #在后面新增参数--insecure-registry harbor.linux39.com
14 ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock  --insecure-registry harbor.linux39.com

# systemctl daemon-reload
# systemctl restart docker
root@master-1:~# docker login harbor.linux39.com
Login Succeeded

root@master-1:~# docker tag cdc71b5a8a0e harbor.linux39.com/baseimages/dashboard:v2.0.0-rc6
root@master-1:~# 
root@master-1:~# docker push harbor.linux39.com/baseimages/dashboard:v2.0.0-rc6
The push refers to repository [harbor.linux39.com/baseimages/dashboard]
f6419c845e04: Pushed 
v2.0.0-rc6: digest: sha256:7d7273c38f37c62375bb8262609b746f646da822dc84ea11710eed7082482b12 size: 529

访问harbor网页:
新建了一个文件项目baseimages 然后push之后复制相应的URL

URL:
harbor.linux39.com/baseimages/dashboard:v2.0.0-rc6

在这里插入图片描述

root@master-1:/usr/local/src# vim dashboard-2.0.0-rc6.yml
 192  image: harbor.linux39.com/baseimages/dashboard:v2.0.0-rc6  #修改为harbor镜像地址
 276  image: harbor.linux39.com/baseimages/metrics-scraper:v1.0.3 

dashboard服务需要上面的镜像提前下好上传到harbor镜像上去
这2个文件在:
https://github.com/kubernetes/dashboard/releases

在这里插入图片描述
打开url
https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-rc6/aio/deploy/recommended.yaml

2个image后面的镜像下载 地址

kubernetesui/dashboard:v2.0.0-rc6
kubernetesui/metrics-scraper:v1.0.3

root@master-1:~# docker pull harbor.linux39.com/baseimages/dashboard:v2.0.0-rc6
root@master-1:~# docker pull kubernetesui/metrics-scraper:v1.0.3

root@master-1:~# docker tag docker.io/kubernetesui/metrics-scraper:v1.0.3 harbor.linux39.com/baseimages/metrics-scraper:v1.0.3
root@master-1:~# docker push harbor.linux39.com/baseimages/metrics-scraper
harbor.linux39.com/baseimages/metrics-scraper         harbor.linux39.com/baseimages/metrics-scraper:v1.0.3
root@master-1:~# docker push harbor.linux39.com/baseimages/metrics-scraper:v1.0.3 
The push refers to repository [harbor.linux39.com/baseimages/metrics-scraper]
4e247d9378a1: Pushed 
0aec45b843c5: Pushed 
3ebaca24781b: Pushed 
v1.0.3: digest: sha256:e24a74b3b1cdc84d6285d507a12eb06907fd8c457b3e8ae9baa9418eca43efc4 size: 946

执行创建

root@master-1:/usr/local/src# ll
total 20
drwxr-xr-x  2 root root 4096 Mar 29 18:28 ./
drwxr-xr-x 10 root root 4096 Dec 28 05:33 ../
-rw-r--r--  1 root root  374 Mar 28 10:54 admin-user.yml
-rw-r--r--  1 root root 7641 Mar 29 18:28 dashboard-2.0.0-rc6.yml
root@master-1:/usr/local/src# kubectl apply -f dashboard-2.0.0-rc6.yml 
namespace/kubernetes-dashboard created
serviceaccount/kubernetes-dashboard created
service/kubernetes-dashboard created
secret/kubernetes-dashboard-certs created
secret/kubernetes-dashboard-csrf created
secret/kubernetes-dashboard-key-holder created
configmap/kubernetes-dashboard-settings created
role.rbac.authorization.k8s.io/kubernetes-dashboard created
clusterrole.rbac.authorization.k8s.io/kubernetes-dashboard created
rolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created
clusterrolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created
deployment.apps/kubernetes-dashboard created
service/dashboard-metrics-scraper created
deployment.apps/dashboard-metrics-scraper created
root@master-1:/usr/local/src# kubectl apply -f admin-user.yml 
serviceaccount/admin-user created
clusterrolebinding.rbac.authorization.k8s.io/admin-user created
root@master-1:/usr/local/src# 

查看服务是否起来 (最后2行)

root@master-1:/usr/local/src# kubectl get pod -A
NAMESPACE              NAME                                         READY   STATUS    RESTARTS   AGE
default                net-test1-5fcc69db59-jz944                   1/1     Running   1          116m
default                net-test1-5fcc69db59-wzlmg                   1/1     Running   1          116m
default                net-test1-5fcc69db59-xthfd                   1/1     Running   1          116m
kube-system            coredns-7f9c544f75-bml7d                     1/1     Running   1          4h15m
kube-system            coredns-7f9c544f75-jwhtr                     1/1     Running   2          4h15m
kube-system            etcd-master-1                                1/1     Running   2          4h15m
kube-system            etcd-master-2                                1/1     Running   1          3h33m
kube-system            etcd-master-3                                1/1     Running   1          3h17m
kube-system            kube-apiserver-master-1                      1/1     Running   4          4h15m
kube-system            kube-apiserver-master-2                      1/1     Running   2          3h33m
kube-system            kube-apiserver-master-3                      1/1     Running   2          3h17m
kube-system            kube-controller-manager-master-1             1/1     Running   3          4h15m
kube-system            kube-controller-manager-master-2             1/1     Running   3          3h33m
kube-system            kube-controller-manager-master-3             1/1     Running   0          3h17m
kube-system            kube-flannel-ds-amd64-4dc22                  1/1     Running   1          95m
kube-system            kube-flannel-ds-amd64-6nvgm                  1/1     Running   1          95m
kube-system            kube-flannel-ds-amd64-9pxvg                  1/1     Running   1          95m
kube-system            kube-flannel-ds-amd64-fxtv6                  1/1     Running   0          95m
kube-system            kube-flannel-ds-amd64-hmd27                  1/1     Running   0          95m
kube-system            kube-flannel-ds-amd64-njpcd                  1/1     Running   2          95m
kube-system            kube-proxy-5prrc                             1/1     Running   0          3h18m
kube-system            kube-proxy-cfbv5                             1/1     Running   2          163m
kube-system            kube-proxy-cjghs                             1/1     Running   1          4h15m
kube-system            kube-proxy-dmknx                             1/1     Running   2          3h5m
kube-system            kube-proxy-lhxz4                             1/1     Running   1          3h3m
kube-system            kube-proxy-wxgf5                             1/1     Running   0          3h33m
kube-system            kube-scheduler-master-1                      1/1     Running   3          4h15m
kube-system            kube-scheduler-master-2                      1/1     Running   3          3h33m
kube-system            kube-scheduler-master-3                      1/1     Running   0          3h17m
kubernetes-dashboard   dashboard-metrics-scraper-5bc5bdcbc5-hbhvm   1/1     Running   0          53s
kubernetes-dashboard   kubernetes-dashboard-d498886d6-7qqnc         1/1     Running   0          53s

查看service的端口:可以看到最后一行显示30002端口

root@master-1:~# kubectl get service -A 
NAMESPACE              NAME                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                  AGE
default                kubernetes                  ClusterIP   192.168.0.1      <none>        443/TCP                  4h17m
kube-system            kube-dns                    ClusterIP   192.168.0.10     <none>        53/UDP,53/TCP,9153/TCP   4h17m
kubernetes-dashboard   dashboard-metrics-scraper   ClusterIP   192.168.13.82    <none>        8000/TCP                 2m29s
kubernetes-dashboard   kubernetes-dashboard        NodePort    192.168.12.204   <none>        443:30002/TCP            2m32s

访问dashboard页面:访问任何一个node节点端口都可:
由于没有做跳转 所以要用 https 访问
在这里插入图片描述

获取登录 token

root@master-1:~#  kubectl get secret -A | grep admin-user
kubernetes-dashboard   admin-user-token-4hl98                           kubernetes.io/service-account-token   3      16m

root@master-1:~#  kubectl get secret -A | grep admin-user
kubernetes-dashboard   admin-user-token-4hl98                           kubernetes.io/service-account-token   3      16m
root@master-1:~# kubectl describe secret  admin-user-token-4hl98
Error from server (NotFound): secrets "admin-user-token-4hl98" not found  #要指定在哪里寻找
root@master-1:~# kubectl describe secret  admin-user-token-4hl98 -n kubernetes-dashboard
Name:         admin-user-token-4hl98
Namespace:    kubernetes-dashboard
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: admin-user
              kubernetes.io/service-account.uid: cfbe8a23-183e-4718-ba77-2ccb7b734619

Type:  kubernetes.io/service-account-token

Data
====
token:      eyJhbGciOiJSUzI1NiIsImtpZCI6ImRrMDFORkYtZlBUdEpwSDZBbTNuc1BvdWxTWFdReU5ySmpTMTk5RVF5NWsifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi11c2VyLXRva2VuLTRobDk4Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImFkbWluLXVzZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJjZmJlOGEyMy0xODNlLTQ3MTgtYmE3Ny0yY2NiN2I3MzQ2MTkiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZXJuZXRlcy1kYXNoYm9hcmQ6YWRtaW4tdXNlciJ9.IEdJFARZoPA0nbS5J9Sw3nQ-CE2Hfe4QhgXyadcxv5ezKpM6cxmgKq5TjEYzIe1w4UNGXcmGlP_IlJvNlhJtTSzgVapFD0H_zZWOfl10lBWQA0ajZhrIAqAg3z6ME1BBwW6CZxyI23I0RJcQ5ciraVEUGV1CbXvzeaAtvgwZHpX3eiFwQ3vQj91NiX_ogLmuFo7ueHO3swP5Nz23sbGpOuKAed5fMe7jyBaW_Jms5_IcrBBbyUWvuObAXZytM355ttYIITMkTJrKplMqIYzXMbNTo8OgqY89qy1olpbfnElLD5P4yIuIFaQanzk43wmA9wNJeuxvda2J2BbG_DNbiQ
ca.crt:     1025 bytes
namespace:  20 bytes

验证 NodePort

root@master-1:~# kubectl get svc -A
NAMESPACE              NAME                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                  AGE
default                kubernetes                  ClusterIP   192.168.0.1      <none>        443/TCP                  4h37m
kube-system            kube-dns                    ClusterIP   192.168.0.10     <none>        53/UDP,53/TCP,9153/TCP   4h37m
kubernetes-dashboard   dashboard-metrics-scraper   ClusterIP   192.168.13.82    <none>        8000/TCP                 22m
kubernetes-dashboard   kubernetes-dashboard        NodePort    192.168.12.204   <none>        443:30002/TCP            22m

复制上面的token 然后再web界面上用token认证的方式登入即可
在这里插入图片描述

k8s 集群升级

升级时间选择在凌晨。适合kubeadm和ansible的方式升级
升级k8s 集群必须 先 升级 kubeadm 版本到目的 k8s 版本也就是说 kubeadm 是k8s升级的准升证 。

升级 k8s master服务

在k8s 的所有 master 进行升级 将管理端服务 kube-controller-manager 、 kube-apiserver 、kube-scheduler 、 kube-proxy

验证当 k8s 前版本:

root@master-1:~# kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"17", GitVersion:"v1.17.2", GitCommit:"59603c6e503c87169aea6106f57b9f242f64df89", GitTreeState:"clean", BuildDate:"2020-01-18T23:27:49Z", GoVersion:"go1.13.5", Compiler:"gc", Platform:"linux/amd64"}

各master安装指定新版本kubeadm

root@master-1:~# apt-cache madison kubeadm

root@master-1:~# apt install kubeadm=1.17.4 00

root@master-1:~# kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"7", GitVersion:"v1.7.4", GitCommit:"793658f2d7ca7f064d2bdf606519f9fe1229c381", GitTreeState:"clean", BuildDate:"2017-08-17T08:30:51Z", GoVersion:"go1.8.3", Compiler:"gc", Platform:"linux/amd64"}

kubeadm 升级命令使用帮助

root@master-1:~# kubeadm  upgrade --help
Upgrade your cluster smoothly to a newer version with this command

Usage:
  kubeadm upgrade [flags]
  kubeadm upgrade [command]

Available Commands:
  apply       Upgrade your Kubernetes cluster to the specified version
  diff        Show what differences would be applied to existing static pod manifests. See also: kubeadm upgrade apply --dry-run
  node        Upgrade commands for a node in the cluster
  plan        Check which versions are available to upgrade to and validate whether your current cluster is upgradeable. To skip the internet check, pass in the optional [version] parameter

Flags:
  -h, --help   help for upgrade

Global Flags:
      --add-dir-header           If true, adds the file directory to the header
      --log-file string          If non-empty, use this log file
      --log-file-max-size uint   Defines the maximum size a log file can grow to. Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800)
      --rootfs string            [EXPERIMENTAL] The path to the 'real' host root filesystem.
      --skip-headers             If true, avoid header prefixes in the log messages
      --skip-log-headers         If true, avoid headers when opening log files
  -v, --v Level                  number for the log level verbosity

Use "kubeadm upgrade [command] --help" for more information about a command.

升级计划:

kubeadm upgrade plan #查看升级计划

root@master-1:~# kubeadm  upgrade plan
[upgrade/config] Making sure the configuration is correct:
[upgrade/config] Reading configuration from the cluster...
[upgrade/config] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml'
[preflight] Running pre-flight checks.
[upgrade] Making sure the cluster is healthy:
[upgrade] Fetching available versions to upgrade to
[upgrade/versions] Cluster version: v1.17.2
[upgrade/versions] kubeadm version: v1.17.4
W0329 20:37:33.266420  121178 version.go:101] could not fetch a Kubernetes version from the internet: unable to get URL "https://dl.k8s.io/release/stable.txt": Get https://dl.k8s.io/release/stable.txt: net/http: request canceled (Client.Timeout exceeded while awaiting headers)
W0329 20:37:33.266466  121178 version.go:102] falling back to the local client version: v1.17.4
[upgrade/versions] Latest stable version: v1.17.4
[upgrade/versions] Latest version in the v1.17 series: v1.17.4

Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
COMPONENT   CURRENT       AVAILABLE
Kubelet     6 x v1.17.2   v1.17.4

Upgrade to the latest version in the v1.17 series:

COMPONENT            CURRENT   AVAILABLE
API Server           v1.17.2   v1.17.4
Controller Manager   v1.17.2   v1.17.4
Scheduler            v1.17.2   v1.17.4
Kube Proxy           v1.17.2   v1.17.4
CoreDNS              1.6.5     1.6.5
Etcd                 3.4.3     3.4.3-0

You can now apply the upgrade by executing the following command:

    kubeadm upgrade apply v1.17.4

_____________________________________________________________________

开始升级

apt autoremove kubeadm=1.7.4-00 #删除版本命令
root@master-1:~# apt install kubeadm=1.17.4-00
root@master-2:~# apt install kubeadm=1.17.4-00
root@master-3:~# apt install kubeadm=1.17.4-00

root@master-1:~# kubeadm upgrade apply v1.17.4
root@master-2:~# kubeadm upgrade apply v1.17.4
root@master-3:~# kubeadm upgrade apply v1.17.4  #这里升级一个一个的升级 最好不要一起升级 可能会影响ks集群

在这里插入图片描述

验证镜像

在这里插入图片描述

升级 k8s node服务

升级客户端服务kubectl kubelet

root@master-1:~# apt install kubelet=1.17.4-00 kubectl=1.17.4-00
root@master-2:~# apt install kubelet=1.17.4-00 kubectl=1.17.4-00
root@master-3:~# apt install kubelet=1.17.4-00 kubectl=1.17.4-00
root@master-1:~# kubectl get node
NAME       STATUS   ROLES    AGE     VERSION
master-1   Ready    master   7h26m   v1.17.4
master-2   Ready    master   6h43m   v1.17.4
master-3   Ready    master   6h28m   v1.17.4
node-1     Ready    <none>   6h15m   v1.17.2
node-2     Ready    <none>   6h14m   v1.17.2
node-3     Ready    <none>   5h53m   v1.17.2

这里只要VERSION显示v1.17.4就说明kubelet已经升级了为v1.17.4

验证当前 node 版本信息

node 节点还是1.17.2的旧版本

升各 node 节点配置文件

这个需要在各个node节点升级

root@Node-1:~# kubeadm upgrade node --kubelet-version v1.17.4
root@Node-2:~# kubeadm upgrade node --kubelet-version v1.17.4
root@Node-3:~# kubeadm upgrade node --kubelet-version v1.17.4

在这里插入图片描述

各Node节点升级 kubelet 二进制包

root@Node-1:~# apt install kubeadm=1.17.4-00 kubelet=1.17.4-00
root@Node-2:~# apt install kubeadm=1.17.4-00 kubelet=1.17.4-00
root@Node-3:~# apt install kubeadm=1.17.4-00 kubelet=1.17.4-00

验证最终版本:

root@master-1:~# kubectl get node 
NAME       STATUS   ROLES    AGE     VERSION
master-1   Ready    master   7h46m   v1.17.4
master-2   Ready    master   7h3m    v1.17.4
master-3   Ready    master   6h48m   v1.17.4
node-1     Ready    <none>   6h35m   v1.17.4
node-2     Ready    <none>   6h34m   v1.17.4
node-3     Ready    <none>   6h13m   v1.17.4

更多咨询,关注微信公众号