1. 程式人生 > >【117】利用 macvlan 把容器當成虛擬機器使用

【117】利用 macvlan 把容器當成虛擬機器使用

一、製作可以遠端登入的Docker容器,系統是Ubuntu14.04。

這個章節記錄下了製作一個支援SSH遠端登入的容器的全過程。這篇文章使用 Ubuntu 14.04 做例子。其他的作業系統應該大同小異。

我這種用法,相當於把容器當成了虛擬機器。使用者可以遠端登入容器,在容器內進行各種操作。

第一個要面對的問題是:如何才能讓容器持久執行下去?眾所周知,容器要執行必須要有一個主程序。如果主程序終止,那麼容器就會自動退出。一開始我用 Ubuntu 14.04 的映象的時候就碰到了這個問題。比如你要是執行如下命令:

docker run --name ubuntu1 -d ubuntu:14.04

那麼你會發現容器 ubuntu1 根本沒有執行起來:

1.png

因此,我們需要一個程式作為容器的主程序無限執行下去。很多人也把這種無限執行的程式稱為守護程序(daemon)。

現在就需要編寫一個程式做主程序了。因為我熟悉 Java ,所以我使用 Java 來編寫主程序。Java 的開發工具使用 Eclipse 和 Maven。

Eclipse 中點選 File 選單,選中 New 選單項,在子選單中點選 Maven Project。在對話方塊中選中下面三項: Create a simple projectUser default Workspace locationResolve Workspace projects

。 點選 Next ,進入下一步的對話方塊。Group Id 填寫 qst,Artifact Id 填寫 dockerCmd,直接點選 Finish 就可以建立專案了。專案資料夾中會自動加入一個 pom.xml 檔案。

整個專案只需要一個包和一個 Java 類即可。src/main/java 下的包名是 dockerCmd,包中只有一個類 Main.java。

Main.java 的程式碼如下:

package dockerCmd;

import java.io.IOException;

/**
 * Docker 容器 Ubuntu 14.04 的主程序,保證容器一直執行。
 * @author
張超 * */
public class Main { public static void main(String[] args) { try { // 啟動 ssh 服務。 Runtime.getRuntime().exec("sudo service ssh start"); } catch (IOException e1) { e1.printStackTrace(); } // 無限迴圈的主程序。 while (true){ try { Thread.sleep(30L * 60L * 1000L); } catch (InterruptedException e) { } } } }

pom.xml :

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>qst</groupId>
    <artifactId>dockerCmd</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>dockerCmd.Main</mainClass> <!-- 你的主類名 -->
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

右鍵點選 dockerCmd 專案,快捷選單中選擇 Run As,子選單中點選 Maven build... ,彈出對話方塊。在對話方塊中, Goals 文字框中填入 clean package,點選 Run 按鈕。 在專案資料夾下會生成一個 target 資料夾,裡面有個 dockerCmd-0.0.1-SNAPSHOT.jar 檔案,就是我們需要的可執行 jar 包。

有了 java 程式後,就可以製作映象了。

新建一個 名為 qstubuntu-v3 的資料夾,目錄結構如下:

qstubuntu-v3
    |
    ├─ dockerCmd-0.0.1-SNAPSHOT.jar
    ├─ Dockerfile
    ├─ jre-8u171-linux-x64.tar.gz
    ├─ sshd_config      
    └─ user.txt     

Dockerfile

FROM ubuntu:14.04
# Set timezone as china/shanghai
RUN cp /usr/share/zoneinfo/PRC /etc/localtime
RUN mkdir /usr/java
# Copy jre install file
COPY jre-8u171-linux-x64.tar.gz /usr/java/
WORKDIR /usr/java/
RUN tar zxvf /usr/java/jre-8u171-linux-x64.tar.gz
RUN rm -rf /usr/java/jre-8u171-linux-x64.tar.gz
# Run server 
RUN mkdir /qst
# Copy app jar file
COPY dockerCmd-0.0.1-SNAPSHOT.jar /qst/
# Install openssh
RUN sudo apt-get update && sudo apt-get install openssh-server -y
# Copy ssh config file.
COPY sshd_config /etc/ssh/
# Change root user's password.
COPY user.txt /qst/
RUN chpasswd < /qst/user.txt
EXPOSE 1-65535
CMD ["/usr/java/jre1.8.0_171/bin/java", "-jar", "/qst/dockerCmd-0.0.1-SNAPSHOT.jar"]

sshd_config

# Package generated configuration file
# See the sshd_config(5) manpage for details

# What ports, IPs and protocols we listen for
Port 22
# Use these options to restrict which interfaces/protocols sshd will bind to
#ListenAddress ::
#ListenAddress 0.0.0.0
Protocol 2
# HostKeys for protocol version 2
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_dsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
#Privilege Separation is turned on for security
UsePrivilegeSeparation yes

# Lifetime and size of ephemeral version 1 server key
KeyRegenerationInterval 3600
ServerKeyBits 1024

# Logging
SyslogFacility AUTH
LogLevel INFO

# Authentication:
LoginGraceTime 120
PermitRootLogin yes
StrictModes yes

RSAAuthentication yes
PubkeyAuthentication yes
#AuthorizedKeysFile %h/.ssh/authorized_keys

# Don't read the user's ~/.rhosts and ~/.shosts files
IgnoreRhosts yes
# For this to work you will also need host keys in /etc/ssh_known_hosts
RhostsRSAAuthentication no
# similar for protocol version 2
HostbasedAuthentication no
# Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication
#IgnoreUserKnownHosts yes

# To enable empty passwords, change to yes (NOT RECOMMENDED)
PermitEmptyPasswords no

# Change to yes to enable challenge-response passwords (beware issues with
# some PAM modules and threads)
ChallengeResponseAuthentication no

# Change to no to disable tunnelled clear text passwords
#PasswordAuthentication yes

# Kerberos options
#KerberosAuthentication no
#KerberosGetAFSToken no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes

# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes

X11Forwarding yes
X11DisplayOffset 10
PrintMotd no
PrintLastLog yes
TCPKeepAlive yes
#UseLogin no

#MaxStartups 10:30:60
#Banner /etc/issue.net

# Allow client to pass locale environment variables
AcceptEnv LANG LC_*

Subsystem sftp /usr/lib/openssh/sftp-server

# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the ChallengeResponseAuthentication and
# PasswordAuthentication.  Depending on your PAM configuration,
# PAM authentication via ChallengeResponseAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
UsePAM yes

user.txt

root:123456

把整個 qstubuntu-v3 資料夾上傳到裝有 Docker 的伺服器上,通過 cd 命令進入 qstubuntu-v3 目錄,然後執行如下命令 docker build -t qst/qstubuntu:v3 . 就可以了。

二、Centos7如何建立docker的macvlan網路模式,讓物理機能和容器通訊。

我在虛擬機器下安裝了一個 centos 7 系統。在centos 7 中實驗了 Docker 的 macvlan 網路模式。本章節記錄了我的實驗過程。

虛擬機器軟體選擇 virtualbox, 版本號是5.2。

安裝好 virtulabox 後,點選新建按鈕,彈出對話方塊。在對話方塊中,名稱填寫server-centos,型別選擇 Linux ,版本選擇 Other Linux(64-bit),點選下一步。

記憶體我填寫了 4096 M,多少根據自己物理機的實際配置決定。點選下一步。

虛擬硬碟步驟中選擇現在建立虛擬硬碟 點選建立。

虛擬硬碟檔案型別選擇 VDI(VirtualBox磁碟映像),點選下一步。

“儲存在物理硬碟上” 這一步的時候,選擇動態分配。下一步。

“檔案位置和大小”:位置是預設的,當然你也可以選擇。大小我填寫了40G。點選建立。

然後在視窗左邊你就可以看到已經建立好的虛擬機器了。這個時候虛擬機器沒有安裝任何作業系統。你需要更改虛擬機器的設定。滑鼠移動到server-centos 虛擬機器上,右鍵,點選設定。在彈出的對話方塊中,左側選擇網路。右邊會出現四個網絡卡的選項卡。確保只有第一個網絡卡被選中 啟用網路連線。其他的選項如圖所示:

1.png

這裡要注意,因為使用 macvlan,所以網絡卡必須允許混雜模式。如果你在物理機上配置,也得確保你的網絡卡支援混雜模式。為了方便後續安裝軟體,連線方式選擇橋接網絡卡,這樣此虛擬機器就加入了物理機的辦公區域網中。只要辦公環境能上網,這臺虛擬機器就能上網。同時此虛擬機器的IP、網段都是辦公區域網的,辦公區域網內的其他物理機可以ping通或連線此虛擬機器(比如SSH遠端登入)。

設定好網路後,左側欄點選儲存,如下圖:

2.png

選擇 1 框中,沒有碟片選單項。再點選 2 框中的按鈕,在開啟的檔案選擇對話方塊中選擇一開始下載的 CentOS 映象。點選 OK 關閉對話方塊,啟動虛擬機器,進入裝機介面。在裝機介面中,語言選擇中文-簡體中文。
裝機介面如圖:
3.png

軟體選擇,點進去後,選擇 GUI 就行,其他多餘的不用選。

安裝位置,點進去後,預設配置,直接點選上方的完成按鈕就好。

網路和主機名,點選後進入如下頁面:

5.png

右上角,開啟狀態,並點選完成按鈕。

SECURITY POLICY 不需要做任何設定,然後點選開始安裝。接著系統進入下圖:

6.png

安裝提示設定好 ROOT 密碼,以及建立使用者。

等待安裝完成後,進入 CentOS 7 的桌面。在桌面空白處右鍵彈出快捷選單,點選“開啟終端”。

ip addr 命令查到網絡卡名稱,這裡假設網絡卡的名稱是 enp0s3。雖然我在虛擬機器中設定了網絡卡的混雜模式,但是還需要在 CentOS 7 作業系統中開啟網絡卡的混雜模式,命令如下:

ip link set enp0s3 promisc on

為了檢視是否已經開啟混雜模式,用如下命令

[[email protected]]# ip link show enp0s3
2: enp0s3: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 08:00:27:3a:29:5e brd ff:ff:ff:ff:ff:ff

回顯的資訊中有 PROMISC ,表示已經開啟網絡卡的混雜模式。注意,重啟機器後,混雜模式又會變成關閉狀態。

建立 macvlan 模式的 docker 網路,取名為 macnet1:

docker network create -d macvlan --subnet 10.30.1.254/24 --gateway 10.30.1.254 -o parent=enp0s3 macnet1

上面命令的含義解釋一下。 –subnet 表示子網,這裡 24 表示 IPv4 32位地址的前24位,即 10.30.1 字首。 –gateway 是閘道器IP,這裡是辦公環境的閘道器。 parent 表示宿主機的網絡卡名。

建立使用 macnet1 網路的容器:

docker run --network macnet1 --ip=10.30.1.23 --name qu1 -d qst/qstubuntu:v3

這樣在其他機器上,就可以通過 IP 直接訪問容器,比如 SSH 遠端登入。此時容器更像是個虛擬機器。需要注意的是,因為使用了macvlan 宿主機和容器之間無法訪問,這是由於 Linux 的 macvlan 機制決定的。應該沒什麼解決方法。出處在此 https://yq.aliyun.com/articles/192998