惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
aimingoo的专栏
aimingoo的专栏
IT之家
IT之家
N
Netflix TechBlog - Medium
MyScale Blog
MyScale Blog
雷峰网
雷峰网
T
Tailwind CSS Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
The Blog of Author Tim Ferriss
S
Schneier on Security
C
CERT Recently Published Vulnerability Notes
Help Net Security
Help Net Security
云风的 BLOG
云风的 BLOG
GbyAI
GbyAI
I
InfoQ
H
Help Net Security
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
酷 壳 – CoolShell
酷 壳 – CoolShell
G
GRAHAM CLULEY
Blog — PlanetScale
Blog — PlanetScale
G
Google Developers Blog
I
Intezer
大猫的无限游戏
大猫的无限游戏
AWS News Blog
AWS News Blog
Recent Announcements
Recent Announcements
Google DeepMind News
Google DeepMind News
Spread Privacy
Spread Privacy
博客园_首页
宝玉的分享
宝玉的分享
量子位
T
Threatpost
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Security Latest
Security Latest
C
Cybersecurity and Infrastructure Security Agency CISA
SecWiki News
SecWiki News
H
Hackread – Cybersecurity News, Data Breaches, AI and More
博客园 - Franky
C
CXSECURITY Database RSS Feed - CXSecurity.com
T
The Exploit Database - CXSecurity.com
T
Tenable Blog
Know Your Adversary
Know Your Adversary
P
Proofpoint News Feed
The Register - Security
The Register - Security
V2EX - 技术
V2EX - 技术
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Last Week in AI
Last Week in AI
L
LangChain Blog
T
Tor Project blog
Stack Overflow Blog
Stack Overflow Blog
月光博客
月光博客

博客园 - A.Z

这是在CNblogs倒闭前,本blog最后一篇随笔,请各位看官好好珍惜,主题:改变Docker Port 2376从你我做起,有图为证 DOCKER绝对领域从2048到4069?不:25519,数字的飞跃,HTTP/2 再次聚焦DOCKER MACHINE CODE 2048 视觉光盘,只有我可以贴全世界唯一,Windows上最高级的DOCKER客户端数字, 夜晚点击一个都没有,值班的小编辛苦了 视觉光盘,只有我可以贴全世界唯一,你永远截不到的图片(小编请用人性化语言解释移出首页) 深夜话题boot2docker还有那些隐藏MENU 揭发233的docker/machine 手动滑稽之golang-vmware-driver广告篇 Windows 7 + Tiny Linux 4.19 + XFS + Vmware Workstation 15 (PRO) 下篇dockerの奥义 预告:Windows 7 + Tiny Linux 4.19 + XFS + Vmware Workstation 15 (PRO)下篇dockerの奥义 首创诠释docker的Formulas: Windows 7 + Tiny Linux 4.19 + XFS + Vmware Workstation 15 (PRO) = super machine (docker从零开始时记,Follow me and you go) 竞斗云2.0开箱,内含全网首发真实测量数据 Aria2 1.35.0,更新,测试,发布 有哪些便宜还好用的东西,买了就感觉得了宝一样? 一起看期待已久的.NET Core 3.0新的单文件部署特性,记在昨日VS2019更新后 1张影射过往的图片,如何勾起往事的回忆,.CORE其实可以是这样的吗? 1张影射过往的图片,如何勾起往事的回忆,.CORE其实可以是这样的 全世界仅有的唯一最高LINUX版本的白菜路由,支持NAND记 续集:白菜的内涵,更新nand分区为ubifs,替换overlay
Go Goosy Disk Docker Port Provisioners (GDP)
A.Z · 2020-01-14 · via 博客园 - A.Z

小伙伴们,她们中出了一个叛徒,他是谁?是谁?是谁?


由一则口口相传的故事开始吧:

中午吃饭时间抽空小李跑到同座大楼的小张公司串门,小李是一名docker顾问熟称砖家,这间公司老板想挖小李,他盯了前台不到三秒,移开视线走到前同事小张的隔间边上打招呼,看到小张眉头紧锁,正在专著的看代码,小李把头凑过去,客套起来,正在忙呢,在学什么新技术?小张开口吼到:在翻小王的代码,你认识的那个烟友!小李一愣,哦那一个小王啊~,研究别人的技术,挺钻的呀,小李嘴上奉承道(心里暗忖着小张工资以前没我高,跳到这里估计也还在当下手吧),小张叹了一口气,嘣出三个字:烦着呢,小李映入眼前的是满屏密密麻麻的代码,左边的行标显示9999,不愧是千足代码,还有那么一小行格空的注释,醒目的打着时间---5年前----这是旧代码,小李摇头晃脑,有所觉悟

那就不打扰你了,想起烟瘾又犯了,正巧认识的小王也是同道中人,下意识就问,小王人呢?小张硕小的脑袋一震,青筋暴起,指了指打印机房外一个空台子,上面积了一层薄灰,放着一些杂物,像似好久没有人办公了,与此同时,一阵阴风从窗角吹过,扬起的窗帘把小张的脸映射成斑斑点点,小张把迟滞的目光瞟向了窗外的浮云,仿佛小王就在云端,小王离职了吗?小李不甘心的问了一句,突然一排没有窗户的老板格间悠悠的打开一扇门,仿佛有人藏在门后很久了,一个光头中年把头探了出来利索的喊了一句,小张进来,谈话!小张战战兢兢的放下鼠标,快速使了一个撤离眼色,轻声说,小王的老板老王现在变成了我的老板...就是以前那一个咚咚咚画白板的那个...小李装作若有所悟的样子恢恢手溜了

从此小李再也没有去小张的办公室,至今小李还在打着寒颤


 这个故事有什么寓意?听过的人众口难调(张冠李戴),索性作为发散性话题,放在本篇作引

 标题GDP三个首字母的组合作为揭发233的docker/machine的后续,为了符合标题的意义,请Follow me一起探究其中的秘密

 我们先从一段代码说起

// b2d hosts need to wait for the daemon to be up
// before continuing with provisioning
if err = WaitForDocker(provisioner, engine.DefaultPort); err != nil {
    return err
}

if err = makeDockerOptionsDir(provisioner); err != nil {
    return err
}

provisioner.AuthOptions = setRemoteAuthOptions(provisioner)

if err = ConfigureAuth(provisioner); err != nil {
    return err
}

这是一段在233篇中重点划出揭露的片断
节选自libmachine/provision/boot2docker.go

从233篇隐藏的逻辑可以判断,此处,导致了整个隐藏在Docker Machine中的b2d出现了port排异

函数WaitForDocker成为此段有争议的焦点

我们进入这段函数看看它到底是什么实现

func checkDaemonUp(p Provisioner, dockerPort int) func() bool {
	reDaemonListening := fmt.Sprintf(":%d\\s+.*:.*", dockerPort)
	return func() bool {
		// HACK: Check netstat's output to see if anyone's listening on the Docker API port.
		netstatOut, err := p.SSHCommand("if ! type netstat 1>/dev/null; then ss -tln; else netstat -tln; fi")
		if err != nil {
			log.Warnf("Error running SSH command: %s", err)
			return false
		}

		return matchNetstatOut(reDaemonListening, netstatOut)
	}
}

 这段试图在netstat返回结果字符类型中执行匹配函数matchNetstatOut

matchNetstatOut = regexp.MatchString(reDaemonListening, line)

 匹配的主角很不幸在这里被强硬的设置为engine.DefaultPort,在233篇里曾试图枚举过engine.DefaultPort的一些用例,不知道小伙伴们看出些什么端倪

在这里我们再次回到最先的那些函数片断,注意到随后调用的if err = ConfigureAuth(provisioner)没有?

这是一段惊心动魄的代码,路经在libmachine/provision/utils.go

不妨我们一起看一下这个ConfigureAuth函数有哪些内涵???

func (provisioner *Boot2DockerProvisioner) Service(name string, action serviceaction.ServiceAction) error {
    _, err := provisioner.SSHCommand(fmt.Sprintf("sudo /etc/init.d/%s %s", name, action.String()))
    return err
}

bits := 2048 


p.Service("docker", serviceaction.Stop);
.
log.Info("Copying certs to the local machine directory...");.
.
.
dockerPort := engine.DefaultPort
parts := strings.Split(u.Host, ":")
if len(parts) == 2 {
    dPort, err := strconv.Atoi(parts[1])
    if err != nil {
        return err
    }
    dockerPort = dPort
}
.
.
.

p.Service("docker", serviceaction.Start);
.
return WaitForDocker(p, dockerPort);

 这是我抽象出来的慰慰代码,在这段代码里,吉祥寺(似)dockerPort被正确合理的设置成它应该有的值,我把这段代码称呼为2048代码,为了抵消你们不时涌现的1024的念头!

如果诸位可以认真地再多看几遍,一定会产生出一群问号???

这里所有的op都以SSH的方式调用,而SSH又隐藏了什么不为人知的小故事?我们一起来猜测,谁是哪一名画白板的人

func (provisioner *Boot2DockerProvisioner) SSHCommand(args string) (string, error) {
	return drivers.RunSSHCommandFromDriver(provisioner.Driver, args)
}

 在b2d内部,SSH的责任链落到driver头上,对就是那一个driver,那一个,那一个,我在手动滑稽之golang-vmware-driver广告篇贴图之一,不会错了

driver为什么会对SSH轻车熟路?

As:

func GetSSHClientFromDriver(d Driver) (ssh.Client, error) {
	address, err := d.GetSSHHostname()
	if err != nil {
		return nil, err
	}

	port, err := d.GetSSHPort()
	if err != nil {
		return nil, err
	}

	var auth *ssh.Auth
	if d.GetSSHKeyPath() == "" {
		auth = &ssh.Auth{}
	} else {
		auth = &ssh.Auth{
			Keys: []string{d.GetSSHKeyPath()},
		}
	}

	client, err := ssh.NewClient(d.GetSSHUsername(), address, port, auth)
	return client, err

}

func RunSSHCommandFromDriver(d Driver, command string) (string, error) {
	client, err := GetSSHClientFromDriver(d)
	if err != nil {
		return "", err
	}

	log.Debugf("About to run SSH command:\n%s", command)

	output, err := client.Output(command)
	log.Debugf("SSH cmd err, output: %v: %s", err, output)
	if err != nil {
		return "", fmt.Errorf(`ssh command error:
command : %s
err     : %v
output  : %s`, command, err, output)
	}

	return output, nil
}

 回到现象

func WaitForSpecificOrError(f func() (bool, error), maxAttempts int, waitInterval time.Duration) error {
	for i := 0; i < maxAttempts; i++ {
		stop, err := f()
		if err != nil {
			return err
		}
		if stop {
			return nil
		}
		time.Sleep(waitInterval)
	}
	return fmt.Errorf("Maximum number of retries (%d) exceeded", maxAttempts)
}

func WaitForSpecific(f func() bool, maxAttempts int, waitInterval time.Duration) error {
	return WaitForSpecificOrError(func() (bool, error) {
		return f(), nil
	}, maxAttempts, waitInterval)
}

 如果docker port已经修改这里会抽风10次,显示ssh调用if ! type netstat 1>/dev/null; then ss -tln; else netstat -tln; fi正确返回已经改变的docker port和ssh port侦听列表

 然而无法match engine.DefaultPort带来的err是臆想不到的,err msg更无法判断b2d的内部排异,这迫使我试图寻找AzureProvisioner,这个不存在的名称

 如果看到这里我再向你吐露docker port从driver中产生或许一点也不会吃惊,最后的伪函数片段是

// Driver defines how a host is created and controlled. Different types of
// driver represent different ways hosts can be created (e.g. different
// hypervisors, different cloud providers)
type Driver interface {
    // Create a host using the driver's config
    Create() error

    // DriverName returns the name of the driver
    DriverName() string

    // GetCreateFlags returns the mcnflag.Flag slice representing the flags
    // that can be set, their descriptions and defaults.
    GetCreateFlags() []mcnflag.Flag

    // GetIP returns an IP or hostname that this host is available at
    // e.g. 1.2.3.4 or docker-host-d60b70a14d3a.cloudapp.net
    GetIP() (string, error)

    // GetMachineName returns the name of the machine
    GetMachineName() string

    // GetSSHHostname returns hostname for use with ssh
    GetSSHHostname() (string, error)

    // GetSSHKeyPath returns key path for use with ssh
    GetSSHKeyPath() string

    // GetSSHPort returns port for use with ssh
    GetSSHPort() (int, error)

    // GetSSHUsername returns username for use with ssh
    GetSSHUsername() string

    // GetURL returns a Docker compatible host URL for connecting to this host
    // e.g. tcp://1.2.3.4:2376
    GetURL() (string, error)

    // GetState returns the state that the host is in (running, stopped, etc)
    GetState() (state.State, error)

    // Kill stops a host forcefully
    Kill() error

    // PreCreateCheck allows for pre-create operations to make sure a driver is ready for creation
    PreCreateCheck() error

    // Remove a host
    Remove() error

    // Restart a host. This may just call Stop(); Start() if the provider does not
    // have any special restart behaviour.
    Restart() error

    // SetConfigFromFlags configures the driver with the object that was returned
    // by RegisterCreateFlags
    SetConfigFromFlags(opts DriverOptions) error

    // Start a host
    Start() error

    // Stop a host gracefully
    Stop() error
}
u.Host from GetUrl() from Implementation of Driver
That's ALL of it.

这些代码调用关系一一展示过之后

// b2d hosts need to wait for the daemon to be up
// before continuing with provisioning

 这里,仅有的注释让我更加确信,以下一行是可以删除的代码,我们都善于反向操作

 然而我对改Machine始终抱No的态度,或许将来可能会注册一个账户submit patch,但是让我犹豫的是,我还没有写过任何hello world go,为什么比我更合适的人选没有呢???

这个疑问始终挥之不去,到了放松环节,请跟着我的节奏Blame(扒)一下精彩截图

图片被我约束了HTML尺寸,请点击单独在TAB页观看图片链接

-->-->

a


简出:

对策篇:

  1. 上文提到的制作自己的Machine,可惜华而不为
  2. 提交patch,为社区贡献,可惜遥遥无期
  3. Register Injection by Init Driver AND YOU CAN HAVE 4069

作为一个万全的对策一定要有一些把握,forkersfolk贡起宝典手册,找到了入门

请看

Init() functions can be used within a package block and regardless of how many times that package is imported
The init() function will only be called once

provisioners          = make(map[string]*RegisteredProvisioner)  <===hashmap

不仅如此,在一个go中init可以反复反反复复存在,按序调用

真是一大奇观, 请跟随我一起念作为结尾 Go

Goosy

Disk

Docker

Port

Provisioner