從零開始的容器工程師
首先
感謝各位
關於自我介紹
Michael.K
- 百臂股份有限公司
- Developer
- 時間軸科技股份有限公司
- Sr. Principal Developer
- 遠時(friDay)科技股份有限公司
- Sr. Principal Developer
- I.X Security
- Sr. Principal Software Engineer
- CapsLock, Studio
今天主要的目標
什麼是docker
將OS Application化
認真說起來
docker經歷過兩個朝代
在docker 1.10前
- 依賴LXC、libvirt、systemd-nspawn
- LXC還是需要一個較完整的VM
在docker 1.10(含)後
- libcontainer
- 完全擺脫LXC的依賴
- 全部由golang打造
- 需要linux kernel 3.10(所以CentOS不一定能用)
那docker是怎麼運作的
先介紹一些元件
Repository
- 就像是apt、brew或是yum的來源一樣
- 存了很多image (Package)
Image
- 相當於Package
- 有多個layer(層),每個layer都紀錄了檔案資料
- 每一層的layer都有一個特殊的hash
- 這個hash可能可以在不同image出現
Container
- 由image建立而成
- 相當於一個一個的程式
- 必須要有一個foreground在跑的程式
Network
- 主要分為幾種
- none
- bridge
- overlay
- container
- host
docker生命週期
- client呼叫docker daemon
- docker daemon與host network / host cgroups溝通
- 判斷docker container是否存在
- 從local image將layer解開
- 如果local image不存在的話從repository拿
- 建立docker container
基本的架構解釋完了
關於安裝的部份
只需要curl
curl https://get.docker.com | bash
或是上docker store
如何操作docker呢
docker有一個共用倉庫
幾個常見的docker指令
- image
- docker run
- docker images
- docker rmi
-
container
- docker exec
- docker ps
- docker logs
- docker stats
- docker start
- docker stop
- docker restart
- docker rm
譬如最常見的
docker run / exec
docker run
啟動 container
docker exec
執行container的指令
# 起一個在背景使用shell的服務
bash-3.2$ docker run -i -t -d nginx
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
be8881be8156: Already exists
65206e5c5e2d: Pull complete
8e029c3e2376: Pull complete
Digest: sha256:291e15f504cdc40aeedcd29b59f0079c794e18f22cd8a6a6d66d646b36f1d51b
Status: Downloaded newer image for nginx:latest
73ac5cf4f67f64ed5eb4e4c6e97bad6b037cdd3097b24799dacc536b6f621c9a
# 這樣就可以進去nginx了
bash-3.2$ docker exec -ti 73 bash
root@73ac5cf4f67f:/#
如果要給別人用怎麼辦
docker run -i -t -d -p 80:80 nginx
如果服務遇到意外中斷
docker run -i -t -d -p 80:80 --restart always nginx
如果要連node.js
docker run -i -d -t -p 80:80 --link node nginx
如何寫docker image
先有一個認知
container是獨立元件
設計儘量可以獨立
關於寫image的部份
介紹一些常用的關鍵字
常用的關鍵字
- FROM
- RUN
- ARG
- ADD
- COPY
- ENV
- ENTRYPOINT
- CMD
- VOLUME
- WORKDIR
輕便、簡單、快速
Docker ❤️ Alpine Linux
Alpine Linux
- 體積非常的小 (5MB)
- 有完整的Linux架構
- 豐富的元件支援
可以在使用前先看tag
FROM nginx:alpine
ARG DOMAIN
ENV DOMAIN=$DOMAIN
COPY default.conf /etc/nginx/conf.d/default.conf
ENTRYPOINT ["nginx", "-g", "daemon off;"]
建立docker image指令會是這樣
docker build . -t image:tag --build-arg DOMAIN=example.com
這時候你一定會有一個問題
ARG vs ENV
一些小變化
# 如果FOO有資料的話就是叫做FOO,如果沒的話就是叫做bar
${FOO:+bar}
# 如果FOO沒資料的話就是empty(空值),如果有的話就是bar
${FOO:-bar}
COPY vs ADD
(COPY && ADD) vs VOLUME
CMD vs ENTRYPOINT
CMD跟ENTRYPOINT
- CMD是在docker run起的指令
- docker run -ti php
- ENTRYPOINT是在container起來時的指令,必須不會中斷
新的問題來了
公司的code不能外流
如何架私有的repository
Text
gcr.io
AWS ECS
GitLab Container Registry
或是自架的方案
Harbor
就我個人而言...
再來就可以上傳了
# 先把需要上傳的container包裝成 domain/project(group)/name 的image
docker commit container registry.gitlab.com/sample/code:latest
# 登入registry
docker login -u user -p password registry.gitlab.com
# 將image上傳到registry
docker push registry.gitlab.com/sample/code:latest
# 使用上傳的image建立container
docker run -i -d -t registry.gitlab.com/sample/code:latest
從頭開始起新的docker
一定會遇到的問題...
- container要怎麼使用?
- 怎麼將各種container連在一起?
可以試看看
docker-compose
docker-compose
- 主要由兩個部份組成(services、version)
- service內定義名稱,並且所有的服務都能靠名稱溝通
version: "3"
services:
php:
build:
context: .
dockerfile: Dockerfile-php
restart: always
env_file:
- ./.env
volumes:
- ./php:/src
db:
container_name: tickets-db
image: mariadb:10
restart: always
volumes:
- ./db:/var/lib/mysql
environment:
- MYSQL_DATABASE=${DB_DATABASE}
- MYSQL_USER=${DB_USERNAME}
- MYSQL_PASSWORD=${DB_PASSWORD}
- MYSQL_RANDOM_ROOT_PASSWORD=true
web:
image: nginx:1.15.2-alpine
restart: always
ports:
- 80:80
- 443:443
depends_on:
- php
- db
- redis
volumes:
- ./php:/src
- ./web:/etc/nginx/conf.d
redis:
image: redis:4.0.11-alpine
restart: always
示範如何從零開始
沒辦法安裝的請用這個
docker後呢? 試看看叢集
kops
首先你需要一個IAM
- AmazonEC2FullAccess
- AmazonRoute53FullAccess
- AmazonS3FullAccess
- IAMFullAccess
- AmazonVPCFullAccess
並且確定有裝awscli
沒有帳號的先不用緊張
export AWS_ACCESS_KEY_ID=
export AWS_SECRET_ACCESS_KEY=
export AWS_DEFAULT_REGION=
export KOPS_STATE_STORE=
export NAME=cluster.k8s.local
# 如果已經有的可以省略
aws s3api create-bucket --bucket $KOPS_STATE_STORE \
--create-bucket-configuration LocationConstraint=ap-northeast-1
kops create cluster --master-size t2.small \
--node-size t2.small --zones ap-northeast-1a $NAME
# 等待大約兩分鐘
kubectl get nodes
如果看到有東西
代表更進一步了
接下來介紹各種角色
先說明一下Kubernetes的組成
關於k8s的設定
- apiVersion
- metadata
- kind
- spec
Node
- 就是指主機
- 包含master、node
- master是控制node的主要角色
- master一般不會部署運算單元
Pod
- Kubernetes的運算最小單位
- 可以由多個docker container組成
- 在Pod內可以取用localhost port到對應container
Deployment
- 建立基礎的Pod
- 定義Pod的行為
Service
- 分為三種類型
- NodePort: 透過master node port可以連接
- ClusterIP: 在k8s cluster內的位置
- LoadBalancer: 對外的load balancer(e.g. ELB)
- 透過ClusterIP可以在Pod內導到對應服務
這時候一定會踩到的點
KOPS的ELB是Classic Elastic Load Balancer
無法使用WebSocket
Secret
- 可以是檔案或是yaml
- 主要分為三種
- generic
- 儲存任何知道的機敏資料,並且可以作為env引入
- docker-registry
- 儲存docker private repo使用的帳號密碼
- tls
- https使用的簽章
- generic
1
1
Ingress
- k8s內的route rule(load balancer)
- 可以將對應的domain導到不同service
- 或是產生一個LoadBalancer,將對應host流量統一導出
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: hello-world-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.org/ssl-services: "hello-world-svc"
spec:
tls:
- hosts:
- api.sample.com
secretName: tls-certificate
rules:
- host: api.sample.com
http:
paths:
- path: /
backend:
serviceName: hello-world-svc
servicePort: 8080
對照docker呢
k8s與docker指令對照
docker | kubernetes |
---|---|
docker run | kubectl run/kubectl create deployment |
docker ps | kubectl get pods |
docker attach | kubectl attach |
docker exec | kubectl exec |
docker logs | kubectl top pod |
實作部署自己的服務
以及擴容方案
Q&A
Thanks
簡報
HWD TG
CapsLock, Studio
Event TG
從零開始的容器工程師
By michael34435
從零開始的容器工程師
- 1,248