docker&k8s学习笔记

304 阅读1分钟

DevOps架构图

Docker底层架构

由Go语言开发实现,并基于Linux内核的cgroup,namespace

实验环境搭建

使用vagrant来搭建服务器

  • 下载安装
  • 构建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
      

构建自定义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服务。

  • mysqlworkpress 将会随机部署到集群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'