# IP Subnetting

Something you need to know first: Binary Odometer

10.1.1.254 + 1 = 10.1.1.255
10.1.1.255 + 1 = 10.1.2.0
10.1.2.0 + 1 = 10.1.2.1

in reverse:

10.1.2.0 – 1 = 10.1.1.255

## Example 1

172.16.35.123/20 or 172.16.35.123 with the mask 255.255.240.0

### Quick Method

Figure out the subnets:

First subnet = 172.16.32.0

Next subnet = 172.16.48.0

Broadcast address = next subnet – 1

172.16.32.0 + 1 = 172.16.32.1`

Last host = Broadcast – 1
`172.16.47.255 - 1 = 172.16.47.254`

### Subnetting

• Class A subnetting (255.0.0.0) support 1677214 (2^24) host per network, that way too much
• Class B subnetting (255.255.0.0) support 16382 (2^16) host per network, that way too much
• Class C subnetting (255.255.255.0) support 254 (2^8) host, more likely we subnet down to at least 254 hosts or even further

If you subnetting a network only has 2 hosts, you can subnet with (255.255.255.254) or CIDR as /31

### Network, host number

• Networks: 2^(network bits)
• one allocate for the subnet
• one allocate for the broadcast
• Hosts: 2^(host bits) – 2

### Subnetting to be short

1. “stealing” or “taking away” bits from the host portion of an address, and
2. allocating those bits to network portion

## Example 2

Origin network 10.128.192.0/18 need at least 30 subnets as many hosts as possible

1. draw the line with /18 to split network and host
2. 2^5 > 30, need 5 subnet bit, draw the line to split subnet and host
3. network/subnet portion is 8+8+7=23 bits, host portion is 32-23=9 bits
• First subnet: 10.128.192.0/23
• Second subnet: 10.128.194.0/23
• Last subnet: 10.128.254.0/23

## 使用 Cloud Build 搭配 Helm 改善雲端部署

1. 須根據環境 (staging, production…) 去套用不同的設定及環境變數，整合不易
2. secret 常是手動新增，如 cloudsql-proxy 的憑證，時間久了常忘記該 secret 是幹麻用的，及整個服務重新部署也會卡在這個手動步驟

1. 一鍵部署、移除
2. 可根據不同的環境採用不同變數，有幾種可行的作法
3. 可根據彈性的判斷式生成設定檔
4. chart 的版本控制 (Release)

1. 有個叢集
2. Client 端安裝 Helm ， Server 端安裝 Tiller
3. 叢集有 RBAC ，可以關閉 RBAC ，或給 Tiller 權限：
• `helm init`預設使用的服務帳戶是`default`
• 叢集的`default`服務帳戶綁定`cluster-admin`叢集角色

Helm 有提供 dependency 的功能，可以透過以下指令來部署全部的 subchart：

### 透過 Cloud Build 部署

1. Build 該映像檔並推至專案的 Container Registry
2. 參考 example 來新增流程，如`helm install``helm upgrade`
3. 若 RBAC 是啟用的狀態，須要給 Cloud Build 操作叢集的權限
• Cloud Build 的服務帳戶綁定`roles/container.admin`角色及`cluster-admin`叢集角色，請參考相關指令

# IP Addressing

• layer 3 logical address assigned by an administrator(MAC built in NIC)
• used to identify specific devices on a network
• every device on the internet has a unique IP Address

Street Analogy

• network address portion
• identifies a specific network
• routers route traffic via routing tables, is based on network address(Network ID), not ip address
• host address portion
• identifies a specific endpoint on a network
• we can use a protocal such as ARP to find the host

Ipv4

• connectionless protocal: no sessions formd when transmitted, no status info
• packets treated independently
• may take different paths: load balancing, bandwidth, hopcount
• hierarchical addressing sturture
• best effort delivery
• format
• 32 bit with 4 octets
• like DHL or FedEx routing parcel based on an address

### Classes

• Unicast Traffic
• A
• start with binary 0
• range from 0.0.0.0(00000000) to 127.255.255.255(01111111)
• exceptions:
• 127 is reserved for loopback: 127.0.0.1
• 0 network is reserved for default network: 0.1.1.1
• actual range from 1.0.0.0 to 126.255.255.255
• portions
• first 1 octets: Networks
• last 3 octests: Hosts
• B
• start with binary 10
• range from 128.0.0.0(10000000) to 191.255.255.255(10111111)
• portions
• first 2 octets: Networks
• last 2 octests: Hosts
• C
• start with binary 110
• range from 192.0.0.0(11000000) to 223.255.255.255(11011111)
• portions
• first 3 octets: Networks
• last 1 octests: Hosts
• Multicast
• D
• start with binary 111
• reserved for other purposes
• E
• start with binary 1111

These classes replaced by Classless Inter-Domain Routing(CIDR) in 1993

Read more “IP Addressing”

# OSI Model

• By International Organization of Standard

### Benefits

• Standard and INTEROPERABILITY
• Split development/role: hide developer from lower layer
• Quicker development

### Layers

You need to remember both the name and the layer number

• Layer7: Application
• Layer6: Presentation
• Layer5: Session
• Layer4: Transport
• Layer3: Network
• Layer2: DataLink
• Layer1: Physical

Trick: All People Sleeping Through Networking Don’t Pass

Network Engineer: Focus on 1, 2, 3, 4 Layers
Web Developer: Focus on 5, 6, 7 Layers

Read more “OSI Model”

# Docker Swarm進階實戰(2)

### Service Logs

• 是container logs的聚集
• 可以印出全部tasks或單一task
• 如果你沒有log system，這可能是唯一troubleshooting的方式
• 沒有storage，、不支援log搜尋或轉送至其他系統
• 如果你有設定`--log-driver`，也就是其他logging方式，此指令就抓不到任何logs

Linux跟Mac可以透過`grep`做簡單的篩選

Windows透過`findstr`

### Docker Events

• Docker engine或Swarm產生的操作(Action)紀錄
• 紀錄service/node/secret/config/network等的新增修改刪除動作
• 支援搜尋及formatting
• 分兩種scope，分別是swarm level跟local level(單一node)
• event存在實體記憶體，最多只能存1000筆，所以當node數量很多時，event就不堪用了，還是需要額外的logging system

`--since`

`--filter`

### Swarm Configs

• nginx設定或更改proxy config
• 設定或更改資料庫config等 這樣可以取代bind mount（將資料儲存在硬碟），存在Raft能提高可用性 swarm config跟secret有異曲同工之妙，可以透過指令來新增刪除config files，要注意的是：
• config是immutable，不能修改只能replace
• 若有任何service使用到該config，要先移除service才能移除config
• 如果是隱私資料一樣用secret來存

stack file，`3.3`之後才支援config

# Docker Swarm進階實戰(1)

### Service的更新

1. 再來看`service update`的選項，很明顯比容器更還多出許多操作，因為swarm service存在的目的就是要能在不影響服務的情況下取代(replace)、重建recreate容器

2. swarm mode也是利用這種方式，逐一取代service底下執行的容器，達到滾動更新

3. docker service的指令並非直接告訴系統去新增或刪除容器，而是新增了一連串的工作到佇列中，整個處理的流程帶有scale、rollback、failure mitigation等功能

4. service更新的目標是limit downtime，也就是控制停機時間

5. `stack deploy`會觸發service更新

6. service更新會對nodes做rebalancing

Read more “Docker Swarm進階實戰(1)”

# Docker簡介

• Docker是2013年由DotCloud開發的開源專案，因為軟體的成功，公司之後也改名為Docker.Inc
• 其實Docker的前身是象龜(@gordonTheTurtle)，之後改成鯨魚

### Docker的重要性

• 容器將會是未來最有影響力的基礎架構
• 不管你是開發、維運、系統管理、部屬都會須要學一下
• 成長最快的雲端技術
• Infrastructure as code

Docker的優點

• 過去底層的基礎架構都是為sysops或sysadmins設計的，但Docker的解決方案考慮了developer的使用情境
• 就是快：develop faster, build faster, test faster, deploy faster, update faster, recover faster
• 使用容器來減少不同應用程式、不同系統、不同相依性的複雜度
• 大部分現存的軟體開發得少維護得多，Docker可以減輕我們維護的難度，增加開發的時間

### 安裝前要注意的

• Linux: 直接安裝，不過有分版本
• Windows: Win10不直接支援，需要透過virtual machine來安裝，在安裝的流程中會設定到；因為Windows Containers的出現，新的Windows Server 2016之後會開始直接支援Docker，不用再透過Linux Container
• Mac: 也是要透過vm，據說不要用brew來裝
• Cloud: Docker for GCP/AWS/Azure

# 安裝

### Windows 10 Pro / Enterprise

• 使用Pro跟Enterprice的用戶算是比較吃香，會有比較好的體驗
• 請在此下載安裝Docker for Windows
• 命令界面(CLI)會建議使用PowerShell
• 如果你的系統已經有在使用VirtualBox或VMware，Hyper-V啟用可能會發生資源互搶的問題

### Windows 7, 8, or 10 Home Edition

• Win7, 8與Pro/Enterprise的主要差別是Hyper-V過舊不支援，Win10 Home則是沒有Hyper-V，因此要額外安裝Docker Toolbox，然後透過VirtualBox安裝Linux VM(Linux Container)，也就是 `docker-machine` 使用網路位址轉換(NAT)存取網路
• 需要把Toolbox的 `http://localhost` 改成 `http://192.168.99.100`

### Mac

• OSX Yosemite 10.10.3以下版本的需要裝Toolbox，以上版本安裝Docker for Mac

### Linux

• 不要用系統預設的packages直接下指令安裝，例如 `apt install docker.io`，你可能會裝到過舊的版本
• 可以經由Docker automated script來安裝相依的程式，例如 `curl -ssl https://get.docker.com/ | sh`
• 或者先看過官網上的要求來手動下載安裝檔

Docker會動用到系統核心的功能，需要root權限來操作 你可以將使用者加入Docker group，註：有些版本的linux如Red Hat, Fedora沒有此選項，每個指令都要透過 `sudo`

##### Docker Machine & Docker Compose

Windows和Mac會自動幫你安裝好，Linux系統則要自己安裝這兩個項目

Docker compose

### 指令格式

• `docker`: 檢視所有管理選項
• `docker version`: 確認你可以跟docker engine溝通，和檢查你的版本號
• `docker info`: 檢視docker engine的各項設定值
• `docker image ls`: 檢視本機所有映像檔
• `docker pull <-- IMAGE -->`: 取得映像檔

# 容器（Containers）

### 映像檔(image)和容器(container)的差別

• 映像檔是我們想執行的應用程式的模板，一個映像檔可以包含一個完整的作業系統環境，裡面安裝了需要的應用程式，同一個映像檔可以建立多個容器
• 容器是從映像檔建立的執行實例，可以被啟動、開始、停止、刪除
• 大部分的映像檔都可以從Docker Hub下載並取用

### 基本指令

1. 從Docker Hub下載nginx映像檔
2. 建立一個映像檔實例（容器），命名為webhost1並執行
3. Port Forwarding: 啟用主機的80 port並將容器內部使用的80 port映射到主機上

• nginx server預設的對外端口是80 port
• 你可以更改要映射到主機的哪個port，例如 `8888:80`，然後用 `localhost:8888` 訪問

#### 以上這些指令發生了什麼事

`docker container run`

1. 尋找特定的映像檔快取，找不到該映像檔的話會從遠端倉庫(remote image repo)尋找（預設是Docker Hub，若沒提供映像檔版本將下載最新的版本）
2. 新增映像檔實例（容器）
3. Docker引擎會給這個容器一個實體IP(virtual ip)
4. 啟用host的特定埠號將容器的特定埠號映射到host
5. 以映像檔的Dockerfile CMD來執行容器

### 容器(container)和虛擬機(virtual machine)的差別

• 容器只是程序(processes)
• 容器可用的資源是受限的
• 容器關閉=程序停止

### 練習：開啟多個容器

1. 執行一個nginx實例，在背景執行且聽80port
2. 執行一個httpd(apche)實例，在背景執行且聽8080port
3. 執行一個mysql實例，在背景執行、密碼設定為自動產生，聽3306port

### 基本指令：在容器中使用終端機

• `run -t`: Allocate a pseudo-TTY
• `run -i`: Keep STDIN open even if not attached

• `start -a`: Attach STDOUT/STDERR and forward signals
• `start -i`： Attach container’s STDIN

• `exec`: 在執行中的容器上執行額外的程序
• `exec -t`: Allocate a pseudo-TTY
• `exec -i`: Keep STDIN open even if not attached

### Docker背後的網路運作

docker讓你可以建立虛擬網路(virtual network)，並將container加到網路內，建立起屬於你自己應用程式的網路拓墣 [來源]

docker daemon運作的時候，會建立三個網路

### 練習：快速更新Linux分支的CLI套件

1. 分別檢查容器不同分支的Linux上的curl版本
2. 分別在centos:7和ubuntu:14.04的容器中開啟終端機

`container run --rm`: exit之後預期容器被移除

### 練習:輪替式DNS(DNS Round Robin aka poor man’s load balancer)

1. 建立一個network包含兩個elasticsearch:2的映像檔實例
2. 將兩個容器的網路拓墣別名(network-alias)都命名為search

`curl -s`: Silent mode. Don’t output anything

# 映像檔(image)

An image is an ordered collections of root filesystem changes and the corresponding execution parameters for use within a container runtime

• 不是作業系統、沒有內核(kernal)、沒有核心模組（kernal module）[ 延伸閱讀 ]
• 體積非常輕量，小則幾KB（golang static binary），大則幾GB（ubuntu distro + apache + php）

### Docker Hub

• `1.15.5`, `mainline`, `1`, `1.15`, `latest` (mainline/stretch/Dockerfile)
• `1.15.5-perl`, `mainline-perl`, `1-perl`, `1.15-perl`, `perl` (mainline/stretch-perl/Dockerfile)
• `1.15.5-alpine`, `mainline-alpine`, `1-alpine`, `1.15-alpine`, `alpine` (mainline/alpine/Dockerfile)

Docker Hub的操作跟Github很類似，可以fork其他repo或是上傳新的repo，你所需要的資訊也都能在detail page或github上找到。

• 映像檔可以從Github或Bitbucket的repo來建置，從首頁點選 `Create Automated Build` 連結帳戶即可
• 可以選擇你的映像檔要從哪個分支來build
• 對於dockerfile的 `FROM` 指令，Docker Hub可以設定Repository Links，設定連結後，來源映像檔如果有偵測到更新，你的映像檔就會跟著rebuild
• 自定義Rebuild的Trigger

### Union檔案系統(Union file system) && 映像檔的資料層(Image layers)

fork一份映像檔到自己的repo

• 在遠端機器使用 `docker login` 的時候，操作完要登出才會移除機器上儲存的密碼
• 欲上傳private映像檔要先建立一個私人的repo

### Dockerfile基本指令

• `FROM`: 開頭一定要加的，指定一個 Base Image 來初始化，通常是取用較輕量的分支如alpine
• `ENV`: 設定環境變數
• `RUN`: 每行指令都會往上建築新的 layer(new layer on top)，上面的範例用 `&&` 來連結每一行指令是常見的作法
• `EXPOSE`: 容器沒有任何預設開啟的TCP/UDP埠號，而加了也不代表這些埠號會自動打開，要開啟埠號還是要透過 `container run -p`
• `CMD`: 容器執行或停止的時候都會執行的指令 註：docker能自動幫我們處理logging，上面的範例將log送到stdout跟stderr，讓docker可以捕捉到這些log然後做後續處理

• 如果你能從更末端的映像檔來build，例如 `FROM` 官方的nginx再做一些客製化，在維護dockerfiles時就會更加容易。如範例A到範例B
• `WORKDIR`: 意同 `RUN cd /some/path`，不過使用 `WORKDIR` 會更好
• `COPY`: 這個範例用本地的index.html複寫原本nginx的index.html
• 這個範例並沒有改寫 `CMD`，這個指令會繼承 `nginx:latest` 的command

# 持久化數據（Persisting Data）

1. `immutable intrastucture`: 當你需要更改設定，皆是透過重新建立新的容器
2. `ephemeral`：無狀態，代表容器可以被關閉、銷毀或取代

1. Volumes: 由Docker管理，存儲在宿主機的某個地方（在linux上是/var/lib/docker/volumes/）。非Docker應用程序不能改動這一位置的數據。Volumes是Docker最好的數據持久化方法
2. Bind mounts: 數據可以存放在宿主機的任何地方。數據甚至可以是重要的系統文件或目錄。非Docker應用程序可以改變這些數據；適用於local 開發測試
3. tmpfs mounts: 數據只存儲在宿主機的內存中，不會寫入到宿主機的文件系統 [ 來源 ]

### Volumes

source的path也變得比較乾淨易讀

### Bind Mounting

• host優先於container
• 不能在Dockerfile裡使用，只能透過 `container run`
• 通常是用 `-v` 指令，或 `--mount`，格式為 `/path/host:/path/container`，如

# Docker Compose[ 官方文件 ]

• 應用程式常常需要結合多個容器如SQL、proxy、網頁和後端排程等，docker compose便是用來設置容器之間的關係
• 一鍵完成
• 可以透過Docker Swarm 1.13以上版本部屬compose file

Docker compose包含兩個部份：

1. `docker-compose.yml`: YAML格式的文件來設定容器、網路、Volumes的hierarchy
• 有區分版本，如1, 2, 2.1
• `-f` 來讀取特定檔案，預設讀取的檔名是 `docker-compose.yml`
2. `docker-compose`: 命令列(CLI)工具用來測試compose file

### docker compose CLI

• 請參考上方提到的安裝流程
• 僅用於開發測試端，非正式部屬使用

• `docker-compose up`: 設定volumes/networks，執行所有容器，使用 `-d` 讓程序於背景執行
• `docker-compose down`: 停止並移除所有容器，常用 `-v` 來移除所有volumes/networks

### 使用compose來建置(build)客製化映像檔

• 使用 `docker-compose up`，如果找不到該映像檔的cache，會在當下建置
• re-build使用 `docker-compose up --build``docker-compose build`

### composefile配置

docker-compose會自動辨識`.override.yml` 的檔案，`.test.yml``.prod.yml` 或其他自訂的compose file則需要手動透過指令 `-f` 來操作

CI測試：`docker-compose.yml` + `docker-compose.test.yml`

# Swarm Mode

• Swarm用來做(叢集)架構管理
• Swarm內建於Docker
• 多個Docker host組成1個Swarm mode
• Swarm程式獨立於Docker，在Docker環境下透過swarmkit運行（須先啟用）

### Node

Swarm中的Docker的實例（Docker host）

• Worker:
• 負責容器的執行
• Manager:
• 在Swarm中透過Raft Database的設定進行協調與同步
• 負責管理Worker與協調容器的部署工作
• 也可以當Worker，Manager可以想像成有Swarm控制權限的Worker

### Service and Task

• Task: Container + Command（怎麼run這個容器）
• Service: Task A + Task B + Task C（任務的堆疊），基於 `docker run` 的再封裝

Swarm會確保services持續運作

## 基本指令

`docker swarm init` 可以新增一個swarm，其中完成這些動作[ 文件 ]

1. 初始公開金鑰基礎架構(public key infrastructure, PKI)
• Docker先扮演第一個Manager node(root manager)
• 產生一組root certificate authority(.ca)
• 產生token: worker token + manager token
• 其他node可以用這組token加入(join)swarm
2. 初始Raft database
• 儲存憑證
• 在control plane讓Manager之間共享log，透過TLS
• 儲存config data[ 文件 ]

### 更新services

service更新其中的tasks都會重建，task建立時docker會挑負載較小的node做較多分配，所以對service做 force update 可以平衡node之間的負載

### CLI更新

`service create``service update` 在不同版本上的參數變更：

1. 17.05前：必須都要透過 `service ls``service ps` 來檢查是否正常執行
2. 17.05後：新增了 `--detach` 參數，預設為true
3. 17.10後：`--detach` 參數，預設改為false 結論是17.12版本後要透過shell scripts或automation來建立service的話，記得設定 `--detach=true`

### 使用GCP Compute Engine Instance Group來試作多節點Swarm

worker node沒有swarm的控制權

### Overley Network

psql在node1，drupal在node2，node2可以透過dns name:psql來存取node1的資料庫，用80 port連到node1也能看到drupal的歡迎頁面

#### Routing Mesh

• 為service底下的task提供路由(routes ingress packets)
• container-to-container use Virtual IP
• external traffic incomming to publish ports(all nodes listen)
• 為services提供負載平衡
• stateless load balancer，如果需要指向特定container的話，須另外設定（如cookie、session）
• 使用linux既有的IPVS(IP Virtual Server)實現load balancing
• load balancer表現於TCP層的(OSI第3層)，針對一個swarm一個對外port的web架構，還會需要Nginx、HAProxy來做DNS層（第4層）的load balancer
1. 無論訪問網路中的哪個節點，即使該節點上沒有運行該service的副本，最終都能訪問到該service 舉例來說，如果後端資料庫有3個副本，當前端web server要取資料時，並非直接訪問某個資料庫副本的ip，而是透過swarm為所有service搭建的Virtual IP(VIP)
2. 外部流量導向所有節點共同監聽的public port

# Stacks

• dockerfile版本3以上
• 適用於部署端的compose(services + volumes + overlay networks + secrets…)
• composefile指令跟local端的差異：開發端忽略 `deploy` 指令，部署端忽略 `build`
• 部署不透過docker-compose
• 針對已經存在的service，再部署會update這些service

swarm的可視化工具visualizer

### Secrets

• 儲存：
• 使用者帳密
• TLS憑證、金鑰
• SSH金鑰
• 自訂設定檔
• 支援動態字串或二進位的內容
• 儲存在Raft database，只存在於各個manager node的硬碟空間
• secrets產生後會先存在swarm再分配到特定service，只有特定的container能訪問
• 乍看之下是個實體檔案，但實際上是ramfs files system透過記憶體儲存
• secrets只適用於swarm，而swarm只適用於部署端(production)，但docker讓docker-compose也能使用，僅提供開發測試，不具真的功能(fake secure)

secrets無法透過指令檢視內容（廢話），容器要存取secret得先經過指定

### secrets透過stack部署

• dockerfile版本3.1以上

### 開發端測試secrets

• docker-compose CLI版本11以上適用
• 開發端是使用bind mount的方式把secrets mount到本機目錄，只是用於開發並無secret實際功能
• 不適用內含external用法，如果部署是用 `external:true`，可以另外維護一個開發用的compose file，secret的部份改用file來寫入

# Healthchecks

• 回傳0(OK)或1(Error)
• 支援Dockerfile、Compose、`docker run` 及swarm services
• 容器有三種健康狀態: starting, healthy, unhealthy

container

services

# Docker Registry

push之後映像檔的實體檔案儲存在/var/lib/registry/

## Registry in Swarm mode

• 主要問題是解決nodes之間要訪問同一份映像檔
• 如果只在其中一個manager node build image，其他node是沒辦法取得該image
• 解法：
• 使用Docker hub、AWS、Quay來儲存管理映像檔
• 借助Routing Mesh，所有node都能藉由127.0.0.1:5000訪問