简介
Calico是一个基于BGP的纯三层的网络方案,与OpenStack,Kubernetes,AWS,GCE等云平台都能够良好地集成.
Calico在每个计算节点利用Linux kernel实现了一个高效的vrouter来负责转发.每个vrouter通过BGP1协议把在本节点上运行的容器的路由信息向整个calico网络广播,并自动设置到达其它节点的路由转发规则.
Calico保证所有容器之间的数据流量都是通过IP路由的方式完成互连互通的.Calico节点组网可以直接利用数据中心的网络结构(L2或者L3),不需要额外的NAT,隧道或者overlay network,没有额外的封包解包,能够节约CPU运算,提高网络效率.
lvreduce -L 100G /dev/mapper/centos-home # home目录减少100G
lvextend -l +100%FREE /dev/mapper/centos-root # root目录增加所有空闲的
xfs_growfs /dev/mapper/centos-root # 将实际分区落盘
参考连接conntrack
OVS supports following match fields related to conntrack:
ct_state
: The state of a connection matching the packet. 可能的值有:
new
est
rel
rpl
inv
trk
snat
dnat
上述字段
如果前面有+
号, 则说明是必须设置的标记;
如果前面有-
号, 则说明必须取消的标记.
同样也支持多个字段同时设置, 例如 ct_state=+trk+new
参考ovs-fields了解更多
ct_zone
:16bit字段用作另一个flow entry的匹配fieldct_mark
:给当前连接的包打上32bit的metadata数据ct_label
给当前连接的包打上128bit的label- …
mysql:
build:
context: ./mariadb
dockerfile: ./Dockerfile
container_name: mariadb_yoga
restart: on-failure
command:
- /bin/bash
- -c
- |
mysqld --user=root
mysql -u root -p 123456 < /db/init_db.sql
volumes:
- /var/lib/openstack/yoga/mysql:/var/lib/mysql
- /etc/localtime:/etc/localtime
ports:
- "23306:3306" # host物理直接映射端口为13306
environment:
MYSQL_ROOT_PASSWORD: '123456' # root管理员用户密码
networks:
network:
ipv4_address: 177.177.0.13
可选策略
在docker run通过 –restart 设置守护机制:
- no: 不自动重新启动容器(默认)
- on-failure: 容器发生error而退出(容器退出状态不为0)重启容器
- unless-stopped: 在容器已经stop掉或Docker stoped/restarted的时候才重启容器
- always: 如果容器停止,总是重新启动容器。如果手动kill容器,则无法自动重启。
docker update追加命令
运行中的容器,当时没有指定restart可以通过update命令追加
举例: web为正在运行的容器
docker update --restart=always web
参考:https://www.jianshu.com/p/5c1f152ac4a6
1. 前言
(Union filesystem)联合文件系统允许我们把多个文件系统逻辑上合并成一个文件系统,组成Union filesystem的文件系统不必相同(它们可以是ext2/3/4,vfat,ntfs,jffs…)。overlay是联合文件系统的一种(a ufs…),overlay文件系统构建于其他文件系统之上,overlay其实更像是个挂载系统(mount system),功能是把不同的文件系统挂载到统一的路径。
2. overlay文件系统
overlay是个分层的文件系统,底层文件系统通常叫lower,顶层文件系统系统通常叫upper,两者通常合并挂载到merged目录,最终用户看到的就是merged中的文件。
lower文件系统是readonly,对merged中所有的修改都只对upper操作,记住这点很重要。下面我们在linux上创建一个overlay文件系统,用以说明overlay文件系统挂载,文件读写,文件新增和删除。
3. 创建overlay文件系统
创建lower upper merged work目录,把lower和upper挂载到merged,work是空目录,必须和merged的文件系统类型一样。
(base) [root@lex learn_cgroup]# tree upper/
upper/
├── books
│ ├── readher.txt
│ └── readyou.txt
├── readme.txt
└── read.txt
(base) [root@lex learn_cgroup]# tree lower/
lower/
├── books
│ ├── readme.txt
│ └── readyou.txt
└── readme.txt
挂载: mount -t overlay overlay -o lowerdir=./lower,upperdir=./upper,workdir=./work merged
,挂载后merged目录结构如下:
(base) [root@lex learn_cgroup]# tree merged/
merged/
├── books
│ ├── readher.txt
│ ├── readme.txt
│ └── readyou.txt
├── readme.txt
└── read.txt
可以看到lower和upper中的文件合并到了merged中,当lower和upper有相同路径的文件时,merged中只显示upper中的。也就是说upper会遮住lower中同名的文件(同路径下)。
CAS算法(compare and swap)
CAS算法是一种有名的无锁算法。无锁编程,即不使用锁的情况下实现多线程之间的变量同步,也就是在没有线程被阻塞的情况下实现变量的同步,所以也叫非阻塞同步(Non-blocking Synchronization)。CAS算法涉及到三个操作数:
- 需要读写的内存值V
- 进行比较的值A
- 拟写入的新值B
当且仅当V的值等于A时,CAS通过原子方式用新值B来更新V的值,否则不会执行任何操作(比较和替换是个原子操作).一般情况下是一个自旋操作,即不断的重试.
自旋锁
自旋锁是指当一个线程在获取锁的时候,如果锁已经被其他线程获取,那么该线程循环等待,然后不断地判断是否能被成功获取,知道获取到锁才会退出循环
获取锁的线程一直处于活跃状态,但是并没有执行任何有效的任务,使用这种锁会造成busy-waiting
。
它是为实现保护共享资源而提出的一种锁机制。其实,自旋锁与互斥锁比较类似,它们都是为了解决某项资源的互斥使用。无论是互斥锁,还是自旋锁,在任何时刻,最多只能由一个保持者,也就说,在任何时刻最多只能有一个执行单元获得锁。但是两者在调度机制上略有不同。对于互斥锁,如果资源已经被占用,资源申请者只能进入睡眠状态。但是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁,“自旋”一词就是因此而得名。
实现自旋锁
type spinLock uint32
func (sl *spinLock) Lock() {
for !atomic.CompareAndSwapUint32((*uint32)(sl), 0, 1) {
runtime.Gosched()
}
}
func (sl *spinLock) Unlock() {
atomic.StoreUint32((*uint32)(sl), 0)
}
func NewSpinLock() sync.Locker {
var lock spinLock
return &lock
}
可重入自旋锁和不可重入自旋锁
上面的代码不支持重入,即当一个线程第一次已经获取到了该锁,在锁释放之前又一次重新获取该锁,第二次就不能成功获取到.由于不满足cas,所以第二次会进入for循环等待,而如果是可重入锁,第二次也能得到锁. 为了实现可重入锁,要引入一个计数器,用来记录获取锁的线程数
type spinLock struct {
owner int
count int
lock uint32
}
func (sl *spinLock) Lock() {
me := GetGoroutineId()
if sl .owner == me { // 如果当前线程已经获取到了锁,线程数增加一,然后返回
sl.count++
return
}
// 如果没获取到锁,则通过CAS自旋
for !atomic.CompareAndSwapUint32(&sl.lock, 0, 1) {
runtime.Gosched()
}
sl.owner = me
}
func (sl *spinLock) Unlock() {
if sl.owner != GetGoroutineId() {
panic("illegalMonitorStateError")
}
if sl.count >0 { // 如果大于0,表示当前线程多次获取了该锁,释放锁通过count减一来模拟
sl.count--
}else { // 如果count==0,可以将锁释放,这样就能保证获取锁的次数与释放锁的次数是一致的了。
atomic.StoreUint32(&sl.lock, 0)
}
}
func GetGoroutineId() int {
defer func() {
if err := recover(); err != nil {
fmt.Printf("panic recover:panic info:%v\n", err) }
}()
var buf [64]byte
n := runtime.Stack(buf[:], false)
idField := strings.Fields(strings.TrimPrefix(string(buf[:n]), "goroutine "))[0]
id, err := strconv.Atoi(idField)
if err != nil {
panic(fmt.Sprintf("cannot get goroutine id: %v\n", err))
}
return id
}
func NewSpinLock() sync.Locker {
var lock spinLock
return &lock
}
自旋锁的其他变种
1. TicketLock
TicketLock主要解决的是公平性的问题
Hypervisor:一种运行在物理服务器和操作系统之间的中间层软件,可以允许多个操作系统和应用共享一套基础物理硬件. 可以将Hypervisor看做是虚拟环境中的"元"操作系统,可以协调访问服务器上的所有物理设备的虚拟机,所以又称为虚拟机监视器(virtual machine monitor). Hypervisor是所有虚拟化技术的核心,非中断的支持多工作负载迁移是Hypervisor的基本功能.
当服务器启动并执行Hypervisor时,会给每一台虚拟机分配适量的内存,cpu,网络和磁盘资源,并且加载所有虚拟机的客户操作系统.
Hypervisor之于操作系统类似于操作系统之于进程.他们为执行提供独立的虚拟硬件平台,而虚拟硬件平台反过来有提供对底层机器的虚拟的完整访问.但并不是所有Hypervisor都是一样的.
虚拟化和Hypervisor
虚拟化就是通过某种方式隐藏底层物理硬件的过程,从而让多个操作系统可以透明的使用和共享它.
Hypervisor分类
- 类型1:这种Hypervisor运行在物理硬件之上
- 类型2:Hypervisor运行在另一个操作系统(运行在物理硬件上)中.
类型1例子:基于内核的虚拟机(kvm—它本身是一个基于操作系统的Hypervisor) 类型2例子:包括qemu和wine.
配置IPv6地址:
ifconfig enp9s0f1 inet6 add 81::d/64
配置IPv4地址:
ifconfig enp9s0f1 add 10.0.0.6/64
ifconfig enp9s0f1 delete 10.0.0.6/64
internet意思是用一个共同的协议族把多个网络连接在一起. 而Internet指的是世界范围内通过TCP/IP互相通信的所有主机集合
Internet是一个internet,但internet不等于Internet