DevOps架构图
Docker底层架构
由Go语言开发实现,并基于Linux内核的cgroup,namespace
实验环境搭建
使用vagrant来搭建服务器
- 下载安装
- vagrant www.vagrantup.com/
- virtualBox www.virtualbox.org/
- 构建Centos7
- 查看版本
vagrant -v
- 选择或者本地创建文件目录centos7
mkdir centos7
- 初始化centos7配置信息
vagrant init centos/7
- 会在当前目录下生成系统配置文件
Vagrantfile
- 下载系统镜像并配置启动
vagrant up
- 根据
Vagrantfile
配置下载镜像以及配置服务信息
- 连接centos7
vagrant ssh
- 退出centos7
exit
- 查看服务器列表状态
vagrant status
- 关闭centos7
vagrant halt
- 查看版本
- Docker安装
- 卸载旧版本的Docker
$ sudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine
- 安装Docker仓库
$ sudo yum install -y yum-utils \ device-mapper-persistent-data \ lvm2 $ sudo yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo
- 安装Docker
$ sudo yum install docker-ce -y
- 启动Docker
$ sudo systemctl start docker
- 验证是否安装成功
$ sudo docker version
- 卸载旧版本的Docker
构建自定义Image
Dockerfile
FROM scratch # 制作Base Image
FROM centos # 使用Base Image
LABEL maintainer="gaozaoshun@mtty.com"
LABEL version="1.0"
LABEL description="descp"
RUN yum install -y vim \
pytion-dev
WORKDIR /test # 根路径下创建test文件夹
WORKDIR demo
RUN pwd # 输出/test/demo
ADD xxx.tar.gz / # 解压xxx.tar.gz到根目录下
COPY xxx.tar.gz / # 复制xxx.tar.gz到根目录下
ENV MYSQL_VERSION 5.6 # 设置常量
RUN apt-get install -y mysql-server="${MYSQL_VERSION}"\
&& rm -rf /var/lib/apt/list*
执行命令
- RUN 执行命令并创建新的Image Layer
构建Image执行RUN会临时生成一个新的Image,待构建完毕后删除该临时Image
- CMD 设置容器启动后默认执行的命令和参数
docker run Image时会执行CMD命令,如果后面添加/bin/bash则会覆盖CMD命令,即不执行CMD命令
- ENTRYPOINT 设置容器启动时运行的命令
docker run Image时会执行该命令,无论是否以/bin/bash终端执行
docker run image -xms 256m
Dockerfile 末尾添加CMD [] 会将-xms 256m 作为添加到ENTRYPOINT的命令后执行
网络命名空间
bridge
容器启动未指定network时,默认使用的namespace,默认地址172.17.0.1
,启动后会docker容器会桥接到docker0
上,并自动创建IP。
当多个docker容器使用--network bridge
启动时,都桥接到docker0
上,形成局域网,可互相访问。
host
当docker容器使用host模式
启动时,容器将会使用宿主机的Network NameSpace
,与宿主机共享同一IP和端口。
none
在none模式下,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。
container
容器以--network container
模式启动时,将与指定docker容器共享IP和端口。
单机部署多容器复杂应用
启动一个应用redis的web应用
- 启动Redis容器,默认birdge
docker run -d --name gaozaoshun/redis redis
- 编写python web脚本
from flask import Flask
import redis
import os
import socket
app = Flask(__name__)
redis = redis.Redis(host=os.environ.get('REDIS_HOST','127.0.0.1'),port=6379)
@app.route('/')
def hello():
redis.incr('hits')
return 'COUNT:%s,IP:%s \n' % (redis.get('hits'),socket.gethostname())
if __name__ == '__main__':
app.run(host='0.0.0.0',port=5000,debug=True)
- 编写Dockerfile
FROM python:2.7
RUN pip install redis flask
COPY app.py /app/
WORKDIR /app
EXPOSE 5000
ENTRYPOINT ["python","app.py"]
- 制作Docker Image
docker build -t gaozaoshun/flask-redis .
- 启动容器flask-redis
通过
--link gaozaoshun/redis
并设置环境变量-e REDIS_HOST=gaozaoshun/redis
容器内即可使用该环境变量REDIS_HOST
docker run -d --name flask-redis --link gaozaoshun/redis -e REDIS_HOST=gaozaoshun/redis gaozaoshun/flask-redis
- 对接部署完毕
多机部署多容器应用
使用overlay网络命名空间可以实现多机间的网络通信
overlay的搭建需要开源分布式存储库etcd的支持
两台服务器均安装etcd并启动etcd
在docker-node1上
wget https://github.com/coreos/etcd/releases/download/v3.0.12/etcd-v3.0.12-linux-amd64.tar.gz
tar zxvf etcd-v3.0.12-linux-amd64.tar.gz
cd etcd-v3.0.12-linux-amd64
nohup ./etcd --name docker-node1 \
--initial-advertise-peer-urls http://192.168.205.10:2380 \
--listen-peer-urls http://192.168.205.10:2380 \
--listen-client-urls http://192.168.205.10:2379,http://127.0.0.1:2379 \
--advertise-client-urls http://192.168.205.10:2379 \
--initial-cluster-token etcd-cluster \
--initial-cluster docker-node1=http://192.168.205.10:2380,docker-node2=http://192.168.205.11:2380 \
--initial-cluster-state new&
在docker-node2上
wget https://github.com/coreos/etcd/releases/download/v3.0.12/etcd-v3.0.12-linux-amd64.tar.gz
tar zxvf etcd-v3.0.12-linux-amd64.tar.gz
cd etcd-v3.0.12-linux-amd64/
nohup ./etcd --name docker-node2 \
--initial-advertise-peer-urls http://192.168.205.11:2380 \
--listen-peer-urls http://192.168.205.11:2380 \
--listen-client-urls http://192.168.205.11:2379,http://127.0.0.1:2379 \
--advertise-client-urls http://192.168.205.11:2379 \
--initial-cluster-token etcd-cluster \
--initial-cluster docker-node1=http://192.168.205.10:2380,docker-node2=http://192.168.205.11:2380 \
--initial-cluster-state new&
检查cluster状态
./etcdctl cluster-health
member 21eca106efe4caee is healthy: got healthy result from http://192.168.205.10:2379
member 8614974c83d1cc6d is healthy: got healthy result from http://192.168.205.11:2379
cluster is healthy
重启docker服务
# docker-node1
systemctl stop docker.service
/usr/bin/dockerd \
-H tcp://0.0.0.0:2375 \
-H unix:///var/run/docker.sock \
--cluster-store=etcd://192.168.205.10:2379 \
--cluster-advertise=192.168.205.10:2375&
# docker-node2
systemctl stop docker.service
usr/bin/dockerd \
-H tcp://0.0.0.0:2375 \
-H unix:///var/run/docker.sock \
--cluster-store=etcd://192.168.205.11:2379 \
--cluster-advertise=192.168.205.11:2375&
创建overlay network
docker network create -d overlay demo
此时overlay网络
demo
会在docker-node2上同步创建
创建连接demo网络的容器
# docker-node1
docker run -d --name test1 --net demo busybox sh -c "while true; do sleep 3600; done"
#docker-node2
docker run -d --name test2 --net demo busybox sh -c "while true; do sleep 3600; done"
验证是否可相互通信
docker exec test1 sh -c "ping 10.0.0.3"
数据持久化之Data Volume
docker存在两种volume:
- Docker容器启动时系统后台自动创建的数据卷,docker rm后数据卷不会自动删除;
- Docker容器启动时通过参数
-v /usr/local/demo/date:/usr/local/data
将本地数据卷映射到容器内指定位置
数据卷的复用
# 启动mysql容器并映射到volume名为mysql的宿主机volume
docker run -d -v mysql:/var/lib/mysql -e MYSQL_ALLOW_EMPTY_PASSWOED=true mysql
当我们操作mysql数据库后会将操作记录以及数据都保存到容器的/var/lib/mysql下,所以当我们启动另一个mysql容器时将会同步到上一个mysql容器的所有数据和记录
开发利器
对于不需要重新编译的就能运行的项目,例如静态页面,flask项目,我们可以将项目路径映射到容器指定路径下,启动容器后运行项目,后续只需要上传更新的文件到宿主机的项目路径下即可。
docker compose
docker-compose通过一个yaml文件定义多容器的创建和管理。
services
一个service代表一个container,可通过image启动,也可通过Dockerfile启动。
networks
创建网络命名空间
volumes
创建宿主机映射到容器的数据卷
docker-compose.yml
version: '3'
services:
wordpress:
image: wordpress
ports:
- 8080:80
environment:
WORDPRESS_DB_HOST: mysql
WORDPRESS_DB_PASSWORD: root
networks:
- my-bridge
mysql:
image: mysql
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: wordpress
volumes:
- mysql-data:/var/lib/mysql
networks:
- my-bridge
networks:
my-bridge:
driver: bridge
volumes:
mysql-data:
当服务的访问量达到峰值时,可以通过--scale service=number
横向扩展,并使用Haproxy
负载均衡即可,实现高并发
docker-compose up --scale wordpress=3 -d
docker swarm
对docker服务进行编排,通过
docker service
后面指定参数选项可以对整个swarm集群进行管理,例如在manger节点上进行容器的创建,启动,水平扩展,集群状态信息的查看等。
swarm集群的搭建
# manager节点初始化
docker swarm init --advertise-addr=192.168.8.155
# worker节点初始化
docker swarm join --token SWMTKN-1-5s47aht6iwdil3ndztpqxwvv0omd569rtdq4h8m6wptk0o97wj-49q23xte2m5bdjgc1qpijvhir 192.168.8.155:2377
创建启动服务
# 创建overlay网络
docker network create -d overlay demo
# 创建mysql服务
docker service create -d \
--name mysql \
--env MYSQL_ROOT_PASSWORD=root \
--env MYSQL_DATABASE=wordpress \
--mount type=volume,source=mysql-data,destination=/var/lib/mysql \
--network demo mysql
# 创建workpress服务
docker service create \
--name workpress -p 80:80 \
--env WORDPRESS_DB_PASSWORD=root \
--env WOEDPRESS_DB_HOST=mysql \
--env WORDPRESS_DB_USER=root \
--env WORDPRESS_DB_NAME=wordpress \
--network demo wordpress
workpress当前最新版本不支持MySQL8.0版本默认的caching_sha2_password密码加密方式,我们只需要进入到mysql容器内修改wordpress使用的数据库账号对应密码的加密方式即可。命令如下:
mysql -u root -p
alter user 'root'@'%' identified with mysql_native_password by 'root';
flush privileges;
使用http://192.168.205.10:10086
http://192.168.205.11:10086
http://192.168.205.12:10086
都可以访问到wordpress服务。
mysql
和workpress
将会随机部署到集群docker节点服务器上,因使用同一overlay网络demo
,所以wordpress服务可以连通mysql服务;- 使用集群内任一服务器IP均可访问到wordpress,
- 当创建overlay网络时,并不会将overlay同步到其他docker上,任务分配到其他服务器并启动时才会将overlay网络同步到本机,swarm集群接替了etcd的工作,底层机制会同步overlay网络。
负载均衡和水平扩展
docker service scale serviceName=Number
集群服务间通信Routing Mesh
- Internal
- Container和Container之间的访问通过overlay网络(通过VIP虚拟IP)
- Ingress
- 如果服务有绑定接口,则此服务可以通过任意swarm节点的相应接口访问
Docker Stack
docker swarm中通过配置文件docker-compose.yml部署服务到不同主机上。
并对全部服务进行管理
docker stack deploy wordpress -c=docker-compose.yml
Docker Secret
用户名密码、SSH KEY、TLS认证、任何不想让别人看到的数据
创建secret - mysql_root_pw
$ echo "rootpwd" | docker secret create mysql_root_pw -
yltdqqfmm2cbhf77a819c51j7
使用secret
docker service create -d \
--name mysql \
--secret mysql_root_pw \
--env MYSQL_ROOT_PASSWORD_FILE=/run/secrets/mysql_root_pw \
--env MYSQL_DATABASE=wordpress \
--mount type=volume,source=mysql-data,destination=/var/lib/mysql \
--network demo mysql
service更新
版本更新
docker service update --image=demo:2.0 demo
端口迁移
docker service update --publish-rm 8080:80 --publish-add 8000:80 demo
Kubernetes
MiniKube单节点
安装kubectl、minikube
brew install kubectl minikube
minikube start --image-mirror-country='cn'