devops-cd之esxi和docker实战
概要
devops-cd之vagrant virtualbox实战
https://www.yuque.com/wushifengcn/kb/qo3kmu
这篇文章讲解和示范了vagrant自动化virtualbox的情况
在vmware跨机器和docker场景下如下使用呢,本文总结下
- vmware esxi
- 通过vagrant操控
- 通过terraform操控
- docker
- docker-compose
- docker swarm
名词
Vmware 服务器虚拟化第一个产品叫ESX,该产品只有60天测试,没有官方认可的免费版。后来Vmware在4版本的时候推出了ESXI,ESXI和ESX的版本最大的技术区别是内核的变化,ESXI更小,更安全,从其他方面来说ESXI可以在网上申请永久免费的license,但是两个版本的收费版功能是完全一样的。
从4版本开始VMware把ESX及ESXi产品统称为vSphere,但是VMware从5版本开始以后取消了原来的ESX版本,所以现在来讲的话vSphere就是ESXI,只是两种叫法而已。一般官方文档中以称呼vSphere为主。
- ESXi Free版被更名为VMware vSphere Hypervisor
- vSphere的免费产品名字叫vSphere Hypervisor,而收费产品有各个版本,包括Essentials,Standard,Enterprise和Enterprise Plus。
- vCenter Server则是另外一个独立产品,用于集中式管理vSphere环境。
【 VMware ESX 和 VMware ESXi 都是直接安装在服务器硬件上的裸机管理程序】
ESXI上部署
软件可以在官方下载
具体的esxi server可以通过WEB浏览器进行管理
下面我们关注的是远程的自动化操作,vagrant和terrafom都可以来操控,可以根据自己的熟悉程度和自己的团队的技术栈来选择
vagrant操控
#
vagrant plugin list | grep vagrant-vmware-esxi || {
vagrant plugin install --plugin-clean-sources --plugin-source https://gems.ruby-china.com/ --debug vagrant-vmware-esxi
}
vagrant box list|grep 'centos7.4_vmware' || {
vagrant init centos7.4_vmware "http://cloud.centos.org/centos/7/vagrant/x86_64/images/CentOS-7-x86_64-Vagrant-1708_01.VMwareFusion.box"
#导入后在 ~/.vagrant.d/boxes/centos7.4_vmware/0/vmware_desktop 可以看到虚拟机文件
}
# 修改Vagrantfile后执行即可远程部署和启动我们设置的虚拟机vagrant up --provider=vmware_esxi
vagrant up
Vagrantfile的vmware_esxi插件语法和例子参考如下
https://hub.fastgit.org/josenk/vagrant-vmware-esxi
https://hub.fastgit.org/josenk/vagrant-vmware-esxi/tree/master/example_box
设置好Vagrantfile后,即可使用vagrant的命令语法来操控了
terraform操控
https://registry.terraform.io/providers/hashicorp/vsphere/latest terraform官方针对vsphere的操作说明是针对大多是针对vcenter进行操作,有的也可以直接在esxi server上执行执行,如果安装vcenter有些复杂
我们选这一个比较简洁的方式,社区的一个实现https://hub.fastgit.org/josenk/terraform-provider-esxi
【注意这个依赖于
- ovftool from VMware.
安装 Vmare workstation 后直接有这个工具 【或者https://code.vmware.com/web/tool/4.4.0/ovf 下载,VMware-ovftool-4.4.1-16812187-lin.x86_64.bundle 】
- You MUST enable ssh access on your ESXi Server
terraform配置文件main.tf
variable "vm_name" {
description = "VM to be created's name"
default = "testvm"
}
variable "vcpus" {
description = "VM to be created's Cpu count"
default = "1"
}
variable "memsize" {
description = "VM to be created's memory[mb]"
default = "1024"
}
variable "state" {
description = "VM state[on / off]"
default = "on"
}
terraform {
required_version = ">= 0.13"
required_providers {
esxi = {
source = "josenk/esxi"
version = "1.8.1"
}
}
}
#esxi server的信息
provider "esxi" {
esxi_hostname = "192.168.80.201"
esxi_hostport = "22"
esxi_hostssl = "443"
esxi_username = "root"
esxi_password = "Root123!"
}
resource "esxi_guest" "vmtest" {
guest_name = var.vm_name
disk_store = "datastore1"
power = var.state
numvcpus = var.vcpus
memsize = var.memsize
#准备部署的ova文件,这个提前准备好
ovf_source = "./ovaexp/vmtest.ova"
network_interfaces {
virtual_network = "VM Network"
# mac_address =
# nic_type = "e1000"
}
}
output "ip" {
value = esxi_guest.vmtest.ip_address
}
部署脚本vm.sh
执行如下的内容,即可动态的建立一个虚拟机了【由于josenk/esxi这个provider不能直接设置ip,因此脚本中换了种方式使用ansible进行设置】
#!/bin/bash
set -xeuo pipefail
BaseDir=$(cd "$(dirname "$0")"; pwd)
cd ${BaseDir}
#原始的IP和需要改变成的IP
#192.168.80.100
RIP=192.168.80.100 #inventory的地址和这个一样
NAME=${1-TEST}
VCPUS=${2-1}
MEMSIZE=${3-1024}
IP=${4-192.168.80.100}
echo "Create VM: ${NAME} ${VCPUS} ${MEMSIZE} ${IP}"
#1 通过terraform导入一个固定IP的虚拟机
#指定虚拟机名字、CPU个数、内存大小[MB]
terraform apply -auto-approve -var "vm_name=${NAME}" -var "vcpus=${VCPUS}" -var "memsize=${MEMSIZE}"
#2 如上固定的IP可用后,使用ansbile修改IP
# ova镜像先期条件 ssh -o StrictHostKeyChecking=no -i ./id_rsa vagrant@192.168.80.100
[ "${IP}" = "${RIP}" ] || {
ansible all -i inventory -m ping
ansible all -i inventory -m replace -a "path=/etc/sysconfig/network-scripts/ifcfg-eth0 regexp=${RIP} replace=${IP}" -b
#修改后重启下机器
terraform apply -auto-approve -var "vm_name=${NAME}" -var "vcpus=${VCPUS}" -var "memsize=${MEMSIZE}" -var "state=off"
terraform apply -auto-approve -var "vm_name=${NAME}" -var "vcpus=${VCPUS}" -var "memsize=${MEMSIZE}" -var "state=on"
}
#如上做完了,在这个虚拟机上可以自由发挥了
echo "done"
inventory文件内容
[ovfbase]
192.168.80.100
[ovfbase:vars]
# ansible_ssh_user ansible_ssh_pass
ansible_ssh_port=22
ansible_ssh_user=vagrant
ansible_ssh_private_key_file=./id_rsa.pub
host_key_checking=false
docker上部署
- 单机上
- 只是运行某个容器,直接命令行或者shell脚本即可
- 如果是多个容器并有依赖关系等比较复杂的设置,可以使用docker-compose
- 多机上
- docker swarm进行分布式部署【不过这个逐步淘汰了,k8s是目前更主流的形式】,但优点是比k8s简单易用
docker-compose
docker-compose是在单机上进行容器编排的工具
在多机分布式式容器编排,docker公司提供的是swarm产品,目前主流的是k8s
docker-compose是python写的程序,可以从这下载单个的打包执行文件,放入/usr/bin/下直接使用【 https://github.com/docker/compose/releases ,python方式的安装方法pip install docker-compose】
docker-compose通过配置好的compose文件运行【compose文件中指定了运行的所有设置,默认读取的文件名为docker-compose.yml】,compose文件语法
https://docs.docker.com/compose/compose-file/compose-file-v3/
从这个例子可以看到概貌
https://docs.docker.com/compose/compose-file/compose-file-v3/#compose-file-structure-and-examples
例子解释
version: "3.9" compose的版本
services: 启动的容器服务节,这个下面可以定义各种服务
redis: 定义一个服务
image: redis:alpine 容器镜像名称
ports: 提供服务的端口,也可以设置映射到host机器的端口
- "6379"
networks:使用的网络
- frontend
deploy: swarm方式下的部署条件设置
replicas: 2
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure
db:
image: postgres:9.4
volumes: 存储卷设置
- db-data:/var/lib/postgresql/data 将docker的db-data卷映射到容器的/var/lib/postgresql/data目录
networks:
- backend
deploy:
placement:
max_replicas_per_node: 1
constraints:
- "node.role==manager"
vote:
image: dockersamples/examplevotingapp_vote:before
ports:
- "5000:80"
networks:
- frontend
depends_on:
- redis
deploy:
replicas: 2
update_config:
parallelism: 2
restart_policy:
condition: on-failure
result:
image: dockersamples/examplevotingapp_result:before
ports:
- "5001:80"
networks:
- backend
depends_on:
- db
deploy:
replicas: 1
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure
worker:
image: dockersamples/examplevotingapp_worker
networks:
- frontend
- backend
deploy:#swarm集群下管理节点上【node.role==manager】部署1个实例,可弹性部署【replicated】
mode: replicated
replicas: 1
labels: [APP=VOTING] #标签用于分类和过滤等,k8s中一个很关键的属性
restart_policy:
condition: on-failure
delay: 10s
max_attempts: 3
window: 120s
placement:
constraints:
- "node.role==manager"
visualizer:
image: dockersamples/visualizer:stable
environment: #部署主机的主机名hostname
- node.name=visualizer
ports:
- "8080:8080"
stop_grace_period: 1m30s
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
deploy:
placement: #swarm集群下仅在管理节点部署这个容器
constraints:
- "node.role==manager"
networks: 网络设置,如下设置了2个网络,网络的配置使用默认
frontend:
backend:
volumes: 卷配置
db-data:
大体的逻辑关系:
frontend网络中
redis容器:redis 6379服务
vote容器:依赖于redis容器,80服务,映射到主机的端口是5000
backend网络
db容器:postgres 服务,持久化数据到db-data卷
result容器:依赖于db, 80服务端端口,映射到主机的端口是5001
跨越frontend backend网络
worker容器:
默认的docker网络:
visualizer容器: 8080服务端端口,映射到主机的端口是8080
常用命令
- 启动
- 服务方式:
- docker-compose up -d:容器不存在创建并运行
- docker-compose start: 容器已经存在时运行
- 阻塞方式:docker-compose up
- 指定某个配置运行:docker-compose -f docker-composeV3.yml up
- 停止
- docker-compose down: Stop and remove containers, networks, images, and volumes
- docker-compose stop: Stop services
- 清理
- docker-compose rm
docker常用运行例子
- docker run --rm/-itd -v $PWD:/rally --name rally --network host dev.docker:8085/elastic/rally:2.0.0 --track=nyc_taxis --test-mode --pipeline=benchmark-only --target-hosts=localhost:9200
- --rm/-itd:--rm运行后直接删除容器; itd 服务方式运行容器
- -v $PWD:/rally: 将当前目录挂载到容器的/rally目录下,作为存放数据目录使用
- --name rally:执行容器的名字,这样docker exec之类的方便使用
- --network host:直接使用主机的ip地址
- dev.docker:8085/elastic/rally:2.0.0:镜像的名称和版本
- --track=nyc_taxis... :运行是传递的参数,这个是和容器内启动程序配合的,如果直接写bash/sh之类,那就会启动个shell
- docker exec -uroot -it rally sh
- 已经运行的容器,以root用户shell登录进去
- docker logs rally -f
- 查看运行的rally容器的输出日志
https://developer.aliyun.com/article/783289?spm=a2c6h.12883283.1362932.3.5f1f201cdosA8U 《AI开发者的Docker实践》这个电子书可以参考
Tip
- 多容器间主机名的通讯
- 在同一个网络的容器可以直接通过主机名【或容器名】通讯,docker内部相当于有个dns,直接解析成了ip
- docker的数据存储
- 数据不要在容器内直接存储,因此容器的格式是aufs,效率没有ext等文件系统高
- 数据一般使用docker建立卷或者映射主机的目录,具体有如下几种
- docker volume命令建立的卷
- -v 映射主机的数据目录挂载到容器的卷
- 在容器内使用nfs之类远程挂载
- host主机ip帮助
- docker-compose -h
- docker-compose help up ....
- docker-compose中变量使用
- 启动时设置变量 export ELASTIC_VERSION=7.9.0
- compose文件中引用
- image: dev.docker:8085/kibana:${ELASTIC_VERSION:-7.8.0}
- 容器内的服务提供服务
- 容器想提供服务,需要首先确保容器内对应的服务进程的正常
- 服务端口需要暴露,expose
- 对外提供服务
- 方式1:使用容器的:ip+端口
- 方式2:设置端口映射,使用:host主机ip+映射端口
- 方式3:仅在网络模式设置了host模式时,使用:host主机ip+expose端口
- 【方式1,2如果对其他的主机提供服务还需要一些特别的设置,方式3其他主机可以直接访问这个服务;服务的诊断curl tcpdump工具很重要】
- docker的镜像
- Dockerfile文件的约定 https://docs.docker.com/engine/reference/builder/
- 自己做镜像是,镜像大小需要注意下,这个有较多的优化技巧【当然如果只是局域网内部用,大小不受限的话就无所谓】
- docker镜像被墙了
- 方式1:使用vpnFQ下载
- 方式2:使用阿里云容器服务或者github上进行海外构建方式,可以规避这个问题【执行查找docker海外构建】
- 容器的资源如何限制
- cpu 、内存等都是可以设置的,具体参考官方文档,命令行和compose文件都可以设置
- 容器和HOST主机如何传递数据文件
- 方式1:基于sftp相互拷贝【需要容器配置好ssh服务并开启sftp】
- 方式2:使用docker cp FILES containerName:FILES 互相拷贝
- 方式3:使用共享的卷传递,docker运行时-v指定的共享目录
- 容器运行数据如何清理
- 运行相关的数据涉及 network volume container system【这个包含了前面3个】,清理这些数据时这些数据资源不能正在使用,其中volume这个需要慎重,这是程序运行保存的数据,需要做好备份
- 使用方法类似:docker system prune -f
- 容器的资源使用情况如何监控
- 在容器内执行top看到的数据不是容器的数据,监控需要使用类似
- 容器内运行:ctop
- HOST机器上运行:cadvisor、metricbeat、docker stats 命令行查看
- 在HOST主机上如何自动运行容器内的脚本等执行文件
- 类似: docker exec -it radius sh "apk add freeradius-client",权限不对的可以增加-u username 参数
参考
devops-hasicorp产品图 https://www.yuque.com/wushifengcn/kb/bbvrtw
devops-cd之esxi和docker实战 https://www.yuque.com/wushifengcn/kb/tyy1r6
devops-cd之vagrant virtualbox实战 https://www.yuque.com/wushifengcn/kb/qo3kmu