前一陣閱讀了google的borg論文,在最后的related works和總結中發現了kubernetes。從論文中了解的kubernetes這個東西很有意思,按照論文所說,它的實現有希望解決an entire multi-job service的統一調度,這個對於目前的調度系統算是一個難題了。當前即使是Borg這樣成熟的分布式系統,能夠解決production任務(gmail等長運行的service)和batch任務的同時運行,但是依舊無法解決multi-job service的調度問題,對於整個service來講,還是必須走多次調度才可以執行完成,這對於用戶的體驗並不友好,這個問題類似於spark的DAGScheduler和傳統Hadoop的調度的區別,spark可以根據RDD的dependency關系來判斷上下游關系,通過lazy的方式構造一個有向無環圖進行處理,作為一個普通用戶,我可以更靈活的構造多個Batch任務在一個spark的Application中,這樣可以降低我的等待時間可提高編程靈活性,但是spark也只是支持多batch任務的DAG,對於其他任務,如production,流處理任務之類的結合也是毫無辦法。如果kubernetes真的能夠完美解決那這個系統肯定是未來的主流了。當然kubernetes是google borg的原班人馬打造,自身高素質的運維經驗會給k8s帶來更多的技術支持,並且相比於borg還加入了每個container獨立IP避免端口號沖突,強權限用戶在線調試對其他用戶的影響也有所改進。光看論文可以說是非常棒的系統。
嘛,所以稍微了解了一下k8s,發現是基於docker做的,docker本身不是很熟,當年還曾經把docker和yarn的container搞混,只能說還是得從頭開始學習docker才行。
學習的第一步自然是先學會使用,根據官網的教程,我們可以簡化為以下幾個步驟:
#獲取curl sudo apt-get install curl #安裝docker curl -fsSL https://get.docker.com/ | sh #跑hello-world docker run hello-world
#看一看本地image鏡像
docker images
#看一看本地container
docker ps -a -q
#刪除container
docker rm $(docker ps -a -q)
最新更新:docker分化了ce版和ee版,所以現在安裝稍微復雜了一點,根據不同操作系統有不同的安裝方式,Ubuntu參考:
https://docs.docker.com/engine/installation/linux/docker-ce/ubuntu/#install-docker-ce-1
看起來使用還是挺簡單的,這里的hello-world程序不是在本地,是從hub上同步下來的image鏡像。下面介紹了一些從遠程hub上pull image的方法。我比較關心的是build your own image這點,首先創建一個Dockerfile:
FROM docker/whalesay:latest RUN apt-get -y update && apt-get install -y fortunes CMD /usr/games/fortune -a | cowsay
然后使用docker build -t name .命令來構建一個image,在這里,FROM是源鏡像,如構建mysql可以使用FROM ubuntu:14.04來指定操作系統,RUN是跑的一些shell命令,我們能通過這些命令來在image持久化一些操作。CMD則是docker run時執行的命令。
到此example學習完畢,自己嘗試下構建mysql on docker。
構建dockerfile:
FROM ubuntu:14.04 MAINTAINER gaoze RUN apt-get update RUN apt-get -y install mysql-server EXPOSE 3306 CMD ["/usr/bin/mysqld_safe"]
執行docker build,再執行docker run,發現無法遠程訪問,雖然暴露了3306接口但是mysql沒設置權限。那么我們加入遠程訪問的權限再試試:
FROM ubuntu:14.04 MAINTAINER gaoze RUN apt-get update RUN apt-get -y install mysql-server RUN /etc/init.d/mysql start \ && mysql -uroot -e "grant all privileges on *.* to 'root'@'%' identified by '1';" \ && mysql -uroot -e "grant all privileges on *.* to 'root'@'localhost' identified by '1';" EXPOSE 3306 CMD ["/usr/bin/mysqld_safe"]
由於安裝時是apt-get -y的,我們使用用戶root,沒密碼,mysql -e 操作執行grant all privileges 操作。並將密碼設置為1。
build再run之后依舊無法訪問。。。但是使用命令:
docker run -i -t docker-mysql /bin/bash
之后發現本地修改確實成功了。於是決定去看看hub上的mysql官方給的Dockerfile是如何做的發現了這個:
# comment out a few problematic configuration values # don't reverse lookup hostnames, they are usually another container RUN sed -Ei 's/^(bind-address|log)/#&/' /etc/mysql/my.cnf \ && echo 'skip-host-cache\nskip-name-resolve' | awk '{ print } $1 == "[mysqld]" && c == 0 { c = 1; system("cat") }' /etc/mysql/my.cnf > /tmp/my.cnf \ && mv /tmp/my.cnf /etc/mysql/my.cnf
shell操作不好,我是沒看懂這個。。於是去查了查,首先第一句話是sed操作,這里是在文件中將bind-address和log前面都加上#將其變為注釋。第二步,在mysqld啟動參數中加入了跳過DNS檢測的部分。這段shell的意義就是保證遠程連接並關閉DNS解析,提高mysql本身的連接性能。
-i[SUFFIX], --in-place[=SUFFIX] edit files in place (makes backup if SUFFIX supplied) 在這里-i代表直接修改文件內容,大E沒找到什么意思 /^reg/replace/代表將reg開頭的行替換為replace
於是,修改后的Dockerfile為這樣:
FROM ubuntu:14.04 MAINTAINER gaoze #RUN apt-get update RUN apt-get -y install mysql-server RUN /etc/init.d/mysql start \ && mysql -uroot -e "grant all privileges on *.* to 'root'@'%' identified by '1';" \ && mysql -uroot -e "grant all privileges on *.* to 'root'@'localhost' identified by '1';" RUN sed -Ei 's/^(bind-address|log)/#&/' /etc/mysql/my.cnf \ && echo 'skip-host-cache\nskip-name-resolve' | awk '{ print } $1 == "[mysqld]" && c == 0 { c = 1; system("cat") }' /etc/mysql/my.cnf > /tmp/my.cnf \ && mv /tmp/my.cnf /etc/mysql/my.cnf EXPOSE 3306 CMD ["/usr/bin/mysqld_safe"]
ok。接下來是執行:
#shell下執行命令,指定docker image的名字為docker-mysql docker build -t docker-mysql . #啟動這個image,-d代表后台執行,-p代表端口映射 docker run -d -p 50001:3306 docker-mysql #讓我們訪問mysql試試,先看看container的運行狀況 docker ps #發現port寫的是 0.0.0.0:50001 -> 3306/tcp mysql -h 0.0.0.0 -P 50001 -uroot -p1 ok,可以訪問了,由於0.0.0.0是localhost(雖然hosts中已經屏蔽了,然而還是可以訪問本地),試試mysql -h ${本機IP地址} -P 50001 -uroot -p1。那么,這樣便創建了一個可用的docker image
目前,大家更推薦使用Dockerfile來創建image,而不是命令行修改container再固化成為image。
編輯於2019-3-13,最近mysql有個簡單的方式進行部署,使用如下命令:
sudo /kubernetes/local/bin/docker run --name mysql-base -e MYSQL_ROOT_PASSWORD=${MYSQL_PASSWD} -d -p 23306:3306 mysql:latest --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --lower_case_table_names=1
此命令的含義如下:
docker run:基本命令,執行docker image創建container並執行的過程;
--name:指定容器名稱;
-e:指定環境變量,將mysql的根用戶密碼傳遞進容器,在容器啟動后可以直接通過此密碼進行遠程連接,不需要再exec -it進入Bash改priviledge了;
-p:端口映射,將本物理機的23306端口的所有訪問映射到此容器的3306端口;
mysql:latest:指定Image名稱和版本;
--character-set-server和--collation-server:改變server字符集;
--lower_case_table_names=1: 忽略表名大小寫,mysql8表名是默認區分大小寫的。
通過此命令我們可以創建一個最新版的mysql,並且對外端口為23306,root密碼為${MYSQL_PASSWD},字符集為utf8mb4。常用設置直接完成。對大部分人來說可以直接使用。