张晋涛

张晋涛 查看完整档案

北京编辑  |  填写毕业院校网易有道  |  Engineer 编辑 moelove.info/ 编辑
编辑

微信公众号:MoeLove
Container, Docker, Go, Kubernetes, Python, Vim;

为了准确筛选信息,可使用付费问答 https://segmentfault.com/pay/...

个人动态

张晋涛 发布了文章 · 2月19日

从 Go 的二进制文件中获取其依赖的模块信息

大家好,我是张晋涛。

我们用 Go 构建的二进制文件中默认包含了很多有用的信息。例如,可以获取构建用的 Go 版本:

(这里我使用我一直参与的一个开源项目 KIND 为例)

➜  kind git:(master) ✗ go version ./bin/kind 
./bin/kind: go1.16

或者也可以获取该二进制所依赖的模块信息:

➜  kind git:(master) ✗ go version -m ./bin/kind
./bin/kind: go1.16
        path    sigs.k8s.io/kind
        mod     sigs.k8s.io/kind        (devel)
        dep     github.com/BurntSushi/toml      v0.3.1
        dep     github.com/alessio/shellescape  v1.4.1
        dep     github.com/evanphx/json-patch/v5        v5.2.0
        dep     github.com/mattn/go-isatty      v0.0.12
        dep     github.com/pelletier/go-toml    v1.8.1  h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM=
        dep     github.com/pkg/errors   v0.9.1
        dep     github.com/spf13/cobra  v1.1.1
        dep     github.com/spf13/pflag  v1.0.5
        dep     golang.org/x/sys        v0.0.0-20210124154548-22da62e12c0c      h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
        dep     gopkg.in/yaml.v2        v2.2.8
        dep     gopkg.in/yaml.v3        v3.0.0-20210107192922-496545a6307b      h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
        dep     k8s.io/apimachinery     v0.20.2
        dep     sigs.k8s.io/yaml        v1.2.0

查看 KIND 代码仓库中的 go.mod文件,都包含在内了。

其实 Linux 系统中二进制文件包含额外的信息并非 Go 所特有的,下面我将具体介绍其内部原理和实现。当然,用 Go 构建的二进制文件仍是本文的主角。

Linux ELF 格式

ELF 是 Executable and Linkable Format 的缩写,是一种用于可执行文件、目标文件、共享库和核心转储(core dump)的标准文件格式。ELF 文件 通常 是编译器之类的输出,并且是二进制格式。以 Go 编译出的可执行文件为例,我们使用 file 命令即可看到其具体类型 ELF 64-bit LSB executable

➜  kind git:(master) ✗ file ./bin/kind 
./bin/kind: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped

本文中我们来具体看看 64 位可执行文件使用的 ELF 文件格式的结构和 Linux 内核源码中对它的定义。

使用 ELF 文件格式的可执行文件是由 ELF 头(ELF Header) 开始,后跟 程序头(Program Header)节头(Section Header) 或两者均有组成的。

ELF 头

ELF 头始终位于文件的零偏移(zero offset)处(即:起点位置),同时在 ELF 头中还定义了程序头和节头的偏移量。

我们可以通过 readelf 命令查看可执行文件的 ELF 头,如下:

➜  kind git:(master) ✗ readelf -h ./bin/kind 
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x46c460
  Start of program headers:          64 (bytes into file)
  Start of section headers:          400 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         6
  Size of section headers:           64 (bytes)
  Number of section headers:         15
  Section header string table index: 3

从上面的输出我们可以看到,ELF 头是以某个 Magic 开始的,此 Magic 标识了有关文件的信息,即:前四个 16 进制数,表示这是一个 ELF 文件。具体来说,将它们换算成其对应的 ASCII 码即可:

45 = E

4c = L

46 = F

7f 是其前缀,当然,也可以直接在 Linux 内核源码中拿到此处的具体定义:

// include/uapi/linux/elf.h#L340-L343
#define    ELFMAG0        0x7f        /* EI_MAG */
#define    ELFMAG1        'E'
#define    ELFMAG2        'L'
#define    ELFMAG3        'F'

接下来的数 02 是与 Class 字段相对应的,表示其体系结构,它可以是 32 位(=01) 或是 64 位(=02)的,此处显示 02 表示是 64 位的,再有 readelf 将其转换为 ELF64 进行展示。这里的取值同样可以在 Linux 内核源码中找到:

// include/uapi/linux/elf.h#L347-L349
#define    ELFCLASSNONE    0        /* EI_CLASS */
#define    ELFCLASS32    1
#define    ELFCLASS64    2

再后面的两个 01 01 则是与 Data 字段和 Version 字段相对应的,Data 有两个取值分别是 LSB(01)和 MSB(02),这里倒没什么必要展开。另外就是 Version 当前只有一个取值,即 01 。

// include/uapi/linux/elf.h#L352-L358
#define ELFDATANONE    0        /* e_ident[EI_DATA] */
#define ELFDATA2LSB    1
#define ELFDATA2MSB    2

#define EV_NONE        0        /* e_version, EI_VERSION */
#define EV_CURRENT    1
#define EV_NUM        2

接下来需要注意的就是我前面提到的关于偏移量的内容,即输出中的以下内容:

  Start of program headers:          64 (bytes into file)
  Start of section headers:          400 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         6
  Size of section headers:           64 (bytes)
  Number of section headers:         15

ELF 头总是在起点,在此例中接下来是程序头(Program Header),随后是节头(Section Header),这里的输出显示程序头是从 64 开始的,所以节头的位置就是:

64 + 56 * 6 = 400

与上述输出符合,同理,节头的结束位置是:

400 + 15 * 64 = 1360

下一节内容中将用到这部分知识。

程序头

通过 readelf -l 可以看到其程序头,包含了若干段(Segment),内核看到这些段时,将调用 mmap syscall 来使用它们映射到虚拟地址空间。这部分不是本文的重点,我们暂且跳过有个印象即可。

➜  kind git:(master) ✗ readelf -l ./bin/kind 

Elf file type is EXEC (Executable file)
Entry point 0x46c460
There are 6 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000400040 0x0000000000400040
                 0x0000000000000150 0x0000000000000150  R      0x1000
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x0000000000333a75 0x0000000000333a75  R E    0x1000
  LOAD           0x0000000000334000 0x0000000000734000 0x0000000000734000
                 0x00000000002b3be8 0x00000000002b3be8  R      0x1000
  LOAD           0x00000000005e8000 0x00000000009e8000 0x00000000009e8000
                 0x0000000000020ac0 0x00000000000552d0  RW     0x1000
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x8
  LOOS+0x5041580 0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000         0x8

 Section to Segment mapping:
  Segment Sections...
   00     
   01     .text 
   02     .rodata .typelink .itablink .gosymtab .gopclntab 
   03     .go.buildinfo .noptrdata .data .bss .noptrbss 
   04     
   05     

节头

使用 readelf -S 即可查看其节头,其结构如下:

// include/uapi/linux/elf.h#L317-L328
typedef struct elf64_shdr {
  Elf64_Word sh_name;        /* Section name, index in string tbl */
  Elf64_Word sh_type;        /* Type of section */
  Elf64_Xword sh_flags;        /* Miscellaneous section attributes */
  Elf64_Addr sh_addr;        /* Section virtual addr at execution */
  Elf64_Off sh_offset;        /* Section file offset */
  Elf64_Xword sh_size;        /* Size of section in bytes */
  Elf64_Word sh_link;        /* Index of another section */
  Elf64_Word sh_info;        /* Additional section information */
  Elf64_Xword sh_addralign;    /* Section alignment */
  Elf64_Xword sh_entsize;    /* Entry size if section holds table */
} Elf64_Shdr;

对照实际的命令输出,含义就很明显了。

➜  kind git:(master) ✗ readelf -S ./bin/kind 
There are 15 section headers, starting at offset 0x190:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .text             PROGBITS         0000000000401000  00001000
       0000000000332a75  0000000000000000  AX       0     0     32
  [ 2] .rodata           PROGBITS         0000000000734000  00334000
       000000000011f157  0000000000000000   A       0     0     32
  [ 3] .shstrtab         STRTAB           0000000000000000  00453160
       00000000000000a4  0000000000000000           0     0     1
  [ 4] .typelink         PROGBITS         0000000000853220  00453220
       00000000000022a0  0000000000000000   A       0     0     32
  [ 5] .itablink         PROGBITS         00000000008554c0  004554c0
       0000000000000978  0000000000000000   A       0     0     32
  [ 6] .gosymtab         PROGBITS         0000000000855e38  00455e38
       0000000000000000  0000000000000000   A       0     0     1
  [ 7] .gopclntab        PROGBITS         0000000000855e40  00455e40
       0000000000191da8  0000000000000000   A       0     0     32
  [ 8] .go.buildinfo     PROGBITS         00000000009e8000  005e8000
       0000000000000020  0000000000000000  WA       0     0     16
  [ 9] .noptrdata        PROGBITS         00000000009e8020  005e8020
       0000000000017240  0000000000000000  WA       0     0     32
  [10] .data             PROGBITS         00000000009ff260  005ff260
       0000000000009850  0000000000000000  WA       0     0     32
  [11] .bss              NOBITS           0000000000a08ac0  00608ac0
       000000000002f170  0000000000000000  WA       0     0     32
  [12] .noptrbss         NOBITS           0000000000a37c40  00637c40
       0000000000005690  0000000000000000  WA       0     0     32
  [13] .symtab           SYMTAB           0000000000000000  00609000
       0000000000030a20  0000000000000018          14   208     8
  [14] .strtab           STRTAB           0000000000000000  00639a20
       000000000004178d  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  l (large), p (processor specific)

Go 二进制文件探秘

本文中,我们重点关注名为 .go.buildinfo 的部分。 使用 objdump 查看其具体内容:

➜  kind git:(master) ✗ objdump -s -j .go.buildinfo ./bin/kind

./bin/kind:     file format elf64-x86-64

Contents of section .go.buildinfo:
 9e8000 ff20476f 20627569 6c64696e 663a0800  . Go buildinf:..
 9e8010 a0fc9f00 00000000 e0fc9f00 00000000  ................

这里我们按顺序来,先看到第一行的 16 个字节。

image

  • 前 14 个字节是魔术字节,必须为 \xff Go buildinf:
  • 第 15 字节表示其指针大小,这里的值为 0x08,表示 8 个字节;
  • 第 16 字节用于判断字节序是大端模式还是小端模式,非 0 为大端模式,0 为小端模式。

我们继续看第 17 字节开始的内容。

Go 版本信息

前面我们也看到了当前使用的字节序是小端模式,这里的地址应该是 0x009ffca0

我们来取出 16 字节的内容:

➜  kind git:(master) ✗ objdump -s --start-address 0x009ffca0 --stop-address 0x009ffcb0 ./bin/kind   

./bin/kind:     file format elf64-x86-64

Contents of section .data:
 9ffca0 f5027d00 00000000 06000000 00000000  ..}.............

这里前面的 8 个字节是 Go 版本的信息,后 8 个字节是版本所占的大小(这里表示占 6 个字节)。

➜  kind git:(master) ✗ objdump -s --start-address  0x007d02f5 --stop-address 0x007d02fb ./bin/kind

./bin/kind:     file format elf64-x86-64

Contents of section .rodata:
 7d02f5 676f31 2e3136                        go1.16

所以,如上所示,我们拿到了构建此二进制文件所用的 Go 版本的信息,是用 Go 1.16 进行构建的。

Go Module 信息

前面我们使用了 17~24 字节的信息,这次我们继续往后使用。

➜  kind git:(master) ✗ objdump -s --start-address  0x009ffce0 --stop-address 0x009ffcf0 ./bin/kind       

./bin/kind:     file format elf64-x86-64

Contents of section .data:
 9ffce0 5a567e00 00000000 e6020000 00000000  ZV~.............

与前面获取 Go 版本信息时相同,前 8 个字节是指针,后 8 个字节是其大小。也就是说从 0x007e565a 开始,大小为 0x000002e6 ,所以我们可以拿到以下内容:

➜  kind git:(master) ✗ objdump -s --start-address  0x007e565a --stop-address 0x7e5940 ./bin/kind

./bin/kind:     file format elf64-x86-64

Contents of section .rodata:
 7e565a 3077 af0c9274 080241e1 c107e6d6 18e6 0w...t..A.......
 7e566a 7061 74680973 6967732e 6b38732e 696f path.sigs.k8s.io
 7e567a 2f6b 696e640a 6d6f6409 73696773 2e6b /kind.mod.sigs.k
 7e568a 3873 2e696f2f 6b696e64 09286465 7665 8s.io/kind.(deve
 7e569a 6c29 090a6465 70096769 74687562 2e63 l)..dep.github.c
 7e56aa 6f6d 2f427572 6e745375 7368692f 746f om/BurntSushi/to
 7e56ba 6d6c 0976302e 332e3109 0a646570 0967 ml.v0.3.1..dep.g
 7e56ca 6974 6875622e 636f6d2f 616c6573 7369 ithub.com/alessi
 7e56da 6f2f 7368656c 6c657363 61706509 7631 o/shellescape.v1
 7e56ea 2e34 2e31090a 64657009 67697468 7562 .4.1..dep.github
 7e56fa 2e63 6f6d2f65 76616e70 68782f6a 736f .com/evanphx/jso
 7e570a 6e2d 70617463 682f7635 0976352e 322e n-patch/v5.v5.2.
 7e571a 3009 0a646570 09676974 6875622e 636f 0..dep.github.co
 7e572a 6d2f 6d617474 6e2f676f 2d697361 7474 m/mattn/go-isatt
 7e573a 7909 76302e30 2e313209 0a646570 0967 y.v0.0.12..dep.g
 7e574a 6974 6875622e 636f6d2f 70656c6c 6574 ithub.com/pellet
 7e575a 6965 722f676f 2d746f6d 6c097631 2e38 ier/go-toml.v1.8
 7e576a 2e31 0968313a 314e6638 336f7270 726b .1.h1:1Nf83orprk
 7e577a 4a79 6b6e5436 68377a62 75454755 456a JyknT6h7zbuEGUEj
 7e578a 6379 566c4378 53554754 454e6d4e 4352 cyVlCxSUGTENmNCR
 7e579a 4d3d 0a646570 09676974 6875622e 636f M=.dep.github.co
 7e57aa 6d2f 706b672f 6572726f 72730976 302e m/pkg/errors.v0.
 7e57ba 392e 31090a64 65700967 69746875 622e 9.1..dep.github.
 7e57ca 636f 6d2f7370 6631332f 636f6272 6109 com/spf13/cobra.
 7e57da 7631 2e312e31 090a6465 70096769 7468 v1.1.1..dep.gith
 7e57ea 7562 2e636f6d 2f737066 31332f70 666c ub.com/spf13/pfl
 7e57fa 6167 0976312e 302e3509 0a646570 0967 ag.v1.0.5..dep.g
 7e580a 6f6c 616e672e 6f72672f 782f7379 7309 olang.org/x/sys.
 7e581a 7630 2e302e30 2d323032 31303132 3431 v0.0.0-202101241
 7e582a 3534 3534382d 32326461 36326531 3263 54548-22da62e12c
 7e583a 3063 0968313a 56777967 55726e77 396a 0c.h1:VwygUrnw9j
 7e584a 6e38 38633475 38474433 725a5162 7172 n88c4u8GD3rZQbqr
 7e585a 502f 74676173 38387450 55624278 5172 P/tgas88tPUbBxQr
 7e586a 6b3d 0a646570 09676f70 6b672e69 6e2f k=.dep.gopkg.in/
 7e587a 7961 6d6c2e76 32097632 2e322e38 090a yaml.v2.v2.2.8..
 7e588a 6465 7009676f 706b672e 696e2f79 616d dep.gopkg.in/yam
 7e589a 6c2e 76330976 332e302e 302d3230 3231 l.v3.v3.0.0-2021
 7e58aa 3031 30373139 32393232 2d343936 3534 0107192922-49654
 7e58ba 3561 36333037 62096831 3a683871 446f 5a6307b.h1:h8qDo
 7e58ca 7461 4550754a 4154724d 6d573034 4e43 taEPuJATrMmW04NC
 7e58da 7767 37763232 61484832 38777770 6175 wg7v22aHH28wwpau
 7e58ea 5568 4b394f6f 3d0a6465 70096b38 732e UhK9Oo=.dep.k8s.
 7e58fa 696f 2f617069 6d616368 696e6572 7909 io/apimachinery.
 7e590a 7630 2e32302e 32090a64 65700973 6967 v0.20.2..dep.sig
 7e591a 732e 6b38732e 696f2f79 616d6c09 7631 s.k8s.io/yaml.v1
 7e592a 2e32 2e30090a f9324331 86182072 0082 .2.0...2C1.. r..
 7e593a 4210 4116d8f2                        B.A...          

我们成功的拿到了其所依赖的 Modules 相关的信息,
这与我们在文章开头执行 go version -m ./bin/kind 是可以匹配上的,只不过这里的内容相当于是做了序列化。

具体实现

在前面的内容中,关于如何使用 readelf 和 objdump 命令获取二进制文件的的 Go 版本和 Module 信息就已经涉及到了其具体的原理。这里我来介绍下 Go 代码的实现。

节头的名称是硬编码在代码中的

//src/cmd/go/internal/version/exe.go#L106-L110
    for _, s := range x.f.Sections {
        if s.Name == ".go.buildinfo" {
            return s.Addr
        }
    }

同时,魔术字节也是通过如下定义:

var buildInfoMagic = []byte("\xff Go buildinf:")

获取 Version 和 Module 相关信息的逻辑如下,在前面的内容中也已经基本介绍过了,这里需要注意的也就是字节序相关的部分了。

    ptrSize := int(data[14])
    bigEndian := data[15] != 0
    var bo binary.ByteOrder
    if bigEndian {
        bo = binary.BigEndian
    } else {
        bo = binary.LittleEndian
    }
    var readPtr func([]byte) uint64
    if ptrSize == 4 {
        readPtr = func(b []byte) uint64 { return uint64(bo.Uint32(b)) }
    } else {
        readPtr = bo.Uint64
    }
    vers = readString(x, ptrSize, readPtr, readPtr(data[16:]))
    if vers == "" {
        return
    }
    mod = readString(x, ptrSize, readPtr, readPtr(data[16+ptrSize:]))
    if len(mod) >= 33 && mod[len(mod)-17] == '\n' {
        // Strip module framing.
        mod = mod[16 : len(mod)-16]
    } else {
        mod = ""
    }

总结

我在这篇文章中分享了如何从 Go 的二进制文件中获取构建它时所用的 Go 版本及它依赖的模块信息。如果对原理不感兴趣的话,直接通过 go version -m 二进制文件 即可获取相关的信息。

具体实现还是依赖于 ELF 文件格式中的相关信息,同时也介绍了 readelf 和 objdump 工具的基本使用,ELF 格式除了本文介绍的这种场景外,还有很多有趣的场景可用,比如为了安全进行逆向之类的。

另外,你可能会好奇从 Go 的二进制文件获取这些信息有什么作用。最直接的来说,可以用于安全漏洞扫描,比如检查其依赖项是否有安全漏洞;或是可以对依赖进行分析(主要指:接触不到源代码的场景下)会比较有用。


欢迎订阅我的文章公众号【MoeLove】

TheMoeLove

查看原文

赞 5 收藏 3 评论 2

张晋涛 发布了文章 · 1月7日

2020 小回顾 | 新晋程序员奶爸的云原生之路

一眨眼已经 2021 年了,虽然我每年也都会惯例的做个小回顾,但 2020 年对我意义更加不同。我打算换个方式来聊。

生活

很多人说 2020 年过于魔幻,这一年确实发生了很多事情,疫情、山火、蝗灾、洪水等。

而这一年对我来说意义更加非凡。正如我在去年的总结文分享的那样,我是在 2019 年和我的小可爱结婚的,2020 年我俩的宝宝出生啦!

我现在对那天仍记忆犹新。那天晚上我总觉得好像需要做点什么,但其实那种感觉也描述不出来。最终我是打开电脑看了几遍孕妇学校老师给的关于临产前准备工作视频后睡觉的。当时小可爱还笑我是不是太紧张了。凌晨时我们一起去了医院,经过小可爱的一番努力,从此我也就增加了新的角色, 成为了一名奶爸,谢谢我的小可爱!

有了孩子之后,生活自然也就不像之前了,很多时候要考虑孩子的情况,比如半夜需要哄他,每天为他洗澡之类的。等稍微大点之后好了不少,也变得更加有趣了。周末会带他去早教中心,其实主要就是带他去玩,能看见其他小朋友,跟其他小朋友打招呼之类的,每次他都很开心。

在作为“奶爸”这个角色上,我没有经验,也还在学习和摸索中。(很早以前我和几个好朋友一起聊过,是不是大家应该组群一起聊聊奶爸心得之类的,交流下经验~ 哈哈哈)

正如我 7 月份在接受思否社区访谈时说的那样, 思否有约丨张晋涛:一直在学习,包括更好的工作和如何成为合格的父亲。对于后者,这里我就不聊太多了,刚刚起步,以后的路还长着呢~

个人学习和成长

接下来就聊聊个人学习和成长相关的部分吧。

今年的主要研究方向仍然专注于容器运行时,Kubernetes 以及 Prometheus 等云原生相关的技术。

在容器运行时方面参与开源社区最多,Docker v20.10 也是我花时间精力最多的一个版本, 关于 Docker v20.10 相关的介绍请参考我之前的文章。在此过程中,我对 containerd, runc,firecracker 等技术也都在源码层有了更深的理解以及做了一些相关实践和尝试。

对于 Kubernetes 来说,今年代码提交方面表现一般。多数时间花在了理清其某些功能的设计及演进过程等方面,积累了一些奇奇怪怪的知识,如果大家感兴趣的话,以后我可以考虑写一些文章来聊聊,以及对 Kubernetes 一些周边技术进行了探索和实践。

至于 Prometheus 的话,有几篇规划中的文章没来得及写。反倒是给 Prometheus云原生监控: 运维与开发实战 这本书写了个推荐语。
同时 Prometheus 在我司也正逐步落地推进,但受资源和人力等因素的限制,远没达到我预期的效果,还有很长的路要走。
2021 年我计划要把它整体架构及周边基础设施完善下,希望能迈入一个新的阶段。

除此之外,还有一些值得记录的内容。

2020 年年初,更新完了我在 GitChat 上的专栏 Docker 核心知识必知必会 ,按照 GitChat 上的字数统计,这个专栏有将近 10w 字,涉及到了 Docker 原理的方方面面。从开始策划到全部更新完成,这期间一共换了 3 位编辑(前 2 位离职了),耗时半年,感谢各位编辑和读者们的支持!感谢我的小可爱催稿!让我终于能按时完稿。
更新专栏的那些天,要么是写到凌晨,要么是凌晨起床就开始写,感觉还是蛮辛苦的。但完稿之后,回头来看,好像也还好。果然一个人的上限是需要逼自己一下的。

此外,自 2019 年 3 月份开始,我也一直在更新着 「K8S 生态周报」 在 2020 年推送了 44 篇,中间有几篇断更,感谢各位新老读者朋友们的支持!未来会继续保持更新。

我的小可爱在 2020 年也开始了视频版的输出。小可爱比我要认真,视频版比文字版要详细的多,包括具体的操作演示之类的。此外,视频中也会有些彩蛋,喜欢看视频的小伙伴可以来一波关注~

除了「K8S 生态周报」外,2020 年我一共写了 15 篇博客,有个别几篇未公开,今年修改润色后会公开发布,此外也把博客重新整理了下,换了个主题,清爽了一些,欢迎大家访问 https://moelove.info/

image

2020 年另外的几件事情:

  • 收到了公司第一份非合同制的聘书 TM599

网易TM599聘书

上半年其实还有一个 RedHat 的 Open TestCon ,不过受疫情影响取消了。下半年基本保持每月 1 次的节奏。根据主办方数据和参会者的反馈来看,效果还不错,感谢大家的支持!这些分享的 PPT ,可以直接在我的 GitHub 仓库中下载

这几次分享,大家其实也可以看到,每次都是不一样的,有各自不同的侧重,包括容器化/Kubernetes,容器运行时,eBPF 等技术。 PS: 我坚信,近五年 eBPF 技术会有更大规模的生产实践,它也是一个很好的突破口。 除 Cilium 外,我也计划之后分享更多好玩和实用的 eBPF 实践,当然,我也计划在我司的环境中,做一些其他的尝试。

既然是年度的总结和回顾,我也来聊一些不那么满意和做的不好的地方吧。

就我个人而言,2020 年上半年有过一小段时间的迷茫,或者说“注意力分散”。各类技术层出不穷,更新也很频繁,唯有持续学习和跟进。关注太多东西,虽然能让自己保持敏锐的判断 & 更轻松的解决问题,然而个人精力有限,持续这样会分散很多注意力。

所以我主动的屏蔽掉了一些信息 & 对相关内容做了分级,将自己的注意力更好的集中在几个主要的领域内,其他内容周期性的回顾下,也未尝不可。这也就是我在开头提到的主要研究方向。

另一方面则是对团队/系统相关的,当前面临较大的问题是信息孤岛(information island),虽说信息孤岛是技术产业发展中不可避免的一个问题,但现在可能出现的早了点,也严重了点。导致了很多孤立的系统 & 信息闭塞。希望明年通过平台建设能改善一些这种问题。

flag

2019 年,在 GitChat 的访谈中 让我聊 2020 年容器的技术趋势。我当时的主要观点如下:

作为云原生技术的基石,Kubernetes 在 2020 年的热度将会持续上升。而各个公司的集群规模,以及对容器技术的推进都将会持续加大。在经历了初步容器化后,更多的公司将面临的问题是稳定性和性能优化问题。与此同时,service mesh,serverless 等技术也都会逐步得到普遍应用。
从底层次技术的角度来看,cgroups v2 将逐步普及,进而取代 cgroups v1,但这个过程可能需要两三年左右。
整体而言,稳定性和性能优化将会是未来的主旋律。

回过头来看,确实 2020 年 Kubernetes 热度是在持续上升。关于稳定性方面,看看 Chaos Engineering 去年在各公司 Kubernetes 中的相关实践,基本也得到印证。

至于性能优化,无论是阿里,腾讯,网易等各家也都对外公开分享了基于 eBPF 等技术的相关优化和实践,这点也没问题。

cgroups v2 2020 年无论是 runc, containerd, Docker 等均已经增加了相关的支持,也基本得到了印证。

唯一没有提到的,可能是安全性相关的部分。 在 2020 年,Kubernetes/容器化技术方面的安全性,也进一步得到了重视。(这和各种前期没有太在意的安全漏洞被发现也有很大关系)。

再来看看年初立的 flag 吧:

  • 工作方面希望能推动更多业务的改造和接入,算是个长线计划;
  • 社区活动方面,今年希望多参与一些,把一些理念和实践经验 push 到社区,也能从中学习到社区的一些经验;
  • 社区贡献方面,会继续投入更多精力来做,但与 2019 年的重点可能会稍有不同;
  • 生活方面,希望宝宝健康的出生,和我的小可爱共同经营好我们的家庭。

基本符合预期。工作方面业务方和同事们都比较配合,推进也较为顺利。社区活动方面,谢谢每个参与者!生活方面,谢谢我的小可爱!感谢每个家人!

惯例贴一张图:

image

至于 2021 年的小目标,这次就不写了。愿:平安喜乐!

还有文章前的你,感谢你的关注和支持,希望我们能各有收获!


欢迎订阅我的文章公众号【MoeLove】

本文参与了 SegmentFault 思否征文「2020 总结」,欢迎正在阅读的你也加入。
查看原文

赞 4 收藏 0 评论 0

张晋涛 发布了文章 · 1月1日

K8S 生态周报| 年终大放送!Docker v20.10

「K8S 生态周报」内容主要包含我所接触到的 K8S 生态相关的每周值得推荐的一些信息。欢迎订阅知乎专栏「k8s生态」

Docker v20.10 主要特性一览

在之前的 K8S 生态周报| Docker v20.10.0-beta1 发布 一文中,我曾为你介绍过 Docker v20.10.0-beta1 发布相关的信息,但是并没有具体介绍 Docker v20.10 版本的具体功能特性等细节。

Docker v20.10 版本,变化非常的大。提供了 CGroup v2 的支持,增强了 rootless 模式的支持,双栈日志,更灵活的内置 DNS 等,我在这个版本中也花费了很多时间。

详细的变更,我会在 v20.10 正式发布后再进行介绍。欢迎大家进行测试和反馈,目前已经收到了一些反馈的建议。我们会尽快修正并发布下个版本。

正如我当时承诺的那样,作为 2020 年最后一篇周报,我来在本篇周报中详细介绍下 Docker v20.10 版本。

安装

Docker v20.10 发布于 2020 年 12 月 8 日,是自 Docker v19.03 (2019 年 7 月)后发布的首个大版本。你可以直接通过以下命令来自动化的安装 Docker v20.10。

➜  ~ curl -fsSL https://get.docker.com |sh

cgroup v2 支持

Docker v19.03 是没有 cgroup v2 支持的,但自从 Fedora 31 开始,这成为了 Fedora 上的默认 cgroup 版本。在 Docker v20.10 发布之前,Fedora 31 及以上用户,需要将系统的 cgroup 设置为 v1 才能正常运行 Docker 。

其实这里面涉及到了大量的修改,包括 runc, containerd 直到 Docker 都添加了 cgroup v2 的支持,此功能才能真正给用户使用。

在此过程中,我也发现了 runc v1.0-rc91 中隐藏的 bug ,会导致 Docker 无法正常通过增加 --privileged 参数以特权模式运行容器。后来对 runc 进行了修改,发布了 runc v1.0-rc92 ,至此才使得 Docker 中的 cgroup v2 特性得以顺利完成。

关于此处更详细的内容,我在 《K8S 生态周报| runc v1.0-rc92 发布》 中已做了详细介绍,感兴趣的小伙伴可以看看。

rootless mode GA

Docker 有个一直被人诟病的点,就在于 docker daemon 必须是以 root 权限来启动,这样才可以使用它的全部特性。这也就意味着,凡是可以操作 docker daemon 的用户,也就有机会获取操作系统的 root 权限。

我们在 Docker v19.03 版本中提供了实验性的 rootless mode 的支持,允许用户无需 root 权限即可运行 docker daemon 。这大大提升了系统的安全性。但当时还处于实验阶段,有部分功能缺失。

我想趁此次 Docker v20.10 发布,正式为你介绍下 Docker 的 rootless mode ,并且,它已经达到 GA 从实验性毕业了,并且也提供了很多功能。

rootless mode 是在用户名称空间中运行 docker daemon 和容器,完全不需要 root 权限。

你可以通过以下命令安装 Docker rootless 模式:

➜  ~ curl -fsSL https://get.docker.com/rootless | sh

或者直接通过 Docker 官方的 RPM/DEB 包进行安装。安装完之后,通过 systemctl 管理 Docker 服务即可。

➜  ~ systemctl --user start docker

更多关于 rootless mode 的详细用法及最佳实践,请参考 Docker 官方文档:以非 root 用户运行 docker daemon

Dockerfile: RUN --mount=type=(ssh|secret|cache) 等特性达到 GA

Docker v18.06 开始实验性的添加了 RUN --mount=type=cache 该特性可用于在构建过程中,保留包管理器的缓存文件。

之后在 v18.09 中又增加了 RUN --mount=type=sshRUN --mount=type=secret 用于在构建过程中,传递密钥或者用户凭证等私密信息,以防止泄漏等。这些高级特性,在我之前的文章 《进阶:Dockerfile 高阶使用指南及镜像优化》 曾详细介绍过。

这些特性非常有用,基本涵盖了你构建镜像时关于安全性方面的绝大多数的需求。大家如果感兴趣,欢迎随时与我交流,后续我也可能会再写相关的文章进行介绍。

其他

  • 此次还优化了内置 DNS 相关的逻辑,可以提供更好的性能;
  • docker build 可支持直接 ssh 远程构建私有仓库的镜像了;

更多关于此版本的变更,可以参考其 ReleaseNote

Rook v1.5.4 发布

关于此版本有两个格外需要注意的信息:

  • #6849 最新版的 Ceph 不支持使用分区的 OSD 了。就我个人经验,我倒是基本没有把 OSD 装到过某个分区中,一般都直接使用整块盘;
  • #6769 Ceph-CSI 默认更新到了 v3.2.0;

更多关于此版本的信息,请参考其 ReleaseNote

etcd 从 CNCF 正式毕业

etcd 想必大家不会陌生,我在「K8S 生态周报」中也曾多次介绍它,这里就不再赘述了。

感兴趣的小伙伴可查看官方公告: CNCF 宣布 etcd 正式毕业

再次恭喜 etcd !

题外话

今年是 2020 年阳历的最后一天了, 感谢大家的关注和支持!

接下来,我将会发布一份 “2020 年 K8S 生态演进报告” 与你分享在 2020 年 K8S 生态相关不容错误的信息,以及 2021 年 K8S 生态相关的展望及发展方向,敬请期待!


欢迎订阅我的文章公众号【MoeLove】

TheMoeLove

查看原文

赞 3 收藏 1 评论 0

张晋涛 发布了文章 · 2020-12-24

Docker 新发布的 hub-tool 可直接查看账户配额

Docker Desktop v3.0 已于前两周正式发布,从这个版本起,Docker 官方承诺每次的更新将以增量更新的方式来提供,以便减少下载包的体积,提升效率。

除了将 Docker Engine 更新至 v20.10.0 外,也对其他的依赖做了更新,如下图:

image

最吸引我的是本次新增的 Docker Hub Tool v0.2.0 ,它是 Docker 官方提供的 Docker Hub CLI 工具,具备管理 DockerHub 上的帐号,镜像等相关资源的能力。

以下,我来为你介绍下 Hub Tool 的主要功能。

(MoeLove) ➜  hub-tool -h
A tool to manage your Docker Hub images

Usage:
  hub-tool
  hub-tool [command]

Available Commands:
  account     Manage your account
  help        Help about any command
  login       Login to the Hub
  logout      Logout of the Hub
  org         Manage organizations
  repo        Manage repositories
  tag         Manage tags
  token       Manage Personal Access Tokens
  version     Version information about this tool

Flags:
  -h, --help      help for hub-tool
      --verbose   Print logs
      --version   Display the version of this tool

Use "hub-tool [command] --help" for more information about a command.

从一级菜单来看,主要功能包括:

  • 登录/登出 DockerHub;
  • 账户相关管理功能;
  • 组织相关管理功能;
  • 仓库和 tag 的相关管理功能;
  • token 的相关管理功能;

当前我使用的是最新版本 v0.2.0 。

(MoeLove) ➜  hub-tool version
Version:    v0.2.0
Git commit: 0edf43ac9091e7cac892cbc4cbc6efbafb665aa4

登录/退出

登录/退出只要执行 hub-tool login 或者 hub-tool logout 即可。

但这里需要注意的是 Hub Tool 并没有使用 Docker Desktop 默认的用户凭证,也就是说,即使你在 Docker Desktop 中已经登录了帐号,你同样还是需要再次在终端下执行 login 操作。

关于为何没有共用用户凭证的问题,我跟 Docker Inc. 的产品经理聊过,是因为当前 Hub Tool 还是一个独立的 CLI 工具,并没有与 docker CLI 进行集成,也暂时没想好要如何集成。等真正要集成进 docker CLI 的时候,就会直接共用用户凭证了。

(MoeLove) ➜  hub-tool login
Username: moelove
Password:

账户管理

账户管理的两个功能:

  • 查看账户信息;
  • 查看当前账户下的流量限制 , 这是我个人觉得比较有用的一个功能;
(MoeLove) ➜  hub-tool account
Manage your account

Usage:
  hub-tool account
  hub-tool account [command]

Available Commands:
  info          Print the account information
  rate-limiting Print the rate limiting information

Flags:
  -h, --help   help for account

Global Flags:
      --verbose   Print logs

Use "hub-tool account [command] --help" for more information about a command.
(MoeLove) ➜  hub-tool account rate-limiting
Limit:     200, 6 hours window
Remaining: 200, 6 hours window
(MoeLove) ➜  hub-tool account info
Username:    moelove.info
Full name:    Jintao Zhang
Company:
Location:
Joined:        6 years ago
Plan:        free
Limits:
  Seats:        1
  Private repositories:    1
  Parallel builds:    1
  Collaborators:    unlimited
  Teams:        unlimited

组织管理

可以看到,hub-tool org 的功能就是展示一些相关信息了。

(MoeLove) ➜  hub-tool org
Manage organizations

Usage:
  hub-tool org
  hub-tool org [command]

Available Commands:
  ls          List all the organizations
  members     List all the members in an organization
  teams       List all the teams in an organization

Flags:
  -h, --help   help for org

Global Flags:
      --verbose   Print logs

Use "hub-tool org [command] --help" for more information about a command.
(MoeLove) ➜  hub-tool org ls
NAMESPACE    NAME    MY ROLE    TEAMS    MEMBERS

仓库和 tag 管理

由于这两个都和镜像有直接的关系,我就聚合到一起介绍了。

  • 对 repo 的查询和删除功能:
(MoeLove) ➜  hub-tool repo -h
Manage repositories

Usage:
  hub-tool repo
  hub-tool repo [command]

Available Commands:
  ls          List all the repositories from your account or an organization
  rm          Delete a repository

Flags:
  -h, --help   help for repo

Global Flags:
      --verbose   Print logs

Use "hub-tool repo [command] --help" for more information about a command.
(MoeLove) ➜  hub-tool repo ls
REPOSITORY                             DESCRIPTION       LAST UPDATE      PULLS    STARS    PRIVATE
taobeier/saythx-work                                     2 years ago      56989    0        false
...
(MoeLove) ➜  hub-tool repo ls -h
List all the repositories from your account or an organization

Usage:
  hub-tool repo ls [ORGANIZATION]

Aliases:
  ls, list

Flags:
      --all             Fetch all available repositories
      --format string   Print values using a custom format ("json")
  -h, --help            help for ls

Global Flags:
      --verbose   Print logs
  • 对 tag 的列表,查询,查看详细等功能。 这里 可以看到 tag 最近一次的 Push/Pull 操作,如果明年 Docker 开始实行镜像保留策略的话,我建议你关注一下
(MoeLove) ➜  hub-tool tag
Manage tags

Usage:
  hub-tool tag [flags]
  hub-tool tag [command]

Available Commands:
  inspect     Show the details of an image in the registry
  ls          List all the images in a repository
  rm          Delete a tag in a repository

Flags:
  -h, --help   help for tag

Global Flags:
      --verbose   Print logs

Use "hub-tool tag [command] --help" for more information about a command.
See 'hub-tool tag ls --help'.

Usage:  hub-tool tag ls [OPTION] REPOSITORY

List all the images in a repository
(MoeLove) ➜  hub-tool tag ls taobeier/saythx-work
TAG                            DIGEST                                                                     STATUS    LAST UPDATE    LAST PUSHED    LAST PULLED    SIZE
taobeier/saythx-work:latest    sha256:3133a607d062dd3a8b46f38c8271099c258f5e59cecd652bebddf6e15789cb32    active    2 years ago    2 years        6 days         52.94MB
taobeier/saythx-work:1.0       sha256:3133a607d062dd3a8b46f38c8271099c258f5e59cecd652bebddf6e15789cb32    active    2 years ago    2 years        6 days         52.94MB

Token 相关管理功能

对个人 Token 的创建/删除,激活/失效,列表,查询详细等功能。

(MoeLove) ➜  hub-tool token -h
Manage Personal Access Tokens

Usage:
  hub-tool token [flags]
  hub-tool token [command]

Available Commands:
  activate    Activate a Personal Access Token
  create      Create a Personal Access Token
  deactivate  Deactivate a Personal Access Token
  inspect     Inspect a Personal Access Token
  ls          List all the Personal Access Tokens
  rm          Delete a Personal Access Token

Flags:
  -h, --help   help for token

Global Flags:
      --verbose   Print logs

Use "hub-tool token [command] --help" for more information about a command.
(MoeLove) ➜  hub-tool token ls
DESCRIPTION               UUID                                    LAST USED       CREATED      ACTIVE
test-docker-token         xxxxxxxx-xxxx-xxxx-xxxx-moelove.info    9 months ago    9 months     true
(MoeLove) ➜  hub-tool token inspect xxxxxxxx-xxxx-xxxx-xxxx-moelove.info
Token:
UUID:    xxxxxxxx-xxxx-xxxx-xxxx-moelove.info
Description:    test-docker-token
Is Active:    true
Created:    9 months ago
Last Used:    9 months ago
Creator User Agent:    Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.4103.116 Safari/537.36
Creator IP:    100.000.000.00
Generated:    By user via Web UI

总结

以上就是关于 Docker 新发布的 Hub Tool 的全部功能介绍了。
当前它是随着 Docker Desktop 一起发行的,所以 Linux 下暂时没有。但是计划会尽快开源。敬请期待!


欢迎订阅我的文章公众号【MoeLove】

TheMoeLove

查看原文

赞 3 收藏 0 评论 0

张晋涛 关注了标签 · 2020-12-19

golang

Go语言是谷歌2009发布的第二款开源编程语言。Go语言专门针对多处理器系统应用程序的编程进行了优化,使用Go编译的程序可以媲美C或C++代码的速度,而且更加安全、支持并行进程。
Go语言是谷歌推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性。谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发Go,是因为过去10多年间软件开发的难度令人沮丧。Go是谷歌2009发布的第二款编程语言。

七牛云存储CEO许式伟出版《Go语言编程
go语言翻译项目 http://code.google.com/p/gola...
《go编程导读》 http://code.google.com/p/ac-m...
golang的官方文档 http://golang.org/doc/docs.html
golang windows上安装 http://code.google.com/p/gomi...

关注 26183

张晋涛 发布了文章 · 2020-12-19

Go 1.16 中关于 go get 和 go install 你需要注意的地方

Go (golang) 已于 18 日发布了 1.16 beta1 版本,至此其主体功能已经基本确定。我看大多数人都在关注 Go 在苹果(Apple) M1 上的支持,甚至 Go 官方博客中也有一篇专门的说明 Go on ARM and Beyond ,来介绍 Go 在此方面的支持。

我就不凑热闹了,我来聊聊 Go 1.16 中关于 go getgo install 你需要注意的地方。

目前 Docker 官方镜像尚未发布,我是本地构建了个镜像来使用。

(MoeLove) ➜  go version
go version go1.16beta1 linux/amd64

概览

Go 1.16 中包含着大量的 Modules 相关的更新,详细内容可直接查看其 Release Note。整体而言,包含以下要点:

  • GO111MODULE 默认为 on ,如果要恢复到之前的行为,则需要将 GO111MODULE 设置为 auto ,这样差不多意味着 GOPATH 模式要逐步淡出人们的视野了;
  • go install 命令可以接受一个版本后缀了,(例如,go install sigs.k8s.io/kind@v0.9.0),并且它是在模块感知的模式下运行,可忽略当前目录或上层目录的 go.mod 文件。这对于在不影响主模块依赖的情况下,安装二进制很方便;
  • 在将来,go install 被设计为“用于构建和安装二进制文件”, go get 则被设计为 “用于编辑 go.mod 变更依赖”,并且使用时,应该与 -d 参数共用,在将来版本中 -d 可能会默认启用;
  • go buildgo test 默认情况下不再修改 go.modgo.sum。可通过 go mod tidygo get 或者手动完成;

总结而言,关于 go installgo get 必须要注意的是:

  • 基本上 go install <package>@<version> 是用于命令的全局安装:

    • 例如:go install sigs.k8s.io/kind@v0.9.0;
  • go get 安装二进制的功能,后续版本将会删除;
  • go get 主要被设计为修改 go.mod 追加依赖之类的,但还存在类似 go mod tidy 之类的命令,所以使用频率可能不会很高;

Go 1.16 中已解决的工具安装问题

到目前为止,Go 一直使用 go get 命令,将我们需要的工具安装到 $GOPATH/bin 目录下,但这种方式存在一个很严重的问题。go get 由于具备更改 go.mod 文件的能力,因此我们 必须要避免执行 go get 命令时,让它接触到我们的 go.mod 文件 ,否则它会将我们安装的工具作为一个依赖。

目前的解决方案通常是:

(MoeLove) ➜  cd $(mktemp -d); GO111MODULE=on go get sigs.k8s.io/kind@v0.9.0

自 1.16 开始,我们可以直接使用下面的方式:

(MoeLove) ➜  go install sigs.k8s.io/kind@v0.9.0

非常的简单直观。需要注意的是 go install <package>@<version> 是从 1.16 开始增加的,无论你当前是否在一个模块下,此命令都会在 $GOPATH/bin 下安装指定版本的工具。

此外由于 Go 1.16 中 GO111MODULE 默认是打开的,go install 不会修改 go.mod 之类的文件,不会造成任何意外。

注意:

@version 只能安装主软件包。非主程序包不受此格式约束。

关于不带 @versiongo install

  • 在模块外,不带 @version 是无法安装的,会有如下错误:
(MoeLove) ➜  go install  -v sigs.k8s.io/kind
go install: version is required when current directory is not in a module
        Try 'go install sigs.k8s.io/kind@latest' to install the latest version
  • 如果你在模块目录中,并且你不带 @version 执行安装的话,只能安装 go.mod 中已经包含的版本。并且不能安装未出现在 go.mod 中的包。
(MoeLove) ➜  mkdir -p /go/src/github.com/moelove/iris
(MoeLove) ➜  cd /go/src/github.com/moelove/iris
# 初始化模块
(MoeLove) ➜  /go/src/github.com/moelove/iris go mod init
go: creating new go.mod: module github.com/moelove/iris
(MoeLove) ➜  /go/src/github.com/moelove/iris cat go.mod 
module github.com/moelove/iris

go 1.16


# 不带 @version 无法安装
(MoeLove) ➜  /go/src/github.com/moelove/iris go install -v sigs.k8s.io/kind
no required module provides package sigs.k8s.io/kind; try 'go get -d sigs.k8s.io/kind' to add it

# 用 go get -d 下载
(MoeLove) ➜  /go/src/github.com/moelove/iris go get -d sigs.k8s.io/kind
go get: added sigs.k8s.io/kind v0.9.0

# 可以看到已经被添加到了模块依赖中
(MoeLove) ➜  /go/src/github.com/moelove/iris cat go.mod 
module github.com/moelove/iris

go 1.16

require sigs.k8s.io/kind v0.9.0 // indirect

# 删除本地的 kind 工具
(MoeLove) ➜  /go/src/github.com/moelove/iris which kind
/go/bin/kind
(MoeLove) ➜  /go/src/github.com/moelove/iris rm /go/bin/kind
(MoeLove) ➜  /go/src/github.com/moelove/iris which kind

# 不带 @version 进行安装
(MoeLove) ➜  /go/src/github.com/moelove/iris go install -v sigs.k8s.io/kind
(MoeLove) ➜  /go/src/github.com/moelove/iris which kind
/go/bin/kind
(MoeLove) ➜  /go/src/github.com/moelove/iris kind version
kind v0.9.0 go1.16beta1 linux/amd64

关于 go getgo.mod

go get 将二进制安装相关的功能都转移到了 go install, 仅作为用于编辑 go.mod 文件的命令存在。在后续版本(计划是 Go 1.17)中删掉 go get 安装二进制的功能,接下来 go get 的行为就等同于我们现在执行 go get -d 命令了,仅需下载源码,并将依赖添加至 go.mod 即可。

go.mod 如何编辑

在 Go 1.16 中,另一个行为变更是 go buildgo test 不会自动编辑 go.mod 了,基于以上信息,Go 1.16 中将进行如下处理:

  • 通过在代码中修改 import 语句,来修改 go.mod

    • go get 可用于添加新模块;
    • go mod tidy 删除掉无用的模块;
  • 将未导入的模块写入 go.mod:

    • go get <package>[@<version>];
    • go mod tidy 也可以;
    • 手动编辑;

从 1.15 升级需要注意什么?

由于 go buildgo test 不会自动编辑 go.mod 了,所以可以将原本的行为通过 go mod tidy 共同处理。

总结

Go 1.16 中 go installgo get 方面有些不兼容的变更,但是 1.16 中模块更加简洁,减少了使用时的心智负担,我还是很期待这个版本的。


欢迎订阅我的文章公众号【MoeLove】

TheMoeLove

查看原文

赞 6 收藏 1 评论 0

张晋涛 报名了系列讲座 · 2020-12-18

PyCon China 2020 中国 Python 开发者大会

2020 年是一个特殊的年份,新冠肺炎蔓延全球, 影响着整个人类,但我们众志成城、共克时艰,即使生活再难,对生活和技术的热爱不减。 2020 年是 PyCon China 的十周年,一路走来,风雨兼程。我们希望在这个特殊的年份继续举办这样一场特殊的技术峰会,用我们技术人的知识和力量来一起走下去 由于疫情原因,本届 PyCon China 将采用议题线上分享+北京,上海,深圳线下沙龙的组合方式进行举办,以最大程度减少健康风险,同时为讲师们保留彼此深入交流的机会。 **线下举办城市: 北京,上海,深圳** **线上:SegmentFault 思否直播** * * * ### 活动议程 **上海站** **![分城市城市日程--上海2的副本.jpg](http://cdn.huodongxing.com/file/ue/20150418/113E37A9724FB21723696DBEF99AF84AA1/30863981874507064.jpg "分城市城市日程--上海2的副本.jpg")** * * * **北京站** ![分城市城市日程--北京的副本.jpg](http://cdn.huodongxing.com/file/ue/20150418/113E37A9724FB21723696DBEF99AF84AA1/30553981874807093.jpg "分城市城市日程--北京的副本.jpg") * * * **深圳站** ![分城市城市日程--深圳的副本.jpg](http://cdn.huodongxing.com/file/ue/20150418/113E37A9724FB21723696DBEF99AF84AA1/30693981874977105.jpg "分城市城市日程--深圳的副本.jpg") * * * ### 大会合作伙伴 ![合作伙伴.jpg](http://cdn.huodongxing.com/file/ue/20150418/113E37A9724FB21723696DBEF99AF84AA1/30193981876287186.jpg "合作伙伴.jpg") * * * ### PyCon China 2019 精彩回顾  2019 年,是 Python 诞生 30 周年,值此三十周年之际,第九届中国 Python 开发者大会 PyCon China 2019 顺利举办。大会于 9 月 21 日在主会场上海站正式开启,并相继在北京、杭州、深圳、成都、南宁等五个城市联动举办,为全国各地的 Pythonista 献上了一场精彩的 Python 盛会。 PyCon China 2019 大咖云集,除了国内大牛之外,还有来自美国、澳大利亚、日本、巴西、加拿大、意大利、奥地利等国家的大咖加入,在六个城市共邀请了 100 多位来自国内外的资深 Pythonista,为大家带来了 60+主题演讲以及 20+闪电演讲。内容覆盖 Python 语言特性、Web 应用、人工智能/大数据、Python 基础架构及创新领域开发等多个 Python 技术领域,共有 2000+ Python 爱好者到场参会,来自全国的 200 余位志愿者参与了大会的志愿工作。本次大会图文直播阅读量 37513 次,关注活动报名页面计 67474 次,浏览官方网页高达 14058 人次,是一次全新的 Python 盛会! #### PyCon China 2019 上海站 ![微信图片_20201120151033.jpg](https://live-static.segmentfault.com/730/074/730074695-5fb76bfd72d7f) **【上海站】作为 PyCon China 2019 的主会场**,我们邀请了 40 多位来自国内外的资深 Pythonista,同我们的合作伙伴以及现场近千位参会者朋友们一起,通过上午峰会主会场以及下午七个分会场的形式,共同庆祝 Python 三十周年这个伟大的时刻。 本届中国 Python 开发者大会特别引入**闪电演讲**(Lightning Talk),通过限时、快速的演讲,为大家带来全新体验。 #### PyCon China 2019 北京/杭州/深圳/成都/南宁站 北京、杭州、深圳、成都、南宁分别由各地 Python 爱好者承办,组委会尽全力为各地城市的举办提供讲师、资金、物料的资源支持。PyCon China 城市站与现场参会者擦出了别样的“爱情火花”,为来自各个领域的 Pythonista 们带来了一场精彩的分享盛宴。 ![微信图片_20201120151132.jpg](https://live-static.segmentfault.com/133/585/133585574-5fb76c5421d40) ![微信图片_20201120151127.png](https://live-static.segmentfault.com/743/080/743080716-5fb76c64eb44c)

张晋涛 发布了文章 · 2020-12-09

K8S 弃用 Docker 了?Docker 不能用了?别逗了!

Docker 大概没想到,2020 年,它在技术圈内的两次成为(舆论的)焦点,竟然都是因为信息差(说是“标题党”也不为过)。

概览

2013 年

Docker 是在 2013 年的 PyCon 上首次正式对外公布的。
它带来了一种先进的软件交付方式,即,通过容器镜像进行软件的交付。
工程师们只需要简单的 docker build 命令即可制作出自己的镜像,并通过 docker push 将其发布至 DockerHub 上。
通过简单的 docker run 命令即可快速的使用指定镜像启动自己的服务。

通过这种办法,可以有效的解决软件运行时环境差异带来的问题,达到其 Build once, Run anywhere 的目标。

从此 Docker 也基本成为了容器的代名词,并成为容器时代的引领者。

2014 年

2014 年 Google 推出 Kubernetes 用于解决大规模场景下 Docker 容器编排的问题。

这是一个逻辑选择,在当时 Docker 是最流行也是唯一的运行时。 Kubernetes 通过对 Docker 容器运行时的支持,迎来了大量的用户。

同时,Google 及 Kubernetes 社区与 Docker 也在进行着密切的合作,在其官方博客上有如下内容:

We’ll continue to build out the feature set, while collaborating with the Docker community to incorporate the best ideas from Kubernetes into Docker.

An update on container support on Google Cloud Platform

Kubernetes is an open source manager for Docker containers, based on Google’s years of experience using containers at Internet scale.
Docker is delivering the full container stack that Kubernetes schedules into, and is looking to move critical capabilities upstream and align the Kubernetes framework with Libswarm.

Welcome Microsoft, RedHat, IBM, Docker and more to the Kubernetes community

并在同一个月的 DockerCon 上发布演讲,介绍了 Kubernetes 并受到了广泛的关注。

此时 Docker Inc. 也发布了其容器编排工具, libswarm (也就是后来的 swarmkit) 。

2015 年

2015 年 OCI (Open Container Initiative)由 Docker 和其他容器行业领导者共同成立(它也是 Linux 基金会旗下项目)

OCI 主要包含两个规范:

  • 运行时规范(runtime-spec):容器运行时,如何运行指定的 文件系统上的包
  • 容器镜像规范(image-spec):如何创建一个 OCI 运行时可运行的文件系统上的包

Docker 把它自己的容器镜像格式和 runtime ( 现在的 runc ) 都捐给了 OCI 作为初始工作。

2016 年

2016 年 6 月,Docker v1.12 发布,带来了 Docker 在多主机多容器的编排解决方案,Docker Swarm 。
这里也需要注意的是,Docker v1.12 的设计原则:

  • Simple Yet Powerful (简单而强大)
  • Resilient(弹性)
  • Secure(安全)
  • Optional Features and Backward Compatibility(可选功能及向后兼容)

所以你可以通过配置自行选择是否需要使用 Docker Swarm ,而无需担心有什么副作用。

2016 年 12 月, Kubernetes 发布 CRI (Container Runtime Interface) ,这当中一部分原因是由于 Kubernetes 尝试支持另一个由 CoreOS 领导的容器运行时项目 rkt ,但是需要写很多兼容的代码之类的,为了避免后续兼容其他运行时带来的维护工作,所以发布了统一的 CRI 接口,凡是支持 CRI 的运行时,皆可直接作为 Kubernetes 的底层运行时;

当然, Kubernetes 也是在 2016 年逐步取得那场容器编排战争的胜利的。

2017 年

2017 年, Docker 将自身从 v1.11 起开始引入的容器运行时 containerd 捐给了 CNCF

2017 年,Docker 的网络组件 libnetwork 增加了 CNI 的支持;
同时通过使用 Docker 为 Docker Swarm 提供的 ipvs 相关的代码,也在 Kubernetes 中实现了基于 IPvs 的 service 负载均衡。不过在 v1.18 中开始移除了相关的依赖。

同年 11 月,Kubernetes 中新增了 containerd 的支持

image

2018 年

2018 年, Kubernetes 的 containerd 集成,正式 GA

之前版本的架构:

image

新的架构:
image

2019 年

2019 年,上文中提到的另一个容器运行时项目 rkt 被 CNCF 归档,终止使命了;
2019 年 Mirantis 收购 Docker 的企业服务。

2020 年

时间回到今年,Docker 主要被误会的两件事:

  • Docker Inc. 修改 DockerHub 的定价和 TOS 。国内争论较多的主要是关于合规性的问题(但是被标题党带歪了,免不了恐慌);
  • Kubernetes 宣布开始进入废弃 dockershim 支持的倒计时,被人误以为 Docker 不能再用了;

说明

关于 DockerHub 修改定价和 TOS 的事情,这里就不再多说了,毕竟 DockerHub 目前大家仍然用的很欢乐,远不像当初那些标题党宣称的那样。

重点来说一下第二件事情吧。

Kubernetes 当初选择 Docker 作为其容器运行时,本身就是因为当时它没有其他的选择,并且选择 Docker 可为它带来众多的用户。
所以,开始时,它便提供了内置的对 Docker 运行时的支持。

而 Docker 其实创建之初,并没有考虑到“编排”的这个功能,当然也没有考虑到 Kubernetes 的存在(因为当时还没有)。

dockershim 一直都是 Kubernetes 社区为了能让 Docker 成为其支持的容器运行时,所维护的一个兼容程序。 本次所谓的废弃,也仅仅是 Kubernetes 要放弃对现在 Kubernetes 代码仓库中的 dockershim 的维护支持。 以便其可以像开始时计划的那样,仅负责维护其 CRI ,任何兼容 CRI 的运行时,皆可作为 Kubernetes 的 runtime 。

在 Kubernetes 提出 CRI 时,有人建议在 Docker 中实现它。但是这种方式也会带来一个问题,即使 Docker 实现了 CRI,但它仍然不是一个单纯的容器运行时,它本身包含了大量的非 “纯底层容器运行时” 所具备的功能。

所以后来 自 Docker 中分离出来的 containerd 项目,作为一个底层容器运行时出现了,它是 Kubernetes 容器运行时更好的选择。

Docker 使用 containerd 作为其底层容器运行时以及众多的云厂商及公司在生产环境中使用 containerd 作为其 Kubernetes 的运行时,这也从侧面验证了 containerd 的稳定性。

现在 Kubernetes 和 Docker 社区都相信 containerd 已经足够成熟可直接作为 Kubernetes 的运行时了,而无需再通过 dockershim 使用 Docker 作为 Kubernetes 的运行时了。这也标志着 Docker 为 Kubernetes 提供一个现代化的容器运行时的承诺最终兑现了。

而本次事件中,重点的 dockershim 之后的方向如何呢?Kubernetes 代码仓库中的 dockershim 将会在未来版本中移除,但是 Mirantis 公司已经和 Docker 达成合作,在未来会共同维护一份 dockershim 组件,以便支持 Docker 作为 Kubernetes 的容器运行时。

Otherwise, if you’re using the open source Docker Engine, the dockershim project will be available as an open source component, and you will be able to continue to use it with Kubernetes; it will just require a small configuration change, which we will document.

Mirantis 公司宣布将维护 dockershim

Q&A

Q:本次 Kubernetes 放弃对 dockershim 的维护,到底有什么影响?
A:对于普通用户而言,没有任何影响;对于在 Kubernetes 之上进行开发的工程师,没什么太大影响;对于集群管理员,需要考虑是否要在未来版本中,将容器运行时,升级为支持 CRI 的运行时,比如 containerd 。
当然,如果你并不想切换容器运行时,那也没关系,Mirantis 公司未来会和 Docker 共同维护 dockershim , 并作为一个开源组件提供。

Q: Docker 不能用了吗?
A:Docker 仍然是本地开发,或者单机部署最佳的容器工具,它提供了更为人性化的用户体验,并且也有丰富的特性。目前 Docker 已经和 AWS 达成合作,可直接通过 Docker CLI 与 AWS 集成。另外,Docker 也仍然可以作为 Kubernetes 的容器运行时,并没有立即中止对其支持。

Q:听说 Podman 可以借机上位了?
A:想太多。Podman 也并不兼容 CRI ,并且它也不具备作为 Kubernetes 容器运行时的条件。我个人也偶尔有在用 Podman, 并且我们在 KIND 项目中也提供了对 Podman 的支持, 但实话讲,它也就是只是一个 CLI 工具,某些情况下会有些作用,比如如果你的 Kubernetes 容器运行时使用 cri-o 的情况下,可以用来本地做下调试。

总结

本文主要介绍了 Docker 和 Kubernetes 的发展历程,也解释了本次 Kubernetes 仅仅是放弃其对 dockershim 组件的支持。未来更推荐的 Kubernetes 运行时是 兼容 CRI 的 containerd 之类的底层运行时。

Mirantis 公司将会和 Docker 共同维护 dockershim 并作为开源组件提供。

Docker 仍然是一款最佳的本地开发测试和部署的工具。


欢迎订阅我的文章公众号【MoeLove】

image

查看原文

赞 10 收藏 5 评论 0

张晋涛 发布了文章 · 2020-10-31

K8S 生态周报| Istio v1.7.1 发布

「K8S 生态周报」内容主要包含我所接触到的 K8S 生态相关的每周值得推荐的一些信息。欢迎订阅知乎专栏「k8s生态」

Istio v1.7.1 发布

这是 Istio v1.7 系列的第一个 patch 版本。此次更新有些值得注意的内容:

  • #26625 修复了 istioctl x authz check 使其能更好的兼容 v1beta1 AuthorizationPolicy ;
  • #26617 修复了 headless services endpoint 更新不会触发任何 xds pushes 的问题;
  • ##26938 修复了当使用 IstioCNIremove-from-mesh 未移除 init container 的问题;

Rook v1.4.3 发布

这是个 patch 版本,主要修复了一些和 Ceph 有关的问题, 以及引入了一些小功能:

修复:

  • #6232 由于 Ceph-CSI driver 在某些集群中会把垃圾回收清理掉,所以创建 csidriver 对象时不再为它设置 ownerRef 了。主要是因为 csidriver 是集群级别的对象,不应该将 namespace 级别的对象设置为它的 ownerRef

修改:

  • #6225 为 OSD pod 添加 storageClassDeviceSet 标签
  • #6145 为 Ceph 集群增加 uninstall 模式,如果 UninstallMode CR spec 设置为 yes-really-uninstall-even-if-in-use, 那么集群会直接全部删除,而不会等待 PVC 的等待;
  • ##6198 仅在 Dashboard 设置为 true 的时候,才会启动 init 容器;
  • #6127 如果一个 OSD down 了,并且需要从 cluster 中移除,则会启动一个 job 去清理它。如果 OSD 仍然 up, 则该 job 会被拒绝;

Thanos v0.15.0 发布

本次新增了一个组件 Query Frontend 这是基于 Cortex Query Frontend 的,所以它们有些相同的特性,比如 SplittingResults Caching

更多关于此版本的信息,请参考其 ReleaseNote

上游进展

  • #94398 kubeadm 将 kube-schedulerkube-controller-manager 的 kubeconfig 配置文件中 API Server 的地址指向了本地的 API Server 地址。主要是为了避免升级过程中,当这些组件与 API Server 版本不一致时,向 API Server 请求不存在的 API 地址;
  • #94395kubeadm upgrade 时,无论 etcd 版本是否有变化,将确保 etcd manifest 重新生成;

欢迎订阅我的文章公众号【MoeLove】

TheMoeLove

查看原文

赞 0 收藏 0 评论 0

张晋涛 发布了文章 · 2020-09-22

突破 DockerHub 限制,全镜像加速服务

最近 DockerHub 修改了定价,对于免费帐号会限制 200 pulls/6小时,对于匿名帐号则限制 100 pulls/6小时。 本文我来介绍下如何使用 Cache 来应对此问题。

背景

DockerHub 是全世界最早也是最大的容器镜像仓库,托管着众多操作系统发行版及各类软件的 Docker 镜像。

在推进业务容器化的过程中,不可避免的,我们会需要使用来自 DockerHub 上的容器镜像。 无论是在个人本地环境中使用,还是用于跑测试服务

以下是两种主要的解决方案:

  • 构建一些公共基础镜像,存放在企业的私有镜像仓库中给业务方使用:

    这种方案下,如果业务方偶尔需要一些小众的/非基础的镜像,可能只是临时测试使用,那通常情况下是没必要将此类镜像作为基础镜像维护的。

    结果可能是:

    • 使用中直接从 DockerHub pull 镜像,网络状况不佳时,就是无尽的等待;
    • 先 pull 镜像,然后 docker tag 重 tag 后, push 到企业的私有镜像仓库中。这种情况下,如果没有较好的镜像管理规则,那么镜像仓库中就会存在各种无意义的镜像,造成存储资源的浪费。
  • 为 docker daemon 配置 Proxy 进行加速:

    • 众多国内镜像加速服务,仅提供 Docker 官方镜像的加速服务,个人/组织下的镜像不提供加速服务
    • 即使在不同节点上,下载相同的镜像,仍然需要通过网络加速,会产生额外的海外带宽成本;

并且近期 DockerHub 修改了其服务价格, 对于免费用户,进行了如下限制:

  • 未登录用户,每 6 小时只允许 pull 100 次
  • 已登录用户,每 6 小时只允许 pull 200 次

如果我们继续使用上述两种模式的话,由于出口 IP 是相对固定的,所以很容易触发 DockerHub 的配额限制。 此限制将于 11 月 1 日正式全面实施。

为了能 提升效率 ,以及 节约加速带宽成本 ,企业内部/个人就非常需要一个 DockerHub 全镜像加速服务了,也就是我们常说的 pull through cache

下面我来介绍下,如何利用 Docker 开源的项目 registry:2 来实现这一需求。

启动服务

使用 registry:2 部署镜像缓存服务很简单,这里先执行 docker pull registry:2 下载所需的镜像:

(MoeLove) ➜  docker pull registry:2
2: Pulling from library/registry
cbdbe7a5bc2a: Pull complete 
47112e65547d: Pull complete 
46bcb632e506: Pull complete 
c1cc712bcecd: Pull complete 
3db6272dcbfa: Pull complete 
Digest: sha256:8be26f81ffea54106bae012c6f349df70f4d5e7e2ec01b143c46e2c03b9e551d
Status: Downloaded newer image for registry:2
docker.io/library/registry:2

最小化配置的 DockerHub 镜像缓存服务,只需要使用一个配置项 REGISTRY_PROXY_REMOTEURL 即可:

这里我顺便为它单独创建了一个名为 hub-cache 的 network ,以及创建了对应的 volume 。

(MoeLove) ➜  ~ docker network create hub-cache
19a39f873a23150d3bdaf021e040ccccb092ee3071884d64d52a92df0397b220
(MoeLove) ➜  ~ docker volume create hub-cache
hub-cache
(MoeLove) ➜  ~ docker run --name=cache -d --restart=always --network=hub-cache -v hub-cache:/var/lib/registry -p 5000:5000  -e REGISTRY_PROXY_REMOTEURL=https://registry-1.docker.io registry:2 
6cbdcbdcc2d62ec781479901c20be43184a48b2d73e06f04bd4693253c0c5a73
(MoeLove) ➜  ~ docker ps -l
CONTAINER ID   IMAGE        COMMAND                  CREATED         STATUS         PORTS                    NAMES
6cbdcbdcc2d6   registry:2   "/entrypoint.sh /etc…"   8 seconds ago   Up 6 seconds   0.0.0.0:5000->5000/tcp   cache

验证加速效果

启动一个全新的 Docker In Docker 容器进行验证,避免受到本地环境的影响。

通过传递 --registry-mirror http://cache:5000 ,将刚才启动的 registry 设置为 mirror 。

(MoeLove) ➜  ~ docker run  --network=hub-cache -d --privileged docker:dind --registry-mirror http://cache:5000 
73c56ac25d68927c9f5b0e458f2babc0699cf8595df0d1e86c021fd03d477384
(MoeLove) ➜  ~ docker exec -it $(docker ps -ql) sh
/ # 检查配置是否生效
/ # docker info --format '{{ .RegistryConfig.Mirrors }}' 
[http://cache:5000/]

/ # time docker pull prom/prometheus
Using default tag: latest
latest: Pulling from prom/prometheus
76df9210b28c: Pull complete 
559be8e06c14: Pull complete 
6a4bb3319487: Pull complete 
2cca90a64593: Pull complete 
d2014e464a99: Pull complete 
70b42590e4a2: Pull complete 
54645fcbd6cc: Pull complete 
67d9943de656: Pull complete 
b9c749b1af90: Pull complete 
9723d8eb5323: Pull complete 
7d20502d5322: Pull complete 
3e519cce6f63: Pull complete 
Digest: sha256:d43417c260e516508eed1f1d59c10c49d96bbea93eafb4955b0df3aea5908971
Status: Downloaded newer image for prom/prometheus:latest
docker.io/prom/prometheus:latest
real    0m 42.71s
user    0m 0.12s
sys     0m 0.09s


/ # docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
prom/prometheus     latest              cdfc440228d0        8 days ago          168MB

/ # docker rmi prom/prometheus                                     
Untagged: prom/prometheus:latest
Untagged: prom/prometheus@sha256:d43417c260e516508eed1f1d59c10c49d96bbea93eafb4955b0df3aea5908971
Deleted: sha256:cdfc440228d01d7a94937d7a047fa6461efc1b1806bb20677043fee032810830
Deleted: sha256:c72f348fd2f923996ea80222feb77e34aba9de397bd96206ddc3c8651adc306d
Deleted: sha256:e34df2c00334266a67bb846b958ba6eae3b1d5cdfe9d763707027a23e7c85100
Deleted: sha256:d2cb38310ada122064b7333bbfc12c67dc58acb30e29146b3ba1e24adc27a950
Deleted: sha256:7a87cd520d19a83b3582541aac4d95098ae5016b092e72eaf80dc54f587bf51e
Deleted: sha256:f84c79dceed6b5a27234c1291d0bdccab5c459d587f13934d74db9b9e79471c6
Deleted: sha256:f542b0cffe0fe16c31c98e7eed934d5fea5e598c03b53b4efd308a62e0e9c6a9
Deleted: sha256:f746b4a525727bcb79367d009d707ef45d75bac09aaa18a68c20a19046df0897
Deleted: sha256:09b45653ee7062c7cd754885bf46ebe554d0794573fb2e200acea8644e64670f
Deleted: sha256:867526c56b30e67493341ef33890aa242c1131e4bb4151e60011b4d450892d59
Deleted: sha256:86d629b358ee70bdb0f0a11c10915b8551e904fe337f9a8bfcad476977329532
Deleted: sha256:842455c528af7383ba4a0de424fc63664a0248581a191516d6dbf45195c69426
Deleted: sha256:1be74353c3d0fd55fb5638a52953e6f1bc441e5b1710921db9ec2aa202725569

/ # time docker pull prom/prometheus
Using default tag: latest
latest: Pulling from prom/prometheus
76df9210b28c: Pull complete 
559be8e06c14: Pull complete 
6a4bb3319487: Pull complete 
2cca90a64593: Pull complete 
d2014e464a99: Pull complete 
70b42590e4a2: Pull complete 
54645fcbd6cc: Pull complete 
67d9943de656: Pull complete 
b9c749b1af90: Pull complete 
9723d8eb5323: Pull complete 
7d20502d5322: Pull complete 
3e519cce6f63: Pull complete 
Digest: sha256:d43417c260e516508eed1f1d59c10c49d96bbea93eafb4955b0df3aea5908971
Status: Downloaded newer image for prom/prometheus:latest
docker.io/prom/prometheus:latest
real    0m 5.27s
user    0m 0.06s
sys     0m 0.03s

可以看到,在首次 pull prom/prometheus 镜像时,耗费了 42+s 的时间,而删除掉已下载的镜像后,再次 pull, 则只需要耗费 5+s 的时间。速度提升非常的明显。镜像加速效果达成

使用配置

对于 Linux 系统而言,仅需要在 /etc/docker/daemon.json 文件(如果没有此文件,直接创建即可)中写入你的镜像加速服务的域名,重启 docker daemon 即可(也可选择 reload 配置)。

{
        "registry-mirrors": [
                "https://hub-cache.moelove.info"
        ]
}

或者是在 docker daemon 的启动参数中加入 registry-mirror 配置项。

对于 Mac 和 Windows 用户,直接在 Docker Desktop 系统设置中,配置 registry-mirrors 即可。

注意 如果 Docker daemon 中配置了 HTTP_PROXYHTTPS_PROXY ,那么需要将加速域名配置在 NO_PROXY 中,避免被代理。

总结

本文介绍了如何使用 Docker 开源的 registry:2 搭建 DockerHub 的镜像加速服务。这里只介绍了最简单的配置。

但如果在企业环境中部署的话,需要有更多的配置。比如,可以通过配置 REGISTRY_HTTP_DEBUG_PROMETHEUS_ENABLED 暴露 Prometheus metrics ,用于监控服务可用性及查看 cache 的效果;可以对日志及相关字段进行配置;
为了避免在 11 月后,触发到 DockerHub 的流量限制,可以横向进行扩容,准备多出口 IP,以及配置账户等。

最近新发布的 Harbor v2.1 貌似多了一个作为 proxy cache 的特性,但它与本文介绍的 pull through cache 并不相同,使用 Harbor 的 proxy cache 特性,需要将待 pull 的镜像,设置成 <harbor_servername>/<proxy_project_name>/repo/name:tag 的形式,这样子只是省去了本文一开始介绍的那种手动重 tag 的操作,不够方便,但也是个很不错的特性了。


欢迎订阅我的文章公众号【MoeLove】

TheMoeLove

查看原文

赞 7 收藏 4 评论 0

张晋涛 发布了文章 · 2020-09-03

被 Google 选择的下一代数据面 Cilium 是什么 - 上手实践

背景

在我之前的文章 K8S 生态周报| Google 选择 Cilium 作为 GKE 下一代数据面 一文中,我介绍了 Google 宣布使用 Cilium 作为 GKE 的下一代数据面,及其背后的故事。

Google 选择 Cilium 主要是为了增加 GKE 平台的容器安全性和可观测性。那么,Cilium 到底是什么,为什么会有这么强的吸引力呢?

摘一段官网的介绍:

Cilium is open source software for transparently securing the network connectivity between application services deployed using Linux container management platforms like Docker and Kubernetes.

Cilium 是一个用于透明保护部署在 Linux 容器管理平台(比如 Docker 和 Kubernetes)上的应用服务之间网络连接的开源软件。

为什么着重强调是 “Linux 容器管理平台” 呢?这就不得不提到 Cilium 的实现了。Cilium 的基础是一种称为 eBPF 的 Linux 内核技术,使用 eBPF 可以在 Linux 自身内部动态的插入一些控制逻辑,从而满足可观察性和安全性相关的需求。

只谈概念毕竟过于空洞,本节我们直接上手实践一下 Cilium 。

准备集群

这里我使用 KIND 来创建一套多节点的本地集群。

写配置文件

在创建集群时候,通过配置文件来禁用掉 KIND 默认的 CNI 插件。

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
- role: worker
- role: worker
networking:
  disableDefaultCNI: true

启动集群

将配置文件命名为 kindconfig ,通过 --config 参数来指定它。 通过 --image 参数可指定创建集群所使用的镜像,这里我使用 kindest/node:v1.19.0@sha256:6a6e4d588db3c2873652f382465eeadc2644562a64659a1da4 来创建一个最新的 Kubernetes v1.19.0 版本的集群。

(MoeLove) ➜  ~ kind create cluster --config=kindconfig  --image=kindest/node:v1.19.0@sha256:6a6e4d588db3c2873652f382465eeadc2644562a64659a1da4
db73d3beaa8848  
Creating cluster "kind" ...
 ✓ Ensuring node image (kindest/node:v1.19.0) 🖼 
 ✓ Preparing nodes 📦 📦 📦 📦  
 ✓ Writing configuration 📜 
 ✓ Starting control-plane 🕹️ 
 ✓ Installing StorageClass 💾 
 ✓ Joining worker nodes 🚜 
Set kubectl context to "kind-kind"
You can now use your cluster with:

kubectl cluster-info --context kind-kind

Have a question, bug, or feature request? Let us know! https://kind.sigs.k8s.io/#community 🙂

查看状态

由于我们已经禁用了 KIND 默认的 CNI ,所以现在集群的 Node 都是 NotReady 的状态,等待 CNI 的初始化。

(MoeLove) ➜  ~ kubectl get nodes 
NAME                 STATUS     ROLES    AGE   VERSION
kind-control-plane   NotReady   master   85s   v1.19.0
kind-worker          NotReady   <none>   49s   v1.19.0
kind-worker2         NotReady   <none>   49s   v1.19.0
kind-worker3         NotReady   <none>   49s   v1.19.0

部署 Cilium

部署 Cilium 可以有多种方式,这里我们选择最简单的,直接使用 Helm 3 进行部署。

添加 Helm 仓库

Cilium 提供了官方维护的 Helm 仓库,我们先来添加它。

注意: 请使用 Helm 3。 在之前的文章 K8S 生态周报| Helm v2 进入维护期倒计时 中,我曾介绍过 Helm v2 的维护期已经进入倒计时,三个月后将停止为 Helm v2 提供安全补丁,届时 Helm v2 的维护期就彻底终止了。

(MoeLove) ➜  ~ helm repo add cilium https://helm.cilium.io/ 
"cilium" has been added to your repositories

预加载镜像

这一步并非必须。 只是由于每个在 Node 上都需要下载 cilium/cilium:v1.8.2 的镜像,会很耗时,所以我们可以直接使用 kind load docker-image 将主机 Docker 中的镜像加载到 KIND 创建的集群中。

# 下载镜像
(MoeLove) ➜  ~ docker pull cilium/cilium:v1.8.2 
v1.8.2: Pulling from cilium/cilium
Digest: sha256:9dffe79408025f7523a94a1828ac1691b997a2b1dbd69af338cfbecc8428d326
Status: Image is up to date for cilium/cilium:v1.8.2
docker.io/cilium/cilium:v1.8.2
# 将镜像加载到 KIND 集群中
(MoeLove) ➜  ~ kind load docker-image cilium/cilium:v1.8.2  
Image: "cilium/cilium:v1.8.2" with ID "sha256:009715be68951ab107617f04dc50bcceb3d3f1e0c09db156aacf95e56eb0d5cc" not yet present on node "kind-worker3", loading...
Image: "cilium/cilium:v1.8.2" with ID "sha256:009715be68951ab107617f04dc50bcceb3d3f1e0c09db156aacf95e56eb0d5cc" not yet present on node "kind-control-plane", loading...
Image: "cilium/cilium:v1.8.2" with ID "sha256:009715be68951ab107617f04dc50bcceb3d3f1e0c09db156aacf95e56eb0d5cc" not yet present on node "kind-worker", loading...
Image: "cilium/cilium:v1.8.2" with ID "sha256:009715be68951ab107617f04dc50bcceb3d3f1e0c09db156aacf95e56eb0d5cc" not yet present on node "kind-worker2", loading...

镜像加载完成后,可使用如下命令进行二次确认:

for i in `docker ps --filter label=io.x-k8s.kind.cluster=kind -q`
do
    docker exec $i ctr -n k8s.io -a /run/containerd/containerd.sock i ls |grep cilium
done

使用 Helm 部署 Cilium

(MoeLove) ➜  ~ helm install cilium cilium/cilium --version 1.8.2 \
   --namespace kube-system \
   --set global.nodeinit.enabled=true \
   --set global.kubeProxyReplacement=partial \
   --set global.hostServices.enabled=false \
   --set global.externalIPs.enabled=true \
   --set global.nodePort.enabled=true \
   --set global.hostPort.enabled=true \
   --set global.pullPolicy=IfNotPresent \
   --set config.ipam=kubernetes \
   --set global.hubble.enabled=true \
   --set global.hubble.relay.enabled=true \
   --set global.hubble.ui.enabled=true \
   --set global.hubble.metrics.enabled="{dns,drop,tcp,flow,port-distribution,icmp,http}"
NAME: cilium
LAST DEPLOYED: Wed Sep  2 21:03:23 2020
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
You have successfully installed Cilium with Hubble Relay and Hubble UI.

Your release version is 1.8.2.

For any further help, visit https://docs.cilium.io/en/v1.8/gettinghelp

这里对几个配置项做下说明:

  • global.hubble.enabled=true : 表示启用 Hubble 。
  • global.hubble.metrics.enabled="{dns,drop,tcp,flow,port-distribution,icmp,http}:表示 Hubble 暴露出的 metrics 中包含哪些内容,如果不指定则表示禁用它。
  • global.hubble.ui.enabled=true :表示启用 Hubble UI

对于 Hubble 是什么,我们稍后再介绍。

当 Cilium 部署完成后,我们可以查看下部署的 ns 下的 Pod 情况:

(MoeLove) ➜  ~ kubectl -n kube-system get pods 
NAME                                         READY   STATUS    RESTARTS   AGE
cilium-86dbc                                 1/1     Running   0          2m11s
cilium-cjcps                                 1/1     Running   0          2m11s
cilium-f8dtm                                 1/1     Running   0          2m11s
cilium-node-init-9r9cm                       1/1     Running   1          2m11s
cilium-node-init-bkg28                       1/1     Running   1          2m11s
cilium-node-init-jgx6r                       1/1     Running   1          2m11s
cilium-node-init-s7xhx                       1/1     Running   1          2m11s
cilium-operator-756cc96896-brlrh             1/1     Running   0          2m11s
cilium-t8kqc                                 1/1     Running   0          2m11s
coredns-f9fd979d6-7vfnq                      1/1     Running   0          6m16s
coredns-f9fd979d6-h7rfw                      1/1     Running   0          6m16s
etcd-kind-control-plane                      1/1     Running   0          6m19s
hubble-relay-666ddfd69b-2lpsz                1/1     Running   0          2m11s
hubble-ui-7854cf65dc-ncj89                   1/1     Running   0          2m11s
kube-apiserver-kind-control-plane            1/1     Running   0          6m19s
kube-controller-manager-kind-control-plane   1/1     Running   0          6m19s
kube-proxy-48rwk                             1/1     Running   0          6m16s
kube-proxy-8mn58                             1/1     Running   0          5m59s
kube-proxy-jptln                             1/1     Running   0          5m59s
kube-proxy-pp24h                             1/1     Running   0          5m59s
kube-scheduler-kind-control-plane            1/1     Running   0          6m19s

查看 Node 的状态:

(MoeLove) ➜  ~ kubectl get nodes 
NAME                 STATUS   ROLES    AGE     VERSION
kind-control-plane   Ready    master   7m1s    v1.19.0
kind-worker          Ready    <none>   6m26s   v1.19.0
kind-worker2         Ready    <none>   6m26s   v1.19.0
kind-worker3         Ready    <none>   6m26s   v1.19.0

Cilium 功能体验

Hubble 介绍

上文中,通过 Helm 部署 Cilium 时,我们指定了一些与 Hubble 有关的参数,但尚未介绍 Hubble 具体是什么。这里简单介绍下。

Hubble 是一个完全分布式的网络和安全性的可观察性平台,它建立在 Cilium 和 eBPF 之上,以完全透明的方式深入了解服务以及网络基础结构的通信和行为。

由于它是构建在 Cilium 之上的,Hubble 可以利用 eBPF 获得可见性。通过使用 eBPF ,所有可见性都是可编程的,并且可以最大程度的减少开销,同时根据用户需要提供深入和详尽的可见性。例如:

  • 了解服务之间的依赖关系。可以观测到服务之间是否有通信,通信频率,以及 HTTP 调用产生的状态码等;
  • 监控网络和告警。可以观测到网络连接是否异常,是 L4 还是 L7 有问题,DNS 查询是否异常等;
  • 监控应用程序。可以观测到 HTTP 4xx/5xx 的错误率,HTTP 请求和响应的 95 值,99值等;
  • 监控安全问题。可以观测到哪些请求是被 Network Policy 所拒绝的,哪些服务解析了特定的域名等;

可观察性

我们可以直接使用 hubble observe 观测当前集群中的连接情况:

(MoeLove) ➜  hubble-ui git:(master) kubectl exec -n kube-system -t ds/cilium -- hubble observe
TIMESTAMP             SOURCE                                      DESTINATION                                TYPE          VERDICT     SUMMARY
Sep  2 07:06:41.624   kube-system/coredns-f9fd979d6-h7rfw:8181    10.244.1.50:52404                          to-stack      FORWARDED   TCP Flags: ACK, FIN
Sep  2 07:06:41.625   10.244.1.50:52404                           kube-system/coredns-f9fd979d6-h7rfw:8181   to-endpoint   FORWARDED   TCP Flags: ACK, FIN
Sep  2 07:06:42.376   10.244.1.12:4240                            10.244.0.76:45164                          to-overlay    FORWARDED   TCP Flags: ACK
Sep  2 07:06:42.376   10.244.0.76:45164                           10.244.1.12:4240                           to-endpoint   FORWARDED   TCP Flags: ACK
Sep  2 07:06:42.778   10.244.1.50:37512                           10.244.1.12:4240                           to-endpoint   FORWARDED   TCP Flags: ACK, PSH
Sep  2 07:06:42.778   10.244.1.12:4240                            10.244.1.50:37512                          to-stack      FORWARDED   TCP Flags: ACK, PSH
Sep  2 07:06:44.941   10.244.1.50:59870                           10.244.0.108:4240                          to-overlay    FORWARDED   TCP Flags: ACK
Sep  2 07:06:44.941   10.244.1.12:4240                            10.244.2.220:47616                         to-overlay    FORWARDED   TCP Fla
gs: ACK
Sep  2 07:06:44.941   10.244.1.50:52090                           10.244.3.159:4240                          to-overlay    FORWARDED   TCP Fla
gs: ACK
Sep  2 07:06:44.941   10.244.1.50:52958                           10.244.2.81:4240                           to-overlay    FORWARDED   TCP Fla
gs: ACK
Sep  2 07:06:44.941   10.244.2.220:47616                          10.244.1.12:4240                           to-endpoint   FORWARDED   TCP Fla
gs: ACK
Sep  2 07:06:45.448   10.244.1.12:4240                            10.244.3.111:54012                         to-overlay    FORWARDED   TCP Fla
gs: ACK
Sep  2 07:06:45.449   10.244.3.111:54012                          10.244.1.12:4240                           to-endpoint   FORWARDED   TCP Fla
gs: ACK
Sep  2 07:06:47.631   kube-system/coredns-f9fd979d6-h7rfw:36120   172.18.0.4:6443                            to-stack      FORWARDED   TCP Fla
gs: ACK
Sep  2 07:06:47.822   10.244.1.50:60914                           kube-system/coredns-f9fd979d6-h7rfw:8080   to-endpoint   FORWARDED   TCP Fla
gs: SYN
Sep  2 07:06:47.822   kube-system/coredns-f9fd979d6-h7rfw:8080    10.244.1.50:60914                          to-stack      FORWARDED   TCP Fla
gs: SYN, ACK
Sep  2 07:06:47.822   10.244.1.50:60914                           kube-system/coredns-f9fd979d6-h7rfw:8080   to-endpoint   FORWARDED   TCP Fla
gs: ACK
Sep  2 07:06:47.823   kube-system/coredns-f9fd979d6-h7rfw:8080    10.244.1.50:60914                          to-stack      FORWARDED   TCP Fla
gs: ACK, PSH
Sep  2 07:06:47.823   kube-system/coredns-f9fd979d6-h7rfw:8080    10.244.1.50:60914                          to-stack      FORWARDED   TCP Fla
gs: ACK, FIN
Sep  2 07:06:47.823   10.244.1.50:60914                           kube-system/coredns-f9fd979d6-h7rfw:8080   to-endpoint   FORWARDED   TCP Fla
gs: ACK, PSH

可以看到内容很详细,包括通信的两端,以及发的包是 ACK 还是 SYN 等信息均可观测到。

部署测试应用

这里我们部署一个测试应用来实际体验下 Cilium 提供的强大功能。官方仓库中提供了一个 connectivity-check 的测试用例,这里我对它做了精简和修改,以便理解。

这里定义的内容如下:

  • 1 个名为 echo-a 的 svc ,用于暴露 echo-a 这个测试服务;
  • 4 个 deploy ,分别是 1 个测试服务,以及三个用于测试与 echo-a 联通性的 deploy;
  • 2 个 CiliumNetworkPolicy,用来控制是否允许与 echo-a 联通;
---
apiVersion: v1
kind: Service
metadata:
  name: echo-a
spec:
  type: ClusterIP
  ports:
  - port: 80
  selector:
    name: echo-a
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: echo-a
spec:
  selector:
    matchLabels:
      name: echo-a
  replicas: 1
  template:
    metadata:
      labels:
        name: echo-a
    spec:
      containers:
      - name: echo-container
        image: docker.io/cilium/json-mock:1.0
        imagePullPolicy: IfNotPresent
        readinessProbe:
          exec:
            command: ["curl", "-sS", "--fail", "-o", "/dev/null", "localhost"]
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pod-to-a-allowed-cnp
spec:
  selector:
    matchLabels:
      name: pod-to-a-allowed-cnp
  replicas: 1
  template:
    metadata:
      labels:
        name: pod-to-a-allowed-cnp
    spec:
      containers:
      - name: pod-to-a-allowed-cnp-container
        image: docker.io/byrnedo/alpine-curl:0.1.8
        command: ["/bin/ash", "-c", "sleep 1000000000"]
        imagePullPolicy: IfNotPresent
        livenessProbe:
          exec:
            command: ["curl", "-sS", "--fail", "-o", "/dev/null", "echo-a"]
        readinessProbe:
          exec:
            command: ["curl", "-sS", "--fail", "-o", "/dev/null", "echo-a"]
---
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: "pod-to-a-allowed-cnp"
spec:
  endpointSelector:
    matchLabels:
      name: pod-to-a-allowed-cnp
  egress:
  - toEndpoints:
    - matchLabels:
        name: echo-a
    toPorts:
    - ports:
      - port: "80"
        protocol: TCP
  - toEndpoints:
    - matchLabels:
        k8s:io.kubernetes.pod.namespace: kube-system
        k8s:k8s-app: kube-dns
    toPorts:
    - ports:
      - port: "53"
        protocol: UDP
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pod-to-a-l3-denied-cnp
spec:
  selector:
    matchLabels:
      name: pod-to-a-l3-denied-cnp
  replicas: 1
  template:
    metadata:
      labels:
        name: pod-to-a-l3-denied-cnp
    spec:
      containers:
      - name: pod-to-a-l3-denied-cnp-container
        image: docker.io/byrnedo/alpine-curl:0.1.8
        command: ["/bin/ash", "-c", "sleep 1000000000"]
        imagePullPolicy: IfNotPresent
        livenessProbe:
          timeoutSeconds: 7
          exec:
            command: ["ash", "-c", "! curl -sS --fail --connect-timeout 5 -o /dev/null echo-a"]
        readinessProbe:
          timeoutSeconds: 7
          exec:
            command: ["ash", "-c", "! curl -sS --fail --connect-timeout 5 -o /dev/null echo-a"]
---
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: "pod-to-a-l3-denied-cnp"
spec:
  endpointSelector:
    matchLabels:
      name: pod-to-a-l3-denied-cnp
  egress:
  - toEndpoints:
    - matchLabels:
        k8s:io.kubernetes.pod.namespace: kube-system
        k8s:k8s-app: kube-dns
    toPorts:
    - ports:
      - port: "53"
        protocol: UDP
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pod-to-a
spec:
  selector:
    matchLabels:
      name: pod-to-a
  replicas: 1
  template:
    metadata:
      labels:
        name: pod-to-a
    spec:
      containers:
      - name: pod-to-a-container
        image: docker.io/byrnedo/alpine-curl:0.1.8
        command: ["/bin/ash", "-c", "sleep 1000000000"]
        imagePullPolicy: IfNotPresent
        livenessProbe:
          exec:
            command: ["curl", "-sS", "--fail", "-o", "/dev/null", "echo-a"]

直接部署即可:

(MoeLove) ➜  ~ kubectl apply -f cilium-demo.yaml 
service/echo-a created
deployment.apps/echo-a created
deployment.apps/pod-to-a-allowed-cnp created
ciliumnetworkpolicy.cilium.io/pod-to-a-allowed-cnp created
deployment.apps/pod-to-a-l3-denied-cnp created
ciliumnetworkpolicy.cilium.io/pod-to-a-l3-denied-cnp created
deployment.apps/pod-to-a created

查看 Pod 状态,看看状态是否正常:

(MoeLove) ➜  ~ kubectl get pods 
NAME                                      READY   STATUS    RESTARTS   AGE
echo-a-8b6595b89-w9kt2                    1/1     Running   0          49s
pod-to-a-5567c85856-xsg5b                 1/1     Running   0          49s
pod-to-a-allowed-cnp-7b85c8db8-jrjhx      1/1     Running   0          49s
pod-to-a-l3-denied-cnp-7f64d7b7c4-fsxrm   1/1     Running   0          49s

命令行观测

接下来,使用 hubble observe 观察下效果,已经可以看到我们部署的应用产生的连接了。

(MoeLove) ➜  ~ kubectl exec -n kube-system -t ds/cilium -- hubble observe  
TIMESTAMP             SOURCE                                               DESTINATION                                             TYPE          VERDICT     SUMMARY
Sep  3 00:00:13.481   default/pod-to-a-5567c85856-xsg5b:60784              default/echo-a-8b6595b89-w9kt2:80                       to-endpoint   FORWARDED   TCP Flags: ACK, PSH
Sep  3 00:00:15.429   kube-system/coredns-f9fd979d6-h7rfw:53               default/pod-to-a-allowed-cnp-7b85c8db8-jrjhx:43696      to-endpoint   FORWARDED   UDP
Sep  3 00:00:16.010   10.244.1.12:4240                                     10.244.2.220:50830                                      to-overlay    FORWARDED   TCP Flags: ACK
Sep  3 00:00:16.010   10.244.1.12:4240                                     10.244.1.50:40402                                       to-stack      FORWARDED   TCP Flags: ACK
Sep  3 00:00:16.010   10.244.1.50:40402                                    10.244.1.12:4240                                        to-endpoint   FORWARDED   TCP Flags: ACK
Sep  3 00:00:16.011   10.244.2.220:50830                                   10.244.1.12:4240                                        to-endpoint   FORWARDED   TCP Flags: ACK
Sep  3 00:00:16.523   10.244.1.12:4240                                     10.244.3.111:57242                                      to-overlay    FORWARDED   TCP Flags: ACK
Sep  3 00:00:16.523   10.244.3.111:57242                                   10.244.1.12:4240                                        to-endpoint   FORWARDED   TCP Flags: ACK
Sep  3 00:00:21.376   kube-system/coredns-f9fd979d6-h7rfw:53               default/pod-to-a-l3-denied-cnp-7f64d7b7c4-fsxrm:44785   to-overlay    FORWARDED   UDP
Sep  3 00:00:21.377   kube-system/coredns-f9fd979d6-h7rfw:53               default/pod-to-a-l3-denied-cnp-7f64d7b7c4-fsxrm:44785   to-overlay    FORWARDED   UDP
Sep  3 00:00:23.896   kube-system/coredns-f9fd979d6-h7rfw:36120            172.18.0.4:6443                                         to-stack      FORWARDED   TCP Flags: ACK
Sep  3 00:00:25.428   default/pod-to-a-allowed-cnp-7b85c8db8-jrjhx:55678   default/echo-a-8b6595b89-w9kt2:80                       L3-L4         FORWARDED   TCP Flags: SYN
Sep  3 00:00:25.428   default/pod-to-a-allowed-cnp-7b85c8db8-jrjhx:55678   default/echo-a-8b6595b89-w9kt2:80                       to-endpoint   FORWARDED   TCP Flags: SYN
Sep  3 00:00:25.428   default/echo-a-8b6595b89-w9kt2:80                    default/pod-to-a-allowed-cnp-7b85c8db8-jrjhx:55678      to-endpoint   FORWARDED   TCP Flags: SYN, ACK
Sep  3 00:00:25.428   default/pod-to-a-allowed-cnp-7b85c8db8-jrjhx:55678   default/echo-a-8b6595b89-w9kt2:80                       to-endpoint   FORWARDED   TCP Flags: ACK
Sep  3 00:00:25.428   default/pod-to-a-allowed-cnp-7b85c8db8-jrjhx:55678   default/echo-a-8b6595b89-w9kt2:80                       to-endpoint   FORWARDED   TCP Flags: ACK, PSH
Sep  3 00:00:25.429   default/pod-to-a-allowed-cnp-7b85c8db8-jrjhx:55678   default/echo-a-8b6595b89-w9kt2:80                       to-endpoint   FORWARDED   TCP Flags: ACK, FIN
Sep  3 00:00:29.546   10.244.1.50:57770                                    kube-system/coredns-f9fd979d6-h7rfw:8080                to-endpoint   FORWARDED   TCP Flags: SYN
Sep  3 00:00:29.546   kube-system/coredns-f9fd979d6-h7rfw:8080             10.244.1.50:57770                                       to-stack      FORWARDED   TCP Flags: SYN, ACK
Sep  3 00:00:29.546   10.244.1.50:57770                                    kube-system/coredns-f9fd979d6-h7rfw:8080                to-endpoint   FORWARDED   TCP Flags: ACK

Hubble UI 观测

还记得我们在上文中部署 Cilium 时候配置的几个关于 Hubble 的参数么,现在我们可以使用 Hubble UI 来看看效果。

先检查下 kube-system ns 下,是否有 hubble-ui 这个 svc 。

(MoeLove) ➜  kubectl -n kube-system get svc                                                                            
NAME             TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)                  AGE
hubble-metrics   ClusterIP   None           <none>        9091/TCP                 4m31s
hubble-relay     ClusterIP   10.102.90.19   <none>        80/TCP                   4m31s
hubble-ui        ClusterIP   10.96.69.234   <none>        80/TCP                   4m31s
kube-dns         ClusterIP   10.96.0.10     <none>        53/UDP,53/TCP,9153/TCP   8m51s

直接使用 kubectl port-forward ,从本地来访问 Hubble UI 。

(MoeLove) ➜  ~ kubectl -n kube-system port-forward svc/hubble-ui 12000:80
Forwarding from 127.0.0.1:12000 -> 12000
Forwarding from [::1]:12000 -> 12000

浏览器中打开 http://127.0.0.1:12000 即可。

image

可以看到我们刚才部署的所有 Pod,以及查看到相应的 CiliumNetworkPolicy 等信息,这里就不赘述了,有兴趣的小伙伴可以自行探索下。

Hubble metrics 观测

我们也可以使用 Hubble 暴露出来的 metrics 进行观测:

(MoeLove) ➜  ~ kubectl port-forward -n kube-system  ds/cilium 19091:9091
Forwarding from 127.0.0.1:19091 -> 9091
Forwarding from [::1]:19091 -> 9091

简单看下其中的内容,包含各类请求/响应/丢弃等相关的统计信息,还有包括每个目标端口包的数量统计等。感兴趣的小伙伴可以自行探索下。

(MoeLove) ➜  ~ curl -s localhost:19091/metrics | head -n 22             
# HELP hubble_dns_queries_total Number of DNS queries observed
# TYPE hubble_dns_queries_total counter
hubble_dns_queries_total{ips_returned="0",qtypes="A",rcode=""} 1165
hubble_dns_queries_total{ips_returned="0",qtypes="AAAA",rcode=""} 1165
# HELP hubble_dns_response_types_total Number of DNS queries observed
# TYPE hubble_dns_response_types_total counter
hubble_dns_response_types_total{qtypes="A",type="A"} 233
hubble_dns_response_types_total{qtypes="AAAA",type="AAAA"} 233
# HELP hubble_dns_responses_total Number of DNS queries observed
# TYPE hubble_dns_responses_total counter
hubble_dns_responses_total{ips_returned="0",qtypes="A",rcode="Non-Existent Domain"} 932
hubble_dns_responses_total{ips_returned="0",qtypes="AAAA",rcode="Non-Existent Domain"} 932
hubble_dns_responses_total{ips_returned="1",qtypes="A",rcode="No Error"} 233
hubble_dns_responses_total{ips_returned="1",qtypes="AAAA",rcode="No Error"} 233
# HELP hubble_drop_total Number of drops
# TYPE hubble_drop_total counter
hubble_drop_total{protocol="ICMPv4",reason="Policy denied"} 459
hubble_drop_total{protocol="ICMPv4",reason="Unsupported protocol for NAT masquerade"} 731
hubble_drop_total{protocol="ICMPv6",reason="Unsupported L3 protocol"} 213
hubble_drop_total{protocol="TCP",reason="Policy denied"} 1425
hubble_drop_total{protocol="UDP",reason="Stale or unroutable IP"} 6
hubble_drop_total{protocol="Unknown flow",reason="Policy denied"} 1884

验证 CiliumNetworkPolicy 的效果

说了这么多,我们来验证下刚才部署的 CiliumNetworkPolicy 的实际效果吧。

以下是刚才部署的测试 Pod, 我们通过这些 Pod 来访问 echo-a 这个 svc 。

(MoeLove) ➜  ~ kubectl get pods 
NAME                                      READY   STATUS    RESTARTS   AGE
echo-a-8b6595b89-w9kt2                    1/1     Running   0          79m
pod-to-a-5567c85856-xsg5b                 1/1     Running   0          79m
pod-to-a-allowed-cnp-7b85c8db8-jrjhx      1/1     Running   0          79m
pod-to-a-l3-denied-cnp-7f64d7b7c4-fsxrm   1/1     Running   0          79m
  • pod-to-a 这是未配置任何 CiliumNetworkPolicy 规则的 Pod
(MoeLove) ➜  ~ kubectl exec pod-to-a-5567c85856-xsg5b --  curl -sI --connect-timeout 5 echo-a
HTTP/1.1 200 OK
X-Powered-By: Express
Vary: Origin, Accept-Encoding
Access-Control-Allow-Credentials: true
Accept-Ranges: bytes
Cache-Control: public, max-age=0
Last-Modified: Sat, 26 Oct 1985 08:15:00 GMT
ETag: W/"83d-7438674ba0"
Content-Type: text/html; charset=UTF-8
Content-Length: 2109
Date: Thu, 03 Sep 2020 00:54:05 GMT
Connection: keep-alive
  • pod-to-a-allowed-cnp 配置了允许通过 TCP 访问 echo-a
(MoeLove) ➜  ~ kubectl exec pod-to-a-allowed-cnp-7b85c8db8-jrjhx --  curl -sI --connect-timeout 5 echo-a
HTTP/1.1 200 OK
X-Powered-By: Express
Vary: Origin, Accept-Encoding
Access-Control-Allow-Credentials: true
Accept-Ranges: bytes
Cache-Control: public, max-age=0
Last-Modified: Sat, 26 Oct 1985 08:15:00 GMT
ETag: W/"83d-7438674ba0"
Content-Type: text/html; charset=UTF-8
Content-Length: 2109
Date: Thu, 03 Sep 2020 01:10:27 GMT
Connection: keep-alive
  • pod-to-a-l3-denied-cnp 则是只配置了允许访问 DNS,而未配置允许对 echo-a 的访问
(MoeLove) ➜  ~ kubectl exec pod-to-a-l3-denied-cnp-7f64d7b7c4-fsxrm --  curl -sI --connect-timeout 5 echo-a
command terminated with exit code 28

可以看到,如果对 Pod 应用了 CiliumNetworkPolicy , 但是未配置对应的允许规则的话,则代表不允许访问。

比如,我们可以使用上面两个配置了 CiliumNetworkPolicy 的 Pod 来访问下公网域名:

(MoeLove) ➜  ~ kubectl exec pod-to-a-allowed-cnp-7b85c8db8-jrjhx --  curl -sI --connect-timeout 5 moelove.info
command terminated with exit code 28
(MoeLove) ➜  ~ kubectl exec pod-to-a-l3-denied-cnp-7f64d7b7c4-fsxrm --  curl -sI --connect-timeout 5 moelove.info
command terminated with exit code 28

可以看到,均不能正常访问。

总结

本节,主要介绍了 Cilium 和 Hubble 等。

通过使用 KIND 创建的 Kubernetes 集群,部署了 Cilium 及其相关组件,并通过一个实例,来展示了通过 hubble observe,Hubble UI 及 Hubble metrics 等方式进行观测。

也通过实际操作,验证了 CiliumNetworkPolicy 的实际效果。

我主要是在为 Docker 写代码的过程中,会涉及到 LSMseccomp 等部分,所以顺便去研究了 eBPF 及其相关技术(后续再分享这部分内容)。

而 Cilium 则是我在 2019 年上半年开始学习和研究的,但正如我在去年的文章 《K8S 生态周报| cilium 1.6 发布 100% kube-proxy 的替代品》 中写的那样:

这里稍微说几句我关于 Cilium 的看法:

  • 厉不厉害?厉害。
  • 值不值得研究?值得。
  • 会不会放到自己的集群替代 kube-proxy ?不会,最起码目前不会。

如果你想要通过 cilium 研究 eBPF 或者 XDP 我倒是建议你可以看看,是个很不错的项目,而且通过这个项目能加深很多网络方面的认识。这么说吧,如果把 cilium 的源码及所涉及原理都研究通透了,那就很厉害了。

至于要不要替换 kube-proxy 在我看来,最起码目前我不会这样去做。解决问题的办法有很多种,而替换掉一个核心组件,却不一定是一个最值得的选择。

Cilium 是一个值得学习和研究的项目/技术,但我目前尚未将它放到生产环境中(这也是我少数花费很多精力研究,但未应用于生产的技术之一)。

但现在看来, Cilium 也有了一定的市场/发展,是时候重新考量下了。后续我会继续分享 Cilium 及 eBPF 相关的技术文章,欢迎关注。

TheMoeLove


查看原文

赞 3 收藏 3 评论 0

张晋涛 发布了文章 · 2020-08-10

初试 Open Service Mesh(OSM)

微软近期开源了一个新的名为 Open Service Mesh 的项目并准备捐赠给 CNCF

基本介绍

Open Service Mesh (OSM) is a lightweight, extensible, Cloud Native service mesh that allows users to uniformly manage, secure, and get out-of-the-box observability features for highly dynamic microservice environments.

Open Service Mesh(OSM)是一个轻量级,可扩展的云原生服务网格,它使用户能够统一管理,保护和获得针对高度动态微服务环境的开箱即用的可观察性功能。

OSM 在 Kubernetes 上运行基于 Envoy 的控制平面,可以使用 SMI API 进行配置。它通过以 sidecar 的形式注入 Envoy 代理来工作。

控制面负责持续配置代理,以配置策略和路由规则等都保持最新。代理主要负责执行访问控制的规则,路由控制,采集 metrics 等。(这和目前我们常见到的 Service Mesh 方案基本都一样的)

显著特性

  • 基于 Service Mesh Interface (SMI) 的实现,主要包括 Traffic Access ControlTraffic SpecsTraffic Split 。剩下的 Traffic Metrics 正在开发中;
  • 服务间的通信加密使用 mTLS ;
  • 定义和执行服务间的访问控制策略;
  • 通过 Prometheus 和 Grafana 完成其观察性;
  • 可与外部证书管理服务进行集成;
  • Envoy sidecar 自动注入;

上手体验

只做介绍未免太过无趣,而且说实话,这么多 service mesh 实现,不亲自上手试试看,感觉不出来太多差异的。

这里我使用 KIND 作为我本地的实验环境。

安装

安装过程很简单,直接去 Release 页面 下载预编译好的二进制文件。可将二进制文件加入到 $PATH 中。

(MoeLove) ➜  ~ wget -q https://github.com/openservicemesh/osm/releases/download/v0.1.0/osm-v0.1.0-linux-amd64.tar.gz
(MoeLove) ➜  ~ tar -xzvf osm-v0.1.0-linux-amd64.tar.gz           
linux-amd64/
linux-amd64/LICENSE
linux-amd64/README.md
linux-amd64/osm
(MoeLove) ➜  ~ cd linux-amd64 
(MoeLove) ➜  linux-amd64 ls
LICENSE  osm  README.md

在进行 osm 资源和服务的正式安装前,先做个必要的检查:

(MoeLove) ➜  linux-amd64 ./osm check --pre-install                                                                       
ok: initialize Kubernetes client
ok: query Kubernetes API
ok: Kubernetes version
ok: can create namespaces
ok: can create customresourcedefinitions
ok: can create clusterroles
ok: can create clusterrolebindings
ok: can create mutatingwebhookconfigurations
ok: can create serviceaccounts
ok: can create services
ok: can create deployments
ok: can create configmaps
ok: can read secrets
ok: can modify iptables
All checks successful!

可以看到主要是和权限相关的一些检查。接下来就正式对 ocm 相关资源进行部署。

默认使用的镜像,托管在 DockerHub 上,如果需要配置加速的小伙伴,可传递 --container-registry 更改源地址,以便于加速安装进度。

(MoeLove) ➜  linux-amd64 ./osm install

OSM installed successfully in namespace [osm-system] with mesh name [osm]
(MoeLove) ➜  linux-amd64 kubectl -n osm-system get pods
NAME                              READY   STATUS              RESTARTS   AGE
osm-controller-d499d6cc7-88659    0/1     ContainerCreating   0          12s
osm-grafana-58ff65dfb7-svztv      0/1     ContainerCreating   0          12s
osm-prometheus-5756769877-zj6f6   0/1     ContainerCreating   0          12s
zipkin-6df4b57677-dcq8q           0/1     ContainerCreating   0          12s 

可以看到默认安装完成后,都在 osm-system 命名空间下,有 4 个 Pods

  • osm-controller:控制谬
  • osm-grafana:Dashboard 相关,可通过 osm dashboard 命令唤起;
  • osm-prometheus:采集 metrics ;
  • zipkin:链路追踪

还有对应的 service 记录.

(MoeLove) ➜  linux-amd64 kubectl -n osm-system get svc  
NAME             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)             AGE
osm-controller   ClusterIP   10.97.115.1      <none>        15128/TCP,443/TCP   7m46s
osm-grafana      ClusterIP   10.110.209.86    <none>        3000/TCP            7m46s
osm-prometheus   ClusterIP   10.97.10.65      <none>        7070/TCP            7m46s
zipkin           ClusterIP   10.103.150.158   <none>        9411/TCP            7m46s

以及一系列的 CRD

(MoeLove) ➜  linux-amd64 kubectl -n osm-system get crd   
NAME                                      CREATED AT
backpressures.policy.openservicemesh.io   2020-08-06T16:14:03Z
httproutegroups.specs.smi-spec.io         2020-08-06T16:14:03Z
tcproutes.specs.smi-spec.io               2020-08-06T16:14:03Z
trafficsplits.split.smi-spec.io           2020-08-06T16:14:03Z
traffictargets.access.smi-spec.io         2020-08-06T16:14:03Z

实践

  • 创建实验用的 namespace, 并通过 osm namespace add 将其纳入管理范围中:
(MoeLove) ➜  ~ kubectl create ns bookstore
namespace/bookstore created
(MoeLove) ➜  ~ kubectl create ns bookbuyer
namespace/bookbuyer created
(MoeLove) ➜  ~ kubectl create ns bookthief
namespace/bookthief created
(MoeLove) ➜  ~ kubectl create ns bookwarehouse
namespace/bookwarehouse created
(MoeLove) ➜  ~ osm namespace add bookstore bookbuyer bookthief bookwarehouse
Namespace [bookstore] succesfully added to mesh [osm]
Namespace [bookbuyer] succesfully added to mesh [osm]
Namespace [bookthief] succesfully added to mesh [osm]
Namespace [bookwarehouse] succesfully added to mesh [osm]
  • 部署实验应用程序
# 在项目的代码目录中执行
(MoeLove) ➜  osm git:(main) kubectl apply -f docs/example/manifests/apps 
Warning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl apply
namespace/bookbuyer configured
serviceaccount/bookbuyer created
service/bookbuyer created
deployment.apps/bookbuyer created
Warning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl apply
namespace/bookstore configured
service/bookstore created
service/bookstore-v1 created
serviceaccount/bookstore-v1 created
deployment.apps/bookstore-v1 created
Warning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl apply
namespace/bookthief configured
serviceaccount/bookthief created
service/bookthief created
deployment.apps/bookthief created
Warning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl apply
namespace/bookwarehouse configured
serviceaccount/bookwarehouse created
service/bookwarehouse created
deployment.apps/bookwarehouse created
trafficsplit.split.smi-spec.io/bookstore-split created
  • 本地访问

你可以通过 kubectl port-foward 在本地对刚才部署的应用进行访问。示例中也提供了相应的启动脚本 scripts/port-forward-all.sh ,注意这里需要先安装 GNU parallel ,例如: dnf install parallel .

(MoeLove) ➜  osm git:(main) ✗ ./scripts/port-forward-all.sh
Academic tradition requires you to cite works you base your article on.
If you use programs that use GNU Parallel to process data for an article in a
scientific publication, please cite:

  O. Tange (2018): GNU Parallel 2018, Mar 2018, ISBN 9781387509881,
  DOI https://doi.org/10.5281/zenodo.1146014

This helps funding further development; AND IT WON'T COST YOU A CENT.
If you pay 10000 EUR you should feel free to use GNU Parallel without citing.

More about funding GNU Parallel and the citation notice:
https://www.gnu.org/software/parallel/parallel_design.html#Citation-notice

To silence this citation notice: run 'parallel --citation' once.

访问本地的 8080~8083 端口即可看到示例项目。例如:

image

备注:这里是因为我的应用程序已经运行一段时间了,如果是新部署的,所有数字皆为 0

  • 访问控制策略

我们来看看如何调整访问控制的策略

kind: TrafficTarget
apiVersion: access.smi-spec.io/v1alpha2
metadata:
  name: bookstore-v1
  namespace: bookstore
spec:
  destination:
    kind: ServiceAccount
    name: bookstore-v1
    namespace: bookstore
  rules:
  - kind: HTTPRouteGroup
    name: bookstore-service-routes
    matches:
    - buy-a-book
    - books-bought
  sources:
  - kind: ServiceAccount
    name: bookbuyer
    namespace: bookbuyer
  #- kind: ServiceAccount
    #name: bookthief
    #namespace: bookthief
---
apiVersion: specs.smi-spec.io/v1alpha3
kind: HTTPRouteGroup
metadata:
  name: bookstore-service-routes
  namespace: bookstore
spec:
  matches:
  - name: books-bought
    pathRegex: /books-bought
    methods:
    - GET
    headers:
    - host: "bookstore.bookstore"
    - "user-agent": ".*-http-client/*.*"
    - "client-app": "bookbuyer"
  - name: buy-a-book
    pathRegex: ".*a-book.*new"
    methods:
    - GET
    headers:
    - host: "bookstore.bookstore"

这里定义了两个 SMI 中的资源 TrafficTargetHTTPRouteGroup ,用来控制入口流量。

(MoeLove) ➜  osm git:(main) ✗ kubectl apply -f docs/example/manifests/access/

通过以上命令创建这两个资源。然后再次打开我们的示例应用程序,就会看到对应的计数正在逐步增加(因为请求被放行了) 。

以上示例来自于项目仓库 中的示例。

Dashboard

通过 osm dashboard 可直接唤起本地浏览器,并 port-foward 将 Grafana 打开。

image

总结

Open Service Mesh 相对来说,确实很轻量。 所需要的访问控制,流量切割等功能通过自己创建 SMI 资源来控制。

并且,在同一个集群内可存在多组 mesh ,osm 安装的时候,可指定 mesh 名称。

此外,这个项目也是微软在 Service Mesh 方向的又一个大动作了。目标也许是 Istio 。让我们拭目以待。


欢迎订阅我的文章公众号【MoeLove】

TheMoeLove

查看原文

赞 1 收藏 0 评论 0

张晋涛 发布了文章 · 2020-08-07

K8S 生态周报| Istio 已修复导致 Pod 崩溃的 bug

「K8S 生态周报」内容主要包含我所接触到的 K8S 生态相关的每周值得推荐的一些信息。欢迎订阅知乎专栏「k8s生态」

Istio 1.6.7 发布

Istio 1.6.7 是为了解决在 1.6.6 中引入的一个 bug

该 bug 可能会导致 在使用 Istio 1.6.6 时,某些 Pod 进入 CrashLoopBackOff 状态,无法正常提供服务。

修复后的核心代码如下,这里主要是增加另一个返回值 expectpod

通过此方法获取 Pod 时,Pod 有两种情况可能为空:

  • 该 endpoint 未关联 Pod,这时 expectpod 为 false
  • 该 endpoint 已关联 Pod,但未找到 Pod,这时 expectpod 为 true

而这种情况发生的最主要原因可能是由于最终一致性,或者乱序事件等。

建议如果打算升级 Istio 的读者,直接跳过 1.6.6 版本,以免影响到服务。

func getPod(c *Controller, ip string, ep *metav1.ObjectMeta, targetRef *v1.ObjectReference, host host.Name) (rpod *v1.Pod, expectPod bool) {
    pod := c.pods.getPodByIP(ip)
    if pod != nil {
        return pod, false
    }
    if targetRef != nil && targetRef.Kind == "Pod" {
        key := kube.KeyFunc(targetRef.Name, targetRef.Namespace)
        podFromInformer, f, err := c.pods.informer.GetStore().GetByKey(key)
        if err != nil || !f {
            log.Debugf("Endpoint without pod %s %s.%s error: %v", ip, ep.Name, ep.Namespace, err)
            endpointsWithNoPods.Increment()
            if c.metrics != nil {
                c.metrics.AddMetric(model.EndpointNoPod, string(host), nil, ip)
            }

            epkey := kube.KeyFunc(ep.Name, ep.Namespace)
            c.pods.queueEndpointEventOnPodArrival(epkey, ip)
            return nil, true
        }
        pod = podFromInformer.(*v1.Pod)
    }
    return pod, false
}

Trivy v0.10.1 发布

本周 Trivy 相继发布了 v0.10.0 和 v0.10.1 版本,我们一起来看看有哪些值得关注的内容吧:

  • #559允许通过使用 --severity 选项进行过滤,只查看特定级别的漏洞信息
(MoeLove) ➜  ~ trivy i --severity LOW  alpine:3.10.2   
2020-08-02T23:19:28.060+0800    INFO    Detecting Alpine vulnerabilities...

alpine:3.10.2 (alpine 3.10.2)
=============================
Total: 1 (LOW: 1)

+---------+------------------+----------+-------------------+---------------+--------------------------------+
| LIBRARY | VULNERABILITY ID | SEVERITY | INSTALLED VERSION | FIXED VERSION |             TITLE              |
+---------+------------------+----------+-------------------+---------------+--------------------------------+
| openssl | CVE-2019-1547    | LOW      | 1.1.1c-r0         | 1.1.1d-r0     | openssl: side-channel weak     |
|         |                  |          |                   |               | encryption vulnerability       |
+---------+------------------+----------+-------------------+---------------+--------------------------------+
  • #562支持通过 Open Policy Agent (OPA) 来进行过滤。

比方说,我们想要实现和上面使用 --severity LOW 参数相同的效果,那我们可以定义如下 rego 规则文件。注意: 包名必须为 trivy ,同时,它还必须包含一个名为 ignore 的规则。

(MoeLove) ➜  ~ cat test_trivy.rego 
package trivy

ignore {
    input.Severity == {"UNKNOWN", "MEDIUM", "HIGH", "CRITICAL"}[_]
}

通过给 trivy 传递 --ignore-policy 参数即可。(这里一定要注意搞清楚逻辑, trivy 的参数为忽略掉匹配成功的规则。)

(MoeLove) ➜  ~ trivy image  --ignore-policy test_trivy.rego  alpine:3.10.2
2020-08-02T23:54:40.843+0800    INFO    Detecting Alpine vulnerabilities...

alpine:3.10.2 (alpine 3.10.2)
=============================
Total: 1 (UNKNOWN: 0, LOW: 1, MEDIUM: 0, HIGH: 0, CRITICAL: 0)

+---------+------------------+----------+-------------------+---------------+--------------------------------+
| LIBRARY | VULNERABILITY ID | SEVERITY | INSTALLED VERSION | FIXED VERSION |             TITLE              |
+---------+------------------+----------+-------------------+---------------+--------------------------------+
| openssl | CVE-2019-1547    | LOW      | 1.1.1c-r0         | 1.1.1d-r0     | openssl: side-channel weak     |
|         |                  |          |                   |               | encryption vulnerability       |
+---------+------------------+----------+-------------------+---------------+--------------------------------+
  • #561在输出内容中新增加了 CweIDs 字段。
(MoeLove) ➜  ~ trivy image -f json  --ignore-policy test_trivy.rego  alpine:3.10.2
[
  {
    "Target": "alpine:3.10.2 (alpine 3.10.2)",
    "Type": "alpine",
    "Vulnerabilities": 
      {
        "VulnerabilityID": "CVE-2019-1547",
        "PkgName": "openssl",
        "InstalledVersion": "1.1.1c-r0",
        "FixedVersion": "1.1.1d-r0",
        "CweIDs": [
          "CWE-311"
      ],
      ...
    }
  }
]
  • #574 增加了 --list-all-pkgs 选项,允许输出被扫描系统中已经安装的包及其版本等。

而后续发布的 v0.10.1 版本主要是为了修正 v0.10.0 中对 Dockerfile 中执行用户的修改,继续使用 root 用户作为容器镜像中的默认用户

更多关于此版本的信息,请查看 Trivy ReleaseNote, 欢迎下载使用。

上游进展

  • #93248 修改了 Kubelet 中 CFS shares 相关的逻辑,为其设置最大值为内核允许的最大值,即 2^18=262144 。

通过此次修改,Kubelet 使用 systemd 作为 cgroups 驱动时,能正常的处理 CPU 核数大于 512 的机器(如果使用 cgroupfs 作为 cgroup 驱动的话,一直都可以,因为内核会直接进行处理)

有关 Linux 内核 CFS 相关内容,可以参考我之前写的文章 Docker 容器资源管理


欢迎订阅我的文章公众号【MoeLove】

TheMoeLove

查看原文

赞 0 收藏 0 评论 0

张晋涛 发布了文章 · 2020-07-31

K8S 生态周报| NGINX Ingress Controller又添新特性

「K8S 生态周报」内容主要包含我所接触到的 K8S 生态相关的每周值得推荐的一些信息。欢迎订阅知乎专栏「k8s生态」

Conftest 正式加入 Open Policy Agent 项目

conftest 是一个非常实用的 CLI 工具,可以用于测试/验证配置文件是否符合预期。例如,可以通过如下内容来定义规则:

package main

deny[msg] {
  input.kind = "Deployment"
  not input.spec.template.spec.securityContext.runAsNonRoot = true
  msg = "Containers must not run as root"
}

deny[msg] {
  input.kind = "Deployment"
  not input.spec.selector.matchLabels.app
  msg = "Containers must provide app label for pod selectors"
}

使用此规则去检查一个未符合预期规则的 Deployment 的配置文件:

(MoeLove) ➜  conftest test deployment.yaml
FAIL - deployment.yaml - Containers must not run as root
FAIL - deployment.yaml - Deployments are not allowed

2 tests, 0 passed, 0 warnings, 2 failures

就会看到有相应的检查结果了。

至于 OPA 它是一个策略引擎,提供了一种非常灵活的方式来声明策略。

conftest 正式加入 OPA 项目,可以更好的让彼此进行集成和组合使用。并且,在 conftest 加入 OPA 项目后,会有部分功能从 conftest 移至 OPA,让 conftest 更间简便。期待后续的发展。

Traefik v2.2.7 发布

Traefik v2.2.6 中,修复了一个安全问题。
在校验使用域前置的 TLS 连接时,如果 Host 头与 SNI 不同的话,则 Traefik 将会返回 421 状态码。

此次 Traefik 发布的 v2.2.7 版本,主要是为了解决上述在 v2.2.6 中由于修复此安全问题而引入的 bug 。

现象是在 v2.2.6 版本中,如果为 Host 指定了非标准端口(443)的话,则 Traefik 会返回 421 状态码,从而导致连接异常。

v2.2.7 中解决办法也很简单,直接忽略掉 Host 中的端口,与 SNI 进行比较即可。

建议如果打算升级的话,直接升至 v2.2.7 ,避开 v2.2.6 版本。可通过 Release 页面 下载使用。

NGINX Ingress Controller v1.8.0 发布

这里介绍的是 NGINX 官方的 Ingress Controller 项目(避免和社区的 Kubernetes NGINX Ingress Controller 搞混) 。

此次版本中有几个非常值得关注的特性。

  • #1028 新增了一种资源 Policy

Policy 资源允许你为 VirtualServer 资源添加访问控制,可作用于 认证,限流和 WAF 之类的特性。由于此版本中是首次添加,目前只实现了基于 IP 的访问控制。例如,你可以通过下方的配置文件,来允许 10.0.0.0/8 的访问:

apiVersion: k8s.nginx.org/v1alpha1
kind: Policy 
metadata:
  name: allow-localhost
spec:
  accessControl:
    allow:
    - 10.0.0.0/8
  • #1019 支持注入片段( Snippets )

使用 Snippets 允许你为 VirtualServer 配置注入一段原生的 NGINX 配置片段,用于覆盖默认配置。示例如下:

apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
  name: cafe
  namespace: cafe
spec:
  http-snippets: |
    limit_req_zone $binary_remote_addr zone=mylimit:10m rate=1r/s;
    proxy_cache_path /tmp keys_zone=one:10m;
  host: cafe.example.com
  tls:
    secret: cafe-secret
  server-snippets: |
    limit_req zone=mylimit burst=20;
  upstreams:
  - name: tea
    service: tea-svc
    port: 80
  - name: coffee
    service: coffee-svc
    port: 80
  routes:
  - path: /tea
    location-snippets: |
      proxy_cache one;
      proxy_cache_valid 200 10m;
    action:
      pass: tea
  - path: /coffee
    action:
      pass: coffee

但要注意的是,如果你使用此特性,我建议你在使用之前,清楚的理解自己配置的含义。因为用这种方式配置,会绕过 Ingress Controller 的校验过程。会比较危险。并且使用此特性,不够直观。但,却可以让你对 NGINX 有更强的控制能力。

更多关于此版本的信息,请参考其 RelaseNote

上游进展

  • #92986 如果 CSI 驱动抛出 FailedPrecondition 错误,则停止重试对卷进行扩展;
  • #80917 移植 deviceManager 到 Windows 容器管理中以支持 GPU 的访问。(这是一个很关键的特性)

欢迎订阅我的文章公众号【MoeLove】

TheMoeLove

查看原文

赞 0 收藏 0 评论 0

张晋涛 发布了文章 · 2020-07-18

K8S 生态周报| Docker v19.03.12 发布

「K8S 生态周报」内容主要包含我所接触到的 K8S 生态相关的每周值得推荐的一些信息。欢迎订阅知乎专栏「k8s生态」

Docker CE v19.03.12 发布

在 Docker v19.03.11 发布时,我在「K8S 生态周报| 几乎影响所有 k8s 集群的漏洞」 一文中曾介绍过,该版本主要是为了修复一个通过使用 IPv6 RA 消息进行地址欺骗的安全漏洞 CVE-2020-13401

解决办法也很简单,直接将 /proc/sys/net/ipv6/conf/*/accept_ra 设置成 0 ,这样便可确保不接收 RA 消息,从而避免遭受攻击。

但是,在 v19.03.11 的修复中,当无法禁用 RA 消息时,会直接报错,导致 docker daemon 无法启动 (比如在容器内的只读文件系统上)。所以此次 v19.03.12 的一个最主要修复,就是无法禁用 RA 消息时,只是会记录一条日志,而不是直接报错。

-    return fmt.Errorf("libnetwork: Unable to disable IPv6 router advertisement: %v", err)
+    logrus.WithError(err).Warn("unable to disable IPv6 router advertisement")

对此版本感兴趣的小伙伴,可以直接更新。

containerd v1.3.5 发布

此次 v1.3.5 版本,有可能是 v1.3.x 系列的最后一个版本了。此版本中主要是把主线中的一些修正给移植过来。比如

  • #4276 修正了镜像用量的计算错误;
  • #4278 当遇到一些错误时候,清理掉分配的资源;
  • #4327 shim v2 runc 传递了 options.Root

此版本也将很快集成进 Docker 中。

更多信息请参考其 ReleaseNote

Istio v1.4.10 发布

Istio v1.4.10 中主要包含以下值得注意的内容:

  • ISTIO-SECURITY-2020-006: 这个漏洞源自 CVE-2020-11080 nghttp2 在 v1.41.0 版本之前,存在 payload 过大导致拒绝服务的漏洞。当攻击者持续构造大型请求时,可能导致 CPU 飙到 100% 。这种请求可能会被发送到 Ingress Gateway 或者 Sidecar ,进而导致拒绝服务。
  • #23770 修复了 CNI 导致 POD 延迟 30~40s 启动的 bug ,主要是因为 istio-iptables.sh 中 IPv6 相关的检查逻辑。

上游进展

  • #88649 删除掉了自 v1.14 起,被废弃的 kubectl get--export 参数;
  • #89778 Ingress 已经 GA,当前使用的 API 版本为 networking.k8s.io/v1;

欢迎订阅我的文章公众号【MoeLove】

TheMoeLove

查看原文

赞 0 收藏 0 评论 0

张晋涛 收藏了文章 · 2020-07-16

思否有约丨张晋涛:一直在学习,包括更好的工作和如何成为合格的父亲

张晋涛

本期访谈嘉宾:@张晋涛
访谈编辑:芒果果

最近接触的技术大佬要么就是二十出头的天才少年,要么就是在一个领域深耕了十几二十年的资深工程师。今天要走近的却是一个「超级奶爸」。

做运维开发的张晋涛很在乎用户体验,跟他对话的时候总会觉得如沐春风。他的宝宝刚刚满月,从与他的对话中我似乎能感受到那种父亲的温柔。即使说到工作,他也是温暖和煦的,对于职业生涯的磕磕绊绊,张晋涛坦言,还没有让他“怀疑人生”想要暴走的时刻。

张晋涛用一句话介绍了自己:一个热爱开源,喜欢折腾的资深工程师,同时是一个刚满月孩子的爸爸。


努力工作,认真生活

Q:为什么会选择做运维开发?

主要是因为我一直对偏 infra 的技术感兴趣,我喜欢更贴近系统及内核层相关的技术。尤其是近些年我一直专注在容器领域,它的很多特性都来自于内核的支持。

Q:对运维将被人工智能取代的说法你有什么看法?

智能化程度越高对运维人员对要求就越高,是要用 AI 取代基础对运维工作,这个范围可能会随着技术水平的提升而扩大。至于更有技术深度的工作,短时间内并不会被取代。

我本身也在做运维平台化和自动化相关的事情,我的目标也是为了能减少更多需要运维手工完成的事情,将大家解放出来。智能化需求是必然趋势,但也存在训练成本和工作任务匹配的问题,发展趋势是“人机协作”,而不是谁取代谁。

Q:做运维开发与其他开发岗位有什么不同吗? 未来发展方向是什么?

最主要的区别在于业务方,以及职责不同。 运维开发做的系统,稍有不慎就可能会影响到用户体验,或者很多基础设施。

发展方向主要还是技术向,维开发需要同时具备运维和开发的能力。就是说在开发的时候有运维的思维,运维的时候懂开发。运维工程师如果不能顺应时代的发展掌握更成熟的技术势必会被淘汰,任何行业都是如此,不断进步才能跟上行业的发展。

Q:掌握的技术栈?目前主要使用的编程语言是?

前后端都在做,主要用的是 Python, Golang 和 Javascript 等。

Q:Python, Golang 和 Javascript 这些编程语言中更喜欢使用哪种?为什么?

喜欢的话,我更喜欢 Python,但目前 Golang 用的更多。 喜欢 Python 最主要是由于它的灵活。

Q:前端后端都在做,你更擅长哪方面?

当然是后端啦,毕竟这是我的主业。其实在前端方面我也折腾了挺多东西,但最主要写前端的原因是因为没有专职的前端工程师。

Q:工作中最常使用的几个工具是什么?好用的插件推荐?

最常用的是  Vim , Tmux 和 Docker, Vim 推荐的插件和配置可以参考我的 Vim 配置 https://github.com/tao12345666333/vim

Q:最近有没有尝试新的编程语言?一般通过什么方式和渠道提升自己的能力?

最近看了看七牛的 goplus ;通常是在 GitHub  关注一些优秀的项目以及在解决 issue 的过程中进行学习。

张晋涛工作台

Q:分享一下你的工作流,有什么个人的特别的工作习惯么?

我日常的操作系统是 Linux,工作流基本就是打开终端,用 tmuxinator 直接打开预先配置好的 tmux 会话,自动切割窗口,用 vim 打开当前正在开发的项目,其他面板会将项目部署至本地开发环境并输出日志。工作习惯的话,应该没太什么特别的,只不过会尽可能的做自动化(偷懒)。

Q:目前为止最满意的开发项目是什么?

近期的话,应该是 KIND(Kubernetes In Docker)项目。这个项目最初是用于 Kubernetes 自身的 CI 环境中的,它同时也非常适合在本地快速的启动一个 Kubernetes 集群(支持多节点)。相比于其他的同类项目,KIND 将整个集群放在了一个 Docker 容器内,资源消耗和管理起来都比较方便,同时也提供了多种解决方案,例如: 与 LB 的集成,开箱即用的镜像仓库等。

Q:你对自己的评价是热爱开源喜欢折腾,请问这两方面是如何体现的,可以举个例子么?

我觉得,直接上 GitHub 的主页图会比较直接

GitHub 的主页图

Q:除了工作之外一直坚持在做的一件事?

我一直在坚持更新 「K8S 生态周报」,分享每周我觉得值得关注的 K8S 生态中的相关信息。也是给周围的人及时传递信息,帮大家做个总结。

Q:生活中有什么爱好?通过什么方式释放工作压力?

我经常会看看动漫,休假的话爱带着我家小可爱逛吃逛吃 。(目前疫情就没法出去玩了)

Q:有宝宝了之后对工作和生活有什么不同的感悟?

有了宝宝之后,在工作之余当然会多放一些精力在照顾孩子上。当然,工作需要更努力了(赚买玩具的钱 哈哈哈)。

Q:你是如何平衡工作和生活的?

多数技术人都有的通病,可能会为了学习或者排查故障、解决问题而忘记吃饭或休息,我也如此。说实话这方面我做的并不好,我也还在努力学习中。

张晋涛


社区经历

Q:与思否的故事?

与思否结缘应该是在 2014 年,在北京场的黑客马拉松帮忙。活动办的很好,在此期间认识了一群很棒的小伙伴,后来我们也经常会约在一起吃饭聊天之类的,这也是我人生的一笔宝贵的财富,感谢思否提供的平台。

Q:如何看待国内社区的环境和氛围?

目前国内技术社区,相比七八年前要好的多。早先我管理着一个近2w人的技术贴吧,高质量问题极少出现,满屏基本都是基础入门相关的问题,伸手党很多。现在国内社区中,看到很多问题都是包含了一些自己的思考和尝试的,伸手党少了很多。

另外,各类技术分享(图文,视频,线下活动等)也在促进着技术的交流,大家有了更多的渠道和机会,这是很不错的。

Q:对想走编程这条路的初学者有什么建议吗?

首先,希望你是因为喜欢或者热爱来学编程的,否则可能会很枯燥,乏味;

其次,编程入门很简单,但是越往深走,越需要更多的基础知识,所以尽可能的去完备自己的技术机体系知识。


小编有话说:

张晋涛的状态非常放松,既没有初入职场的年轻人那么激进,也没有经验丰富的职场老人的“圆滑”。他只是平静的面对工作和生活。

工作上,他没有放松,每天都在积累,生活上他也没有懈怠,会带着家人去逛逛吃吃享受闲暇。

事业有成,家庭幸福不就是大多数人最朴实的愿望么,他似乎已经找到了那个令我们羡慕的平和状态。


思否有约

欢迎有兴趣参与访谈的小伙伴踊跃报名,《思否有约》将把你与编程有关的故事记录下来。报名邮箱:mango@sifou.com

查看原文

张晋涛 赞了文章 · 2020-07-16

思否有约丨张晋涛:一直在学习,包括更好的工作和如何成为合格的父亲

张晋涛

本期访谈嘉宾:@张晋涛
访谈编辑:芒果果

最近接触的技术大佬要么就是二十出头的天才少年,要么就是在一个领域深耕了十几二十年的资深工程师。今天要走近的却是一个「超级奶爸」。

做运维开发的张晋涛很在乎用户体验,跟他对话的时候总会觉得如沐春风。他的宝宝刚刚满月,从与他的对话中我似乎能感受到那种父亲的温柔。即使说到工作,他也是温暖和煦的,对于职业生涯的磕磕绊绊,张晋涛坦言,还没有让他“怀疑人生”想要暴走的时刻。

张晋涛用一句话介绍了自己:一个热爱开源,喜欢折腾的资深工程师,同时是一个刚满月孩子的爸爸。


努力工作,认真生活

Q:为什么会选择做运维开发?

主要是因为我一直对偏 infra 的技术感兴趣,我喜欢更贴近系统及内核层相关的技术。尤其是近些年我一直专注在容器领域,它的很多特性都来自于内核的支持。

Q:对运维将被人工智能取代的说法你有什么看法?

智能化程度越高对运维人员对要求就越高,是要用 AI 取代基础对运维工作,这个范围可能会随着技术水平的提升而扩大。至于更有技术深度的工作,短时间内并不会被取代。

我本身也在做运维平台化和自动化相关的事情,我的目标也是为了能减少更多需要运维手工完成的事情,将大家解放出来。智能化需求是必然趋势,但也存在训练成本和工作任务匹配的问题,发展趋势是“人机协作”,而不是谁取代谁。

Q:做运维开发与其他开发岗位有什么不同吗? 未来发展方向是什么?

最主要的区别在于业务方,以及职责不同。 运维开发做的系统,稍有不慎就可能会影响到用户体验,或者很多基础设施。

发展方向主要还是技术向,维开发需要同时具备运维和开发的能力。就是说在开发的时候有运维的思维,运维的时候懂开发。运维工程师如果不能顺应时代的发展掌握更成熟的技术势必会被淘汰,任何行业都是如此,不断进步才能跟上行业的发展。

Q:掌握的技术栈?目前主要使用的编程语言是?

前后端都在做,主要用的是 Python, Golang 和 Javascript 等。

Q:Python, Golang 和 Javascript 这些编程语言中更喜欢使用哪种?为什么?

喜欢的话,我更喜欢 Python,但目前 Golang 用的更多。 喜欢 Python 最主要是由于它的灵活。

Q:前端后端都在做,你更擅长哪方面?

当然是后端啦,毕竟这是我的主业。其实在前端方面我也折腾了挺多东西,但最主要写前端的原因是因为没有专职的前端工程师。

Q:工作中最常使用的几个工具是什么?好用的插件推荐?

最常用的是  Vim , Tmux 和 Docker, Vim 推荐的插件和配置可以参考我的 Vim 配置 https://github.com/tao12345666333/vim

Q:最近有没有尝试新的编程语言?一般通过什么方式和渠道提升自己的能力?

最近看了看七牛的 goplus ;通常是在 GitHub  关注一些优秀的项目以及在解决 issue 的过程中进行学习。

张晋涛工作台

Q:分享一下你的工作流,有什么个人的特别的工作习惯么?

我日常的操作系统是 Linux,工作流基本就是打开终端,用 tmuxinator 直接打开预先配置好的 tmux 会话,自动切割窗口,用 vim 打开当前正在开发的项目,其他面板会将项目部署至本地开发环境并输出日志。工作习惯的话,应该没太什么特别的,只不过会尽可能的做自动化(偷懒)。

Q:目前为止最满意的开发项目是什么?

近期的话,应该是 KIND(Kubernetes In Docker)项目。这个项目最初是用于 Kubernetes 自身的 CI 环境中的,它同时也非常适合在本地快速的启动一个 Kubernetes 集群(支持多节点)。相比于其他的同类项目,KIND 将整个集群放在了一个 Docker 容器内,资源消耗和管理起来都比较方便,同时也提供了多种解决方案,例如: 与 LB 的集成,开箱即用的镜像仓库等。

Q:你对自己的评价是热爱开源喜欢折腾,请问这两方面是如何体现的,可以举个例子么?

我觉得,直接上 GitHub 的主页图会比较直接

GitHub 的主页图

Q:除了工作之外一直坚持在做的一件事?

我一直在坚持更新 「K8S 生态周报」,分享每周我觉得值得关注的 K8S 生态中的相关信息。也是给周围的人及时传递信息,帮大家做个总结。

Q:生活中有什么爱好?通过什么方式释放工作压力?

我经常会看看动漫,休假的话爱带着我家小可爱逛吃逛吃 。(目前疫情就没法出去玩了)

Q:有宝宝了之后对工作和生活有什么不同的感悟?

有了宝宝之后,在工作之余当然会多放一些精力在照顾孩子上。当然,工作需要更努力了(赚买玩具的钱 哈哈哈)。

Q:你是如何平衡工作和生活的?

多数技术人都有的通病,可能会为了学习或者排查故障、解决问题而忘记吃饭或休息,我也如此。说实话这方面我做的并不好,我也还在努力学习中。

张晋涛


社区经历

Q:与思否的故事?

与思否结缘应该是在 2014 年,在北京场的黑客马拉松帮忙。活动办的很好,在此期间认识了一群很棒的小伙伴,后来我们也经常会约在一起吃饭聊天之类的,这也是我人生的一笔宝贵的财富,感谢思否提供的平台。

Q:如何看待国内社区的环境和氛围?

目前国内技术社区,相比七八年前要好的多。早先我管理着一个近2w人的技术贴吧,高质量问题极少出现,满屏基本都是基础入门相关的问题,伸手党很多。现在国内社区中,看到很多问题都是包含了一些自己的思考和尝试的,伸手党少了很多。

另外,各类技术分享(图文,视频,线下活动等)也在促进着技术的交流,大家有了更多的渠道和机会,这是很不错的。

Q:对想走编程这条路的初学者有什么建议吗?

首先,希望你是因为喜欢或者热爱来学编程的,否则可能会很枯燥,乏味;

其次,编程入门很简单,但是越往深走,越需要更多的基础知识,所以尽可能的去完备自己的技术机体系知识。


小编有话说:

张晋涛的状态非常放松,既没有初入职场的年轻人那么激进,也没有经验丰富的职场老人的“圆滑”。他只是平静的面对工作和生活。

工作上,他没有放松,每天都在积累,生活上他也没有懈怠,会带着家人去逛逛吃吃享受闲暇。

事业有成,家庭幸福不就是大多数人最朴实的愿望么,他似乎已经找到了那个令我们羡慕的平和状态。


思否有约

欢迎有兴趣参与访谈的小伙伴踊跃报名,《思否有约》将把你与编程有关的故事记录下来。报名邮箱:mango@sifou.com

查看原文

赞 8 收藏 1 评论 2

张晋涛 发布了文章 · 2020-06-26

K8S 生态周报| CoreDNS 发布 v1.7.0

「K8S 生态周报」内容主要包含我所接触到的 K8S 生态相关的每周值得推荐的一些信息。欢迎订阅知乎专栏「k8s生态」

CoreDNS v1.7.0 发布

CoreDNS 本周发布了 v1.7.0 版本, 这是一个向后不兼容的版本。 主要包含了以下几个方面:

  • #3776更好的 metrics 名称,其修改了大量的 metrics 名称,Dashborad 之类的都需要修改了。 例如: coredns_request_block_count_total -> coredns_dns_blocked_requests_total
  • #3794federation 插件已经被移除 (v1 Kubernetes federation);
  • kubernetes 插件中删除了一些代码, 所以它不会作为外部插件构建;
  • #3534 新的 dns64 插件,由外部转为内置插件,该插件提供了 DNS64 IPv6 地址转换机制;
  • #3737plugin/kubernetes: 移除了已经过期的 resyncperiodupstream 选项;

以上便是此版本中值得注意的变更,更多详细内容请参看其 ReleaseNote

Helm v3.2.4 发布

这是一个安全更新版本,主要是为了修正一个漏洞,该漏洞影响了 v3.2.4 之前所有 Helm v3 版本。漏洞号为 CVE-2020-4053

此漏洞的具体影响范围是,当通过 HTTP 的方式从远程来安装一个 Plugin 的时候,可能会发生文件目录的遍历攻击。攻击者可能会在恶意插件中包含相对路径,以此来将攻击文件复制到预期的文件目录之外。

这是一种很常见的攻击方法,在之前的「K8S 生态周报」文章中,我也介绍过类似的利用这种文件目录遍历的漏洞。

修正方式也很简单,对于文件的解压操作,判断是否包含相对路径,如果有,则抛出异常(这里主要是为了警示用户,其安装的内容中可能有恶意行为)。

对此版本感兴趣的朋友,可以直接下载 使用。

Istio v1.6.3 发布

本周 Istio 发布了 v1.6.3 ,此版本的主要变更如下:

  • #24264 修复了 istio 崩溃信息为 proto.Message is *client.QuotaSpecBinding, not *client.QuotaSpecBinding 的问题;
  • #24365) 修正了 SidecarInjectionSpec CRD, 从 .Values.global 阅读 imagePullSecret
  • #24469)gateway.runAsRoot 开启时,从 PodSecurityContext 移除了无效的配置;

更多关于此版本的信息,请参考其 ReleaseNote

Rook v1.3.6 发布

Rook 已经提交了从 CNCF 托管项目中毕业的申请,可能还需要一段时间才能毕业吧。

我们来看看本次 Rook v1.3.6 版本的更新内容:

  • #5603 将 CSI 驱动升级到了 v2.1.2;
  • #5309 修复了 template size 增加时,OSD PVC size 不增加的问题;
  • #5595 修改了 svc port 的名称,需求主要来自想要将 rook 与 Istio 集成,其中 kiali 要求 port 名称必须有个协议前缀,具体信息请参考 https://kiali.io/documentatio...
  • #5606 修正了小集群(比如 OSD 为 3) 当 OSD 更新时,获取的 OSD 数量不准确的情况;

更多关于此版本的详细信息,请参考其 ReleaseNote

上游进展

  • #90569kubectl run 增加了一个 --privileged 的参数;
  • #91952kubeadm join 增加了一个重试的循环, 默认写超时是 40 s, 读超时是 15s ;

欢迎订阅我的文章公众号【MoeLove】

TheMoeLove

查看原文

赞 0 收藏 0 评论 0

张晋涛 发布了文章 · 2020-06-08

K8S 生态周报| 几乎影响所有 k8s 集群的漏洞

「K8S 生态周报」内容主要包含我所接触到的 K8S 生态相关的每周值得推荐的一些信息。欢迎订阅知乎专栏「k8s生态」

Docker v19.03.11 发布

距离 v19.03.10 发布仅一周时间,Docker 又发布了新版本 v19.03.11 。此版本是一个安全修复版本,通过禁用了 IPv6 路由地址广播(RA)从而防止地址欺骗,对应的漏洞为 CVE-2020-13401

在 Docker 的默认配置中,容器网络接口是指向主机(veth 接口)的虚拟以太网链接,在此配置下,如果一个攻击者可以在容器中以 root 身份运行进程的话,那么他是可以使用 CAP_NET_RAW 能力,向主机任意发送和接收数据包的。

例如: 在容器内使用 root 用户,可以正常执行 ping 命令

(MoeLove) ➜  ~ docker run --rm -it -u root redis:alpine sh
/data # whoami
root
/data # ping -c 1 moelove.info
PING moelove.info (185.199.108.153): 56 data bytes
64 bytes from 185.199.108.153: seq=0 ttl=49 time=54.389 ms

--- moelove.info ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 54.389/54.389/54.389 ms

在容器内使用非 root 用户,执行 ping 命令会提示无权限

(MoeLove) ➜  ~ docker run --rm -it -u redis redis:alpine sh
/data # whoami
redis
/data $ ping -c 1 moelove.info
PING moelove.info (185.199.109.153): 56 data bytes
ping: permission denied (are you root?)

如果没有在主机上完全禁用 IPv6 (通过内核参数 ipv6.disable=1), 那么主机上的网络接口可以自己进行配置。如果配置项为 /proc/sys/net/ipv6/conf/*/forwarding == 0 那表示该接口禁用了 IPv6 转发。全局的静态配置可以在以下位置看到:

(MoeLove) ➜  ~ cat /proc/sys/net/ipv6/conf/all/forwarding
1

另外,还有一个默认配置是关于是否接收 RA 消息的,如果配置项为 /proc/sys/net/ipv6/conf/*/accept_ra == 1,则表示该接口默认接收 RA 消息。全局的静态配置可以在以下位置看到:

(MoeLove) ➜  ~ cat /proc/sys/net/ipv6/conf/all/accept_ra 
1

上述的两个系统默认配置的组合,表示系统接受路由广播(RA)消息,并且使用它配置 IPv6 网络栈(SLAAC)。如果熟悉 IETF RFC 4861 的小伙伴应该知道,ICMPv6 RA 虽然本意是好的,但它确实存在安全风险。

在尚未使用 IPv6 的网络中,双栈主机处于休眠状态,并等待最终的 RA 消息来唤醒其 IPv6 连接。攻击者可以制作恶意的 RA 消息,获取网络中的双协议节点以配置其 IPv6 地址,并利用攻击者的系统作为其默认的网关。这样便可很简单的实施中间人攻击了。在 RFC 6104 中其实早就记录过这个问题,也有很多相关的解决方案,此处就不展开了,涉及的东西太多了。

对应到此次漏洞中,如果攻击者通过容器发送恶意 RA 消息(rogue RA),则可以重新配置主机,将主机的部分或者全部 IPv6 通信都重定向到攻击者控制的容器。

即使之前没有 IPv6 流量,如果 DNS 服务器返回 A(IPv4)和 AAAA(IPv6)记录的话,很多 HTTP 库将会首先尝试进行 IPv6 连接,然后再回退到 IPv4 。这就为攻击者提供了制造响应的机会。

如果主机恰好有类似去年 apt 的 CVE-2019-3462 这种漏洞的话,则攻击者便可能获取主机权限。

总体而言,Docker 容器默认没有配置 CAP_NET_ADMIN 能力,所以攻击者无法直接将其配置为中间人攻击的 IP,无法使用 iptables 进行 NAT 或者 REDIRECT 流量,也不能使用 IP_TRANSPARENT。但是攻击者仍然可以使用 CAP_NET_RAW 能力,并在用户空间实现 TCP/IP 堆栈。

聊完 Docker 相关的这个漏洞,这里就顺便展开聊聊相关的一些其他问题吧。

与此漏洞类似的,受影响的还有 Kubernetes , 但并不是 Kubernetes 自身的漏洞,而是官方安装源仓库中,kubelet 依赖的 kubernetes-cni CNI 包,也存在漏洞 CVE-2020-10749

受影响版本为:

  • kubelet v1.18.0-v1.18.3
  • kubelet v1.17.0-v1.17.6
  • kubelet v1.16.11 之前版本

第三方组件相关的漏洞信息:

以下第三方组件目前未受此次漏洞影响:

  • Cilium
  • Juniper Contrail Networking
  • OpenShift SDN
  • OVN-Kubernetes
  • Tungsten Fabric

结合前面我对此漏洞的说明,想必你也看到了,解决此漏洞最简单的方法是:

  • 更新相关组件到最新(包含修复内容)的版本(截至目前,相关受影响组件中,除 Flannel 外,均已发布新版本来解决此漏洞);
  • 可以在系统中禁止接收 RA 消息(如果你不需要 RA 消息的话);
  • 也可以禁用容器的 CAP_NET_RAW 能力,例如:
(MoeLove) ➜  ~ docker run --cap-drop CAP_NET_RAW --rm -it -u root redis:alpine sh
/data # ping -c 1 moelove.info
PING moelove.info (185.199.108.153): 56 data bytes
ping: permission denied (are you root?)

Docker Compose v1.26.0 发布

Docker Compose 是一个很方便灵活的工具,大家应该不会陌生。前段时间 Docker 将 Compose 规范开源后,社区在逐步成长中。

本次发布的 v1.26.0 中,包含了很多值得注意的内容:

  • 添加了对 doker context 的支持,context 非常好用!Docker Inc. 在今年的 Docker Con 之前还和 Azure 达成了合作,加速从本地到云的开发/部署等,具体操作上也都是通过 context 实现的;
  • 支持通过 COMPOSE_COMPATIBILITY 环境变量配置其能力;

对此版本感兴趣的朋友请参考其 ReleaseNote

Kube-OVN v1.2 发布

Kube-OVN 是首次出现在「K8S 生态周报」中的项目,稍微做下介绍。它是一款基于 OVN 的 Kubernetes 网络组件,通过将OpenStack领域成熟的网络功能平移到Kubernetes,来应对更加复杂的基础环境和应用合规性要求。

Kube-OVN主要具备五大主要功能:Namespace 和子网的绑定,以及子网间访问控制,静态IP分配,动态QoS,分布式和集中式网关,内嵌 LoadBalancer。

本次发布的 v1.2 中包含了以下重要更新:

  • 开始支持 OVS-DPDK 以便于支持高性能 dpdk 应用;
  • 支持使用 BGP 将 Pod IP 路由宣告到外部网络;
  • 在创建后,支持修改子网 CIDR (我个人觉得这个功能特别有用,网络规划也有动态调整的实际需求);
  • 当子网网关修改后,路由可以自动更改;

对此版本感兴趣的朋友请参考其 RelaseNote

上游进展

本周 Kubernetes v1.19.0-beta1 已经发布!

  • #91113#91481kubectl create deployment 时,增加了 --port 的选项;

另一个值得开心的变更来自 etcd :

  • #11946 为 etcd 添加了一个 --unsafe-no-fsync 的选项,可以禁止文件同步。这对于本地开发/CI 测试都是非常好的!

欢迎订阅我的文章公众号【MoeLove】

TheMoeLove

查看原文

赞 0 收藏 0 评论 0

张晋涛 发布了文章 · 2020-06-01

K8S 生态周报| Docker v19.03.10 正式发布

「K8S 生态周报」内容主要包含我所接触到的 K8S 生态相关的每周值得推荐的一些信息。欢迎订阅知乎专栏「k8s生态」

Node Exporter v1.0.0 正式发布

Prometheus 是最早由 SoundCloud 开源的监控告警解决方案。并已经成长为继 Kubernetes 之后,第二个从 CNCF 毕业的项目。伴随着云原生理念的普及和 Kubernetes 等技术的发展, Prometheus 在监控领域也有了长足的发展。

其主要组件包括 Prometheus,Alertmanager,Node Exporter,Blackbox Exporter 和 Pushgateway 等。

Promethues 采取 Pull 的模式,所采集的 metrics 需要由对应的 Exporter 暴露出来。我们最常用的用于收集系统 metrics 的组件便是 Node Exporter 了。

本周,Node Exporter 终于迎来了 v1.0.0 版本,标志着它更加稳定,更加通用。

我在本周专门写了一篇文章来介绍它这个版本中我最关注的特性: 为 Prometheus Node Exporter 加上认证, 我们可以让监控变得更加安全。

当然这个版本中也包含了众多变更和 bugfix, 这里暂且跳过,有兴趣的小伙伴可直接参阅其 ReleaseNote

Docker v19.03.10 发布

Docker 在本周发布了 v19.03.10 版本,距离上个版本 v19.03.9 仅过了两周的时间,如果在使用 Docker v19.03.x 版本的小伙伴,我个人还是建议你更新到此版本。

此版本中最主要的一个修复是网络相关的,具体而言是与内置 DNS (embedded DNS) 有关的问题,在特定场景下,如果你创建了自定义网络,当解析外部域名时,可能会出现解析失败的情况。

这个问题的根因最早是今年 3 月份我在参与 Docker 开发时遇到的,当内置 DNS 服务器域名解析失败时,可能会触发 panic 导致 Docker daemon 异常退出。随后 Sam Whitedmoby/libnetwork 中快速的对其进行了修正。

-        if err != nil && !resp.Truncated {
+        if err != nil && (resp != nil && !resp.Truncated) {

修改的内容看起来很简单,在异常处理时,增加了 resp != nil 的条件,这确实修正了我当时遇到的情况。

但这个修正却会忽略返回错误但无响应的情况,比如 DNS 服务器异常之类的情况。但由于后续 Docker 中的逻辑处理中,需要依赖于此处的错误处理,所以会错误的认为 DNS 服务器已连接成功,只是没有响应罢了。这也就带来了问题。

所以这次的修正,也还是在这个位置:

-        if err != nil && (resp != nil && !resp.Truncated) {
+        if err != nil && (resp == nil || !resp.Truncated) {

处理了两种情况:

  • 如果返回了错误,并且响应为空;
  • 如果返回了错误,并且和截断的响应无关;

经过这次的修正,那就基本覆盖了目前能考虑到的所有情况了。希望大家能尽早升级版本。

trivy 发布 v0.8 版本

在之前的 「K8S 生态周报」中已经介绍过 trivy 工具了,是一款很方便的镜像安全扫描工具。 本周它发布了 v0.8 的版本,带来了几个值得关注的变更。

  • 增加了新的子命令 trivy image $IMAGE_NAME ,同时废弃了之前的 trivy $IMAGE_NAME 的格式;
  • 增加 --format=json 用于以 JSON 形式输出结果,更便于与其他系统进行集成;
  • 通过设置 TRIVY_REGISTRY_TOKEN 环境变量,可设置 registry token 便于直接拉取镜像进行扫描;

可直接访问 Release 页面 下载使用新版本。

上游进展

  • #90960 修正了 kubectl create secret docker-registry --from-file 不可用的问题;
  • #91182 kubelet 的 --seccomp-profile-root 选项移动到了配置文件中;
  • #91171 将 etcd 的镜像换成了基于 distroless 的镜像,之前已经把其他的一些镜像都换掉了,主要考虑的点可能是安全和体积相关的问题吧。

欢迎订阅我的文章公众号【MoeLove】

TheMoeLove

查看原文

赞 0 收藏 0 评论 0